package eu.dnetlib.ariadneplus.reader; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import javax.annotation.PostConstruct; import eu.dnetlib.ariadneplus.reader.json.ParseRDFJSON; import eu.dnetlib.ariadneplus.reader.utils.ClassSpec; import eu.dnetlib.ariadneplus.reader.utils.Mappings; import eu.dnetlib.ariadneplus.reader.utils.PropertiesMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; @Service public class ResourceManager { private static final Log log = LogFactory.getLog(ResourceManager.class); @Value("${type.path:undefined}") private String type_path; @Value("${general.classpath:undefined}") private String general_classpath; @Value("${exclude.predicates:[]}") private String exclude_predicates; @Value("${class.map.specifications:undefined}") private String spec; private List not_parsable; private ParseRDFJSON parser; private PropertiesMap propertiesMap; public void setup(String type_path, String general_classpath, String exclude_predicates, String spec) { this.type_path = type_path; this.general_classpath = general_classpath; this.exclude_predicates = exclude_predicates; this.spec = spec; init(); } @PostConstruct public void init(){ Type listType = new TypeToken>(){}.getType(); not_parsable = new Gson().fromJson(exclude_predicates, listType); propertiesMap = new PropertiesMap(); propertiesMap.fill(spec); } private String getFieldValue(Object value){ if (value instanceof LinkedHashMap) return (String)((LinkedHashMap)value).get("value"); return (String)((JSONObject)value).get("value"); } public void manage(ParseRDFJSON parser){ this.parser = parser; } public boolean hasNext(){ return parser.hasNextElement(); } public Object next() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { return manage(parser.getNextElement(),null); } private Object manage(Object entry, String class_name) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { if (class_name == null){ if(entry instanceof LinkedHashMap){ LinkedHashMap tmp = (LinkedHashMap)((JSONArray)((LinkedHashMap)entry).get(type_path)).get(0); class_name = (String)tmp.get("value"); //TODO: Use rdf:type instead of these values that are added statically by the CONSTRUCT queries (that need to be changed as well to include the rdf:type if (class_name.equals("Record") || class_name.equals("Collection")) { class_name = "AriadnePlusEntry"; } } } if (entry == null) { return null; } Class c = Class.forName(general_classpath + class_name); Object class_instance = c.newInstance(); ClassSpec class_spec = propertiesMap.get(class_name); Set keySet; if(entry instanceof LinkedHashMap) keySet = ((LinkedHashMap)entry).keySet(); else keySet = ((JSONObject)entry).keySet(); for(Object predicate: keySet){//predicates in the json if (not_parsable.contains(predicate)) continue; Mappings map = class_spec.get((String)predicate); if (map==null) { continue; } JSONArray values; if(entry instanceof LinkedHashMap) values = (JSONArray)((LinkedHashMap)entry).get(predicate); else values = (JSONArray)((JSONObject)entry).get(predicate); if (!map.hasExternalReference()){ Method setField = c.getMethod("set" + map.getClass_field(), Class.forName(map.getElement_type())); //TODO: the current language seems not to support list of strings if (map.getClass_field().equals("Description") ) { setField.invoke(class_instance, values.stream().map(value -> { return getFieldValue(value); }).collect(Collectors.joining(" \n"))); } else { if(map.getClass_field().equals("OtherId")){ for (Object v : values) { setField.invoke(class_instance, getFieldValue(v)); } } else { setField.invoke(class_instance, getFieldValue(values.get(0))); } } } else{ if(propertiesMap.get(map.getExternal_reference()).getClass_type().equals("prototype")){ List value_list = new ArrayList<>(); for(Object value: values){ value_list.add(manage(ParseRDFJSON.get(getFieldValue(value)), map.getExternal_reference())); } Method setField = c.getMethod("set" + map.getClass_field(),List.class); setField.invoke(class_instance, value_list); } else{ Class ref = Class.forName(general_classpath + map.getExternal_reference()); Method setField = c.getMethod("set" + map.getClass_field(), ref); setField.invoke(class_instance, manage (ParseRDFJSON.get(getFieldValue(values.get(0))),map.getExternal_reference())); } } } return class_instance; } public String getType_path() { return type_path; } public void setType_path(String type_path) { this.type_path = type_path; } public String getGeneral_classpath() { return general_classpath; } public void setGeneral_classpath(String general_classpath) { this.general_classpath = general_classpath; } public String getExclude_predicates() { return exclude_predicates; } public void setExclude_predicates(String exclude_predicates) { this.exclude_predicates = exclude_predicates; } public String getSpec() { return spec; } public void setSpec(String spec) { this.spec = spec; } }