diff --git a/entity-management-common/src/main/java/eu/europeana/entitymanagement/common/config/EntityManagementConfiguration.java b/entity-management-common/src/main/java/eu/europeana/entitymanagement/common/config/EntityManagementConfiguration.java index 419858fd0..5489cf1cd 100644 --- a/entity-management-common/src/main/java/eu/europeana/entitymanagement/common/config/EntityManagementConfiguration.java +++ b/entity-management-common/src/main/java/eu/europeana/entitymanagement/common/config/EntityManagementConfiguration.java @@ -23,7 +23,7 @@ import org.springframework.context.annotation.PropertySources; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import eu.europeana.entitymanagement.definitions.model.CountryMapping; +import eu.europeana.entitymanagement.definitions.model.ZohoLabelUriMapping; /** * Container for all settings that we load from the entitymanagement.properties file and optionally @@ -167,8 +167,12 @@ public class EntityManagementConfiguration implements InitializingBean { @Value("${zoho.country.mapping:null}") private String zohoCountryMappingFilename; - - Map countryMappings = new HashMap<>(); + + @Value("${zoho.role.mapping:null}") + private String zohoRoleMappingFilename; + + Map countryMappings = new HashMap<>(); + Map roleMappings = new HashMap<>(); @Autowired @Qualifier(BEAN_JSON_MAPPER) @@ -186,6 +190,8 @@ public void afterPropertiesSet() throws Exception { } //initialize country mapping initCountryMappings(); + //initialize role mapping + initRoleMappings(); } /** verify properties */ @@ -222,14 +228,27 @@ private void initCountryMappings() throws IOException { assert inputStream != null; try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String contents = reader.lines().collect(Collectors.joining(System.lineSeparator())); - List countryMappingList = emJsonMapper.readValue(contents, new TypeReference>(){}); - for (CountryMapping countryMapping : countryMappingList) { + List countryMappingList = emJsonMapper.readValue(contents, new TypeReference>(){}); + for (ZohoLabelUriMapping countryMapping : countryMappingList) { countryMappings.put(countryMapping.getZohoLabel(), countryMapping); } } } } + private void initRoleMappings() throws IOException { + try (InputStream inputStream = getClass().getResourceAsStream(getZohoRoleMappingFilename())) { + assert inputStream != null; + try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { + String contents = reader.lines().collect(Collectors.joining(System.lineSeparator())); + List roleMappingList = emJsonMapper.readValue(contents, new TypeReference>(){}); + for (ZohoLabelUriMapping roleMapping : roleMappingList) { + roleMappings.put(roleMapping.getZohoLabel(), roleMapping.getEntityUri()); + } + } + } + } + public String getPrSolrUrl() { return prSolrUrl; } @@ -406,7 +425,15 @@ public String getZohoCountryMappingFilename() { return zohoCountryMappingFilename; } - public Map getCountryMappings() { + public Map getCountryMappings() { return countryMappings; } + + public String getZohoRoleMappingFilename() { + return zohoRoleMappingFilename; + } + + public Map getRoleMappings() { + return roleMappings; + } } diff --git a/entity-management-common/src/main/java/eu/europeana/entitymanagement/common/vocabulary/AppConfigConstants.java b/entity-management-common/src/main/java/eu/europeana/entitymanagement/common/vocabulary/AppConfigConstants.java index 5157c34b1..964735b22 100644 --- a/entity-management-common/src/main/java/eu/europeana/entitymanagement/common/vocabulary/AppConfigConstants.java +++ b/entity-management-common/src/main/java/eu/europeana/entitymanagement/common/vocabulary/AppConfigConstants.java @@ -16,6 +16,7 @@ public class AppConfigConstants { public static final String BEAN_MESSAGE_SOURCE = "messageSource"; public static final String BEAN_ENTITY_RECORD_REPO = "emEntityRecordRepo"; + public static final String BEAN_VOCABULARY_REPO = "emVocabularyRepo"; public static final String BEAN_CONCEPT_SCHEME_REPO = "emConceptSchemeRepo"; public static final String BEAN_ZOHO_SYNC_REPO = "emZohoSyncRepo"; public static final String BEAN_ENTITY_RECORD_SERVICE = "emEntityRecordService"; diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/VocabularyFields.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/VocabularyFields.java new file mode 100644 index 000000000..17820921e --- /dev/null +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/VocabularyFields.java @@ -0,0 +1,12 @@ +package eu.europeana.entitymanagement.definitions; + +// Collection field names +public class VocabularyFields { + + private VocabularyFields() { + // private constructor to prevent instantiation + } + + public static final String VOCABULARY_URI = "vocabularyUri"; + +} \ No newline at end of file diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/Organization.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/Organization.java index 02507d39d..2b39e2e1b 100644 --- a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/Organization.java +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/Organization.java @@ -65,7 +65,6 @@ public class Organization extends Entity { private String homepage; private List phone; private List mbox; - private Map> europeanaRole; @Reference(lazy = true) private EntityRecord countryRef; @@ -73,6 +72,12 @@ public class Organization extends Entity { @Transient private Place country; + private List europeanaRoleIds; + @Reference(lazy = true) + private List europeanaRoleRefs; + @Transient + private List europeanaRole; + private Address hasAddress; private List sameAs; private List language; @@ -89,9 +94,11 @@ public Organization(Organization copy) { this.homepage = copy.getHomepage(); if (copy.getPhone() != null) this.phone = new ArrayList<>(copy.getPhone()); if (copy.getMbox() != null) this.mbox = new ArrayList<>(copy.getMbox()); - if (copy.getEuropeanaRole() != null) - this.europeanaRole = new HashMap<>(copy.getEuropeanaRole()); - //because the countryRef is a reference to the object we keep it the same + //because the europeanaRoleRef is a reference to the object we keep it the same (therefore also for europeanaRole) + this.europeanaRole = copy.getEuropeanaRole(); + this.europeanaRoleRefs = copy.getEuropeanaRoleRefs(); + if(copy.getEuropeanaRoleIds()!=null) this.europeanaRoleIds=new ArrayList<>(copy.getEuropeanaRoleIds()); + //because the countryRef is a reference to the object we keep it the same (therefore also for country) this.countryRef=copy.getCountryRef(); this.countryId = copy.getCountryId(); this.country = copy.getCountry(); @@ -121,16 +128,6 @@ public void setAcronym(Map> acronym) { this.acronym = acronym; } - @JsonGetter(EUROPEANA_ROLE) - public Map> getEuropeanaRole() { - return europeanaRole; - } - - @JsonSetter(EUROPEANA_ROLE) - public void setEuropeanaRole(Map> europeanaRole) { - this.europeanaRole = europeanaRole; - } - @JsonGetter(FOAF_PHONE) public List getPhone() { return phone; @@ -250,5 +247,41 @@ public String getCountryId() { public void setCountryId(String countryId) { this.countryId = countryId; } + + @JsonIgnore + public List getEuropeanaRoleIds() { + return europeanaRoleIds; + } + + public void setEuropeanaRoleIds(List europeanaRoleIds) { + this.europeanaRoleIds = europeanaRoleIds; + } + + @JsonIgnore + public List getEuropeanaRoleRefs() { + return europeanaRoleRefs; + } + + public void setEuropeanaRoleRefs(List europeanaRoleRefs) { + this.europeanaRoleRefs = europeanaRoleRefs; + } + + @JsonGetter(EUROPEANA_ROLE) + public List getEuropeanaRole() { + if(europeanaRole==null && europeanaRoleIds!=null && !europeanaRoleIds.isEmpty()) { + europeanaRole=new ArrayList<>(); + for(String roleId : europeanaRoleIds) { + Vocabulary vocab = new Vocabulary(); + vocab.setVocabularyUri(roleId); + europeanaRole.add(vocab); + } + } + return europeanaRole; + } + + @JsonSetter(EUROPEANA_ROLE) + public void setEuropeanaRole(List europeanaRole) { + this.europeanaRole = europeanaRole; + } } diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/Vocabulary.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/Vocabulary.java new file mode 100644 index 000000000..ee32500cc --- /dev/null +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/Vocabulary.java @@ -0,0 +1,108 @@ +package eu.europeana.entitymanagement.definitions.model; + +import static eu.europeana.entitymanagement.vocabulary.WebEntityFields.IN_SCHEME; +import static eu.europeana.entitymanagement.vocabulary.WebEntityFields.PREF_LABEL; +import java.util.Date; +import java.util.List; +import java.util.Map; +import org.bson.types.ObjectId; +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonSetter; +import dev.morphia.annotations.EntityListeners; +import dev.morphia.annotations.Id; +import dev.morphia.annotations.IndexOptions; +import dev.morphia.annotations.Indexed; +import eu.europeana.entitymanagement.utils.VocabularyWatcher; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(value = JsonInclude.Include.NON_EMPTY) +@dev.morphia.annotations.Entity("Vocabulary") +@EntityListeners(VocabularyWatcher.class) +public class Vocabulary { + + private String type = "Vocabulary"; + + @Id @JsonIgnore private ObjectId dbId; + + @Indexed(options = @IndexOptions(unique = true)) + private String vocabularyUri; + + protected List inScheme; + + protected Map prefLabel; + + @JsonIgnore + private Date created; + + @JsonIgnore + private Date modified; + + public Vocabulary() { + } + + public void setDbId(ObjectId dbId_param) { + this.dbId = dbId_param; + } + + public ObjectId getDbId() { + return dbId; + } + + public void setCreated(Date created) { + this.created = created; + } + + public Date getCreated() { + return this.created; + } + + public void setModified(Date modified) { + this.modified = modified; + } + + public Date getModified() { + return this.modified; + } + + @Override + public String toString() { + return String.format("Vocabulary.vocabularyUri: %s", getVocabularyUri()); + } + + @JsonGetter + public String getVocabularyUri() { + return vocabularyUri; + } + + @JsonSetter + public void setVocabularyUri(String vocabularyUri) { + this.vocabularyUri = vocabularyUri; + } + + @JsonGetter(IN_SCHEME) + public List getInScheme() { + return inScheme; + } + + @JsonSetter(IN_SCHEME) + public void setInScheme(List inScheme) { + this.inScheme = inScheme; + } + + @JsonGetter(PREF_LABEL) + public Map getPrefLabel() { + return prefLabel; + } + + @JsonSetter(PREF_LABEL) + public void setPrefLabel(Map prefLabel) { + this.prefLabel = prefLabel; + } + + public String getType() { + return type; + } +} \ No newline at end of file diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/CountryMapping.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/ZohoLabelUriMapping.java similarity index 97% rename from entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/CountryMapping.java rename to entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/ZohoLabelUriMapping.java index d97db542c..8272e115d 100644 --- a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/CountryMapping.java +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/definitions/model/ZohoLabelUriMapping.java @@ -14,7 +14,7 @@ ENTITY_URI, WIKIDATA_URI }) -public class CountryMapping { +public class ZohoLabelUriMapping { private String zohoLabel; private String entityUri; diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/normalization/EntityFieldsCleaner.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/normalization/EntityFieldsCleaner.java index b0d801a91..a5b38276d 100644 --- a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/normalization/EntityFieldsCleaner.java +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/normalization/EntityFieldsCleaner.java @@ -1,6 +1,9 @@ package eu.europeana.entitymanagement.normalization; -import static eu.europeana.entitymanagement.vocabulary.EntityFieldsTypes.*; +import static eu.europeana.entitymanagement.vocabulary.EntityFieldsTypes.FIELD_TYPE_DATE; +import static eu.europeana.entitymanagement.vocabulary.EntityFieldsTypes.FIELD_TYPE_KEYWORD; +import static eu.europeana.entitymanagement.vocabulary.EntityFieldsTypes.FIELD_TYPE_TEXT; +import static eu.europeana.entitymanagement.vocabulary.EntityFieldsTypes.FIELD_TYPE_TEXT_OR_URI; import static eu.europeana.entitymanagement.vocabulary.WebEntityFields.BASE_DATA_EUROPEANA_URI; import static eu.europeana.entitymanagement.vocabulary.WebEntityFields.BEGIN; import static eu.europeana.entitymanagement.vocabulary.WebEntityFields.DATE_OF_BIRTH; @@ -9,14 +12,6 @@ import static eu.europeana.entitymanagement.vocabulary.WebEntityFields.DATE_OF_TERMINATION; import static eu.europeana.entitymanagement.vocabulary.WebEntityFields.END; import static eu.europeana.entitymanagement.vocabulary.WebEntityFields.GENDER; - -import eu.europeana.entitymanagement.definitions.LanguageCodes; -import eu.europeana.entitymanagement.definitions.exceptions.EntityManagementRuntimeException; -import eu.europeana.entitymanagement.definitions.model.ConsolidatedAgent; -import eu.europeana.entitymanagement.definitions.model.Entity; -import eu.europeana.entitymanagement.definitions.model.WebResource; -import eu.europeana.entitymanagement.utils.EntityUtils; -import eu.europeana.entitymanagement.vocabulary.EntityFieldsTypes; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; @@ -35,6 +30,13 @@ import org.apache.commons.lang3.reflect.ConstructorUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import eu.europeana.entitymanagement.definitions.LanguageCodes; +import eu.europeana.entitymanagement.definitions.exceptions.EntityManagementRuntimeException; +import eu.europeana.entitymanagement.definitions.model.ConsolidatedAgent; +import eu.europeana.entitymanagement.definitions.model.Entity; +import eu.europeana.entitymanagement.definitions.model.WebResource; +import eu.europeana.entitymanagement.utils.EntityUtils; +import eu.europeana.entitymanagement.vocabulary.EntityFieldsTypes; public class EntityFieldsCleaner { @@ -89,13 +91,15 @@ public void cleanAndNormalize(Entity entity) { String[] normalized = normalizedList.toArray(new String[0]); entity.setFieldValue(field, normalized); } else if (fieldType.isAssignableFrom(List.class)) { - List fieldValueList = (List) fieldValue; - if (fieldValueList.isEmpty()) { + List fieldValueList = (List) fieldValue; + if(fieldValueList.isEmpty() || !(fieldValueList.get(0) instanceof String)) { continue; } + + List fieldValueListString = (List) fieldValue; // remove spaces from the List fields - List normalizedList = normalizeValues(field.getName(), fieldValueList); + List normalizedList = normalizeValues(field.getName(), fieldValueListString); // if Entity field is supposed to contain a single element, remove all elements // except the diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/utils/VocabularyWatcher.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/utils/VocabularyWatcher.java new file mode 100644 index 000000000..0287f1880 --- /dev/null +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/utils/VocabularyWatcher.java @@ -0,0 +1,22 @@ +package eu.europeana.entitymanagement.utils; + +import java.util.Date; +import dev.morphia.annotations.PrePersist; +import eu.europeana.entitymanagement.definitions.model.Vocabulary; + +/** Watches for Database operations on the Vocabulary collection */ +public class VocabularyWatcher { + + /** + * Invoked by Morphia when creating / updating a Vocabulary. Sets the created/modified time. + * @param record Vocabulary + */ + @PrePersist + void prePersist(Vocabulary vocab) { + Date now = new Date(); + if (vocab.getCreated() == null) { + vocab.setCreated(now); + } + vocab.setModified(now); + } +} \ No newline at end of file diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/vocabulary/EntityFieldsTypes.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/vocabulary/EntityFieldsTypes.java index 15f59620c..dfe9c9557 100644 --- a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/vocabulary/EntityFieldsTypes.java +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/vocabulary/EntityFieldsTypes.java @@ -99,11 +99,14 @@ public enum EntityFieldsTypes { // Organization-specific fields logo(EntityFieldsTypes.FIELD_TYPE_WEB_RESOURCE, false, EntityFieldsTypes.FIELD_CARDINALITY_0_1), + europeanaRoleIds( + EntityFieldsTypes.FIELD_TYPE_URI, false, EntityFieldsTypes.FIELD_CARDINALITY_0_INFINITE), europeanaRole( - EntityFieldsTypes.FIELD_TYPE_KEYWORD, true, EntityFieldsTypes.FIELD_CARDINALITY_0_INFINITE), - country(EntityFieldsTypes.FIELD_TYPE_TEXT, false, EntityFieldsTypes.FIELD_CARDINALITY_0_1), + EntityFieldsTypes.FIELD_TYPE_VOCABULARY, false, EntityFieldsTypes.FIELD_CARDINALITY_0_INFINITE), + europeanaRoleRefs( + EntityFieldsTypes.FIELD_TYPE_VOCABULARY, false, EntityFieldsTypes.FIELD_CARDINALITY_0_INFINITE), countryId(EntityFieldsTypes.FIELD_TYPE_URI, false, EntityFieldsTypes.FIELD_CARDINALITY_0_1), - countryPlace(EntityFieldsTypes.FIELD_TYPE_PLACE, false, EntityFieldsTypes.FIELD_CARDINALITY_0_1), + country(EntityFieldsTypes.FIELD_TYPE_PLACE, false, EntityFieldsTypes.FIELD_CARDINALITY_0_1), countryRef(EntityFieldsTypes.FIELD_TYPE_ENTITY_RECORD, false, EntityFieldsTypes.FIELD_CARDINALITY_0_1), homepage(EntityFieldsTypes.FIELD_TYPE_URI, false, EntityFieldsTypes.FIELD_CARDINALITY_0_1), phone( @@ -142,6 +145,7 @@ public enum EntityFieldsTypes { public static final String FIELD_TYPE_ADDRESS = "Address"; public static final String FIELD_TYPE_PLACE = "Place"; public static final String FIELD_TYPE_ENTITY_RECORD = "EntityRecord"; + public static final String FIELD_TYPE_VOCABULARY = "Vocabulary"; public static final String FIELD_CARDINALITY_1_1 = "1..1"; public static final String FIELD_CARDINALITY_0_1 = "0..1"; diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/vocabulary/OrganizationSolrFields.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/vocabulary/OrganizationSolrFields.java index f286ec96c..241aeabdb 100644 --- a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/vocabulary/OrganizationSolrFields.java +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/vocabulary/OrganizationSolrFields.java @@ -15,7 +15,6 @@ public interface OrganizationSolrFields extends EntitySolrFields { public static final String FOAF_PHONE = "foaf_phone"; public static final String FOAF_MBOX = "foaf_mbox"; public static final String EUROPEANA_ROLE = "europeanaRole"; - public static final String EUROPEANA_ROLE_ALL = EUROPEANA_ROLE + EXTENSION_ALL; public static final String COUNTRY = "country"; public static final String VCARD_HAS_ADDRESS = "vcard_hasAddress.1"; public static final String VCARD_STREET_ADDRESS = "vcard_streetAddress.1"; diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlBaseEntityImpl.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlBaseEntityImpl.java index a30311914..3b707e1a3 100644 --- a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlBaseEntityImpl.java +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlBaseEntityImpl.java @@ -102,6 +102,10 @@ public XmlWebResourceWrapper getDepiction() { public List getPrefLabel() { return this.prefLabel; } + + public void setPrefLabel(List prefLabel) { + this.prefLabel=prefLabel; + } public List getAltLabel() { return this.altLabel; diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlConceptImpl.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlConceptImpl.java index 5728a2284..bb66a3609 100644 --- a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlConceptImpl.java +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlConceptImpl.java @@ -20,10 +20,6 @@ import static eu.europeana.entitymanagement.web.xml.model.XmlConstants.RELATED; import static eu.europeana.entitymanagement.web.xml.model.XmlConstants.RELATED_MATCH; import static eu.europeana.entitymanagement.web.xml.model.XmlConstants.XML_CONCEPT; - -import eu.europeana.entitymanagement.definitions.exceptions.EntityModelCreationException; -import eu.europeana.entitymanagement.definitions.model.Concept; -import eu.europeana.entitymanagement.vocabulary.EntityTypes; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; @@ -31,8 +27,11 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import eu.europeana.entitymanagement.definitions.exceptions.EntityModelCreationException; +import eu.europeana.entitymanagement.definitions.model.Concept; +import eu.europeana.entitymanagement.vocabulary.EntityTypes; -@XmlRootElement(name = XML_CONCEPT) +@XmlRootElement(namespace = NAMESPACE_SKOS, name = XML_CONCEPT) @XmlAccessorType(XmlAccessType.FIELD) @XmlType( propOrder = { @@ -172,6 +171,10 @@ public List getNote() { public List getInScheme() { return this.inScheme; } + + public void setInScheme(List inScheme) { + this.inScheme=inScheme; + } @Override protected EntityTypes getTypeEnum() { diff --git a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlOrganizationImpl.java b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlOrganizationImpl.java index d6605d967..8bef05ad7 100644 --- a/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlOrganizationImpl.java +++ b/entity-management-definitions/src/main/java/eu/europeana/entitymanagement/web/xml/model/XmlOrganizationImpl.java @@ -34,6 +34,7 @@ import org.apache.commons.collections.CollectionUtils; import eu.europeana.entitymanagement.definitions.exceptions.EntityModelCreationException; import eu.europeana.entitymanagement.definitions.model.Organization; +import eu.europeana.entitymanagement.definitions.model.Vocabulary; import eu.europeana.entitymanagement.vocabulary.EntityTypes; @XmlRootElement(namespace = NAMESPACE_EDM, name = XML_ORGANIZATION) @@ -75,7 +76,7 @@ public class XmlOrganizationImpl extends XmlBaseEntityImpl { private XmlWebResourceWrapper logo; @XmlElement(namespace = NAMESPACE_EDM, name = XML_EUROPEANA_ROLE) - private List europeanaRole = new ArrayList<>(); + private List europeanaRole = new ArrayList<>(); @XmlElement(namespace = NAMESPACE_EDM, name = XML_COUNTRY) private XmlPlaceImpl country; @@ -106,8 +107,19 @@ public XmlOrganizationImpl(Organization organization) { if (organization.getLogo() != null) { this.logo = XmlWebResourceWrapper.fromWebResource(organization.getLogo()); } - this.europeanaRole = - RdfXmlUtils.convertToXmlMultilingualString(organization.getEuropeanaRole()); + //set the europeanaRole + List orgRole=organization.getEuropeanaRole(); + if(orgRole!=null && !orgRole.isEmpty()) { + List orgXmlRole= new ArrayList<>(); + for(Vocabulary vocab : orgRole) { + XmlConceptImpl xmlConcept = new XmlConceptImpl(); + xmlConcept.setAbout(vocab.getVocabularyUri()); + xmlConcept.setPrefLabel(RdfXmlUtils.convertMapToXmlMultilingualString(vocab.getPrefLabel())); + xmlConcept.setInScheme(RdfXmlUtils.convertToRdfResource(vocab.getInScheme())); + orgXmlRole.add(xmlConcept); + } + this.europeanaRole=orgXmlRole; + } this.country = new XmlPlaceImpl(organization.getCountry()); @@ -137,7 +149,21 @@ public Organization toEntityModel() throws EntityModelCreationException { entity.setAcronym(RdfXmlUtils.toLanguageMapList(getAcronym())); entity.setDescription(RdfXmlUtils.toLanguageMap(getDescription())); entity.setLogo(XmlWebResourceWrapper.toWebResource(getLogo())); - entity.setEuropeanaRole(RdfXmlUtils.toLanguageMapList(getEuropeanaRole())); + //set europeanaRole + if(getEuropeanaRole()!=null && !getEuropeanaRole().isEmpty()) { + List roleIds=new ArrayList<>(); + List role=new ArrayList<>(); + for(XmlConceptImpl xmlConcept : getEuropeanaRole()) { + Vocabulary vocab=new Vocabulary(); + vocab.setVocabularyUri(xmlConcept.getAbout()); + vocab.setPrefLabel(RdfXmlUtils.toLanguageMap(xmlConcept.getPrefLabel())); + vocab.setInScheme(RdfXmlUtils.toStringList(xmlConcept.getInScheme())); + role.add(vocab); + roleIds.add(xmlConcept.getAbout()); + } + entity.setEuropeanaRole(role); + entity.setEuropeanaRoleIds(roleIds); + } if(getCountry() != null) { //the country is not saved in the database @@ -178,7 +204,7 @@ public XmlWebResourceWrapper getLogo() { return logo; } - public List getEuropeanaRole() { + public List getEuropeanaRole() { return europeanaRole; } diff --git a/entity-management-mongo/src/main/java/eu/europeana/entitymanagement/mongo/repository/VocabularyRepository.java b/entity-management-mongo/src/main/java/eu/europeana/entitymanagement/mongo/repository/VocabularyRepository.java new file mode 100644 index 000000000..0e35213c5 --- /dev/null +++ b/entity-management-mongo/src/main/java/eu/europeana/entitymanagement/mongo/repository/VocabularyRepository.java @@ -0,0 +1,41 @@ +package eu.europeana.entitymanagement.mongo.repository; + +import static dev.morphia.query.experimental.filters.Filters.in; +import static eu.europeana.entitymanagement.definitions.VocabularyFields.VOCABULARY_URI; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Resource; +import org.springframework.stereotype.Repository; +import dev.morphia.Datastore; +import dev.morphia.query.experimental.filters.Filter; +import eu.europeana.entitymanagement.common.vocabulary.AppConfigConstants; +import eu.europeana.entitymanagement.definitions.model.Vocabulary; + +/** Repository for retrieving the Vocabulary objects. */ +@Repository(AppConfigConstants.BEAN_VOCABULARY_REPO) +public class VocabularyRepository { + + @Resource(name = AppConfigConstants.BEAN_EM_DATA_STORE) + Datastore datastore; + + public List findByVocabularyUris(List vocabularyUris) { + List filters = new ArrayList<>(); + filters.add(in(VOCABULARY_URI, vocabularyUris)); + return datastore.find(Vocabulary.class) + .filter(filters.toArray(Filter[]::new)) + .iterator() + .toList(); + } + + public Vocabulary save(Vocabulary vocab) { + return datastore.save(vocab); + } + + public List saveBulk(List vocabs) { + return datastore.save(vocabs); + } + + public void dropCollection() { + datastore.getMapper().getCollection(Vocabulary.class).drop(); + } +} \ No newline at end of file diff --git a/entity-management-solr/src/main/java/eu/europeana/entitymanagement/solr/model/SolrOrganization.java b/entity-management-solr/src/main/java/eu/europeana/entitymanagement/solr/model/SolrOrganization.java index 1e98d8a06..97b6e1def 100644 --- a/entity-management-solr/src/main/java/eu/europeana/entitymanagement/solr/model/SolrOrganization.java +++ b/entity-management-solr/src/main/java/eu/europeana/entitymanagement/solr/model/SolrOrganization.java @@ -36,8 +36,8 @@ public class SolrOrganization extends SolrEntity { @Field(OrganizationSolrFields.FOAF_MBOX) private List mbox; - @Field(OrganizationSolrFields.EUROPEANA_ROLE_ALL) - private Map> europeanaRole; + @Field(OrganizationSolrFields.EUROPEANA_ROLE) + private List europeanaRole; @Field(OrganizationSolrFields.COUNTRY) private String country; @@ -81,7 +81,8 @@ public SolrOrganization(Organization organization) { this.homepage = organization.getHomepage(); this.phone = organization.getPhone(); if (organization.getMbox() != null) this.mbox = new ArrayList<>(organization.getMbox()); - setEuropeanaRole(organization.getEuropeanaRole()); + + if(organization.getEuropeanaRoleIds()!=null) this.europeanaRole=new ArrayList<>(organization.getEuropeanaRoleIds()); this.country=organization.getCountryId(); @@ -119,16 +120,6 @@ private void setAcronym(Map> acronym) { acronym)); } } - - private void setEuropeanaRole(Map> europeanaRole) { - if (MapUtils.isNotEmpty(europeanaRole)) { - this.europeanaRole = - new HashMap<>( - SolrUtils.normalizeStringListMapByAddingPrefix( - OrganizationSolrFields.EUROPEANA_ROLE + EntitySolrFields.DYNAMIC_FIELD_SEPARATOR, - europeanaRole)); - } - } public Map getDescription() { return description; @@ -154,7 +145,7 @@ public List getMbox() { return mbox; } - public Map> getEuropeanaRole() { + public List getEuropeanaRole() { return europeanaRole; } diff --git a/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/AbstractIntegrationTest.java b/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/AbstractIntegrationTest.java index 97d192d17..f33ed6119 100644 --- a/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/AbstractIntegrationTest.java +++ b/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/AbstractIntegrationTest.java @@ -152,6 +152,7 @@ static void setProperties(DynamicPropertyRegistry registry) { registry.add("zoho.generate.organization.europeanaid", () -> true); registry.add("zoho.country.mapping", () -> "/zoho_country_mapping_test.json"); + registry.add("zoho.role.mapping", () -> "/zoho_role_mapping_test.json"); // could be used to fix eclipse issues registry.add("scmBranch", () -> "dev"); diff --git a/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/service/DereferenceServiceIT.java b/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/service/DereferenceServiceIT.java index 25e532607..f0cd7cd56 100644 --- a/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/service/DereferenceServiceIT.java +++ b/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/service/DereferenceServiceIT.java @@ -134,7 +134,8 @@ public void zohoOrganizationDereferenceLabelsTest() throws Exception { Organization org = ZohoOrganizationConverter.convertToOrganizationEntity( record, zohoConfiguration.getZohoBaseUrl(), - emConfig.getCountryMappings()); + emConfig.getCountryMappings(), + emConfig.getRoleMappings()); Assertions.assertEquals(2, org.getPrefLabel().size()); Assertions.assertEquals(1, org.getAltLabel().size()); diff --git a/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/web/BaseWebControllerTest.java b/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/web/BaseWebControllerTest.java index f2136ba86..0476b51d4 100644 --- a/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/web/BaseWebControllerTest.java +++ b/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/web/BaseWebControllerTest.java @@ -30,6 +30,7 @@ import eu.europeana.entitymanagement.definitions.model.EntityRecord; import eu.europeana.entitymanagement.definitions.model.Organization; import eu.europeana.entitymanagement.exception.ingestion.EntityUpdateException; +import eu.europeana.entitymanagement.mongo.repository.VocabularyRepository; import eu.europeana.entitymanagement.solr.exception.SolrServiceException; import eu.europeana.entitymanagement.solr.service.SolrService; import eu.europeana.entitymanagement.testutils.IntegrationTestUtils; @@ -53,6 +54,8 @@ abstract class BaseWebControllerTest extends AbstractIntegrationTest { protected SolrService emSolrService; @Autowired private WebApplicationContext webApplicationContext; + + @Autowired protected VocabularyRepository vocabRepository; @BeforeEach protected void setup() throws Exception { @@ -176,7 +179,8 @@ protected EntityRecord createOrganization(String europeanaProxyEntityStr, Record ZohoOrganizationConverter.convertToOrganizationEntity( zohoRecord, zohoConfiguration.getZohoBaseUrl(), - emConfig.getCountryMappings()); + emConfig.getCountryMappings(), + emConfig.getRoleMappings()); EntityRecord savedRecord = entityRecordService.createEntityFromRequest( europeanaProxyEntity, zohoOrganization, dataSource, null); diff --git a/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/web/EntityRetrievalIT.java b/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/web/EntityRetrievalIT.java index ccf69eb6a..411df4cd7 100644 --- a/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/web/EntityRetrievalIT.java +++ b/entity-management-tests/src/integration-test/java/eu/europeana/entitymanagement/web/EntityRetrievalIT.java @@ -14,6 +14,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath; +import java.util.List; import java.util.Map; import java.util.Optional; import org.hamcrest.Matchers; @@ -28,6 +29,7 @@ import eu.europeana.entitymanagement.batch.service.FailedTaskService; import eu.europeana.entitymanagement.definitions.batch.model.ScheduledUpdateType; import eu.europeana.entitymanagement.definitions.model.EntityRecord; +import eu.europeana.entitymanagement.definitions.model.Vocabulary; import eu.europeana.entitymanagement.testutils.IntegrationTestUtils; import eu.europeana.entitymanagement.vocabulary.EntityTypes; import eu.europeana.entitymanagement.vocabulary.FailedTaskJsonFields; @@ -490,12 +492,19 @@ public void retrievePlaceExternalSchemaOrgShouldBeSuccessful() throws Exception } @Test - public void retrieveOrganizationJsonExternalWithCountryDereference() throws Exception { + public void retrieveOrganizationJsonExternalWithCountryAndRoleDereference() throws Exception { //1. create a place "Sweden" to be used to dereference zoho country for the zoho GFM org String europeanaMetadata = loadFile(IntegrationTestUtils.PLACE_REGISTER_SWEDEN_JSON); String metisResponse = loadFile(IntegrationTestUtils.PLACE_SWEDEN_XML); createEntity(europeanaMetadata, metisResponse, IntegrationTestUtils.PLACE_SWEDEN_URI); + //2. create a vocabulary for the europeanaRole + Vocabulary vocab = new Vocabulary(); + vocab.setVocabularyUri("http://data.europeana.eu/vocabulary/role/ProvidingInstitution"); + vocab.setInScheme(List.of("http://data.europeana.eu/vocabulary/role")); + vocab.setPrefLabel(Map.of("en", "Providing Institution")); + vocabRepository.save(vocab); + // //forcefully change the country mapping uri to the right one // List countryMap= entityRecordService.getCountryMapping(); // for(CountryMapping cm : countryMap) { @@ -504,7 +513,7 @@ public void retrieveOrganizationJsonExternalWithCountryDereference() throws Exce // } // } - //2. register zoho GFM org + //3. register zoho GFM org europeanaMetadata = loadFile(IntegrationTestUtils.ORGANIZATION_REGISTER_GFM_ZOHO_JSON); Optional zohoRecord = IntegrationTestUtils.getZohoOrganizationRecord( @@ -523,7 +532,8 @@ public void retrieveOrganizationJsonExternalWithCountryDereference() throws Exce .andExpect(jsonPath("$.id", is(entityId))) .andExpect(jsonPath("$.type", is(EntityTypes.Organization.getEntityType()))) .andExpect(jsonPath("$.sameAs").isNotEmpty()) - .andExpect(jsonPath("$.country.prefLabel.en", is("Sweden"))); + .andExpect(jsonPath("$.country.prefLabel.en", is("Sweden"))) + .andExpect(jsonPath("$.europeanaRole[0].prefLabel.en", is("Providing Institution"))); } @Test diff --git a/entity-management-tests/src/integration-test/resources/solr-docker/conf/schema.xml b/entity-management-tests/src/integration-test/resources/solr-docker/conf/schema.xml index e7b4243a6..8d83e5388 100644 --- a/entity-management-tests/src/integration-test/resources/solr-docker/conf/schema.xml +++ b/entity-management-tests/src/integration-test/resources/solr-docker/conf/schema.xml @@ -485,8 +485,10 @@ - + + @@ -571,7 +573,7 @@ dest="text.*" /> - + @@ -585,7 +587,7 @@ dest="text" /> - + diff --git a/entity-management-tests/src/integration-test/resources/zoho_role_mapping_test.json b/entity-management-tests/src/integration-test/resources/zoho_role_mapping_test.json new file mode 100644 index 000000000..10a5602c7 --- /dev/null +++ b/entity-management-tests/src/integration-test/resources/zoho_role_mapping_test.json @@ -0,0 +1,6 @@ +[ + { + "Zoho Label": "providing institution", + "Entity URI": "http://data.europeana.eu/vocabulary/role/ProvidingInstitution" + } +] diff --git a/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/MetisDereferenceUtils.java b/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/MetisDereferenceUtils.java index b04307ad2..60b0a8c98 100644 --- a/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/MetisDereferenceUtils.java +++ b/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/MetisDereferenceUtils.java @@ -1,13 +1,14 @@ package eu.europeana.entitymanagement.web; -import eu.europeana.api.commons.error.EuropeanaApiException; -import eu.europeana.entitymanagement.exception.DatasourceDereferenceException; -import eu.europeana.entitymanagement.web.xml.model.XmlBaseEntityImpl; -import eu.europeana.entitymanagement.web.xml.model.metis.EnrichmentResultList; import java.io.StringReader; +import java.util.List; import java.util.Optional; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; +import eu.europeana.api.commons.error.EuropeanaApiException; +import eu.europeana.entitymanagement.exception.DatasourceDereferenceException; +import eu.europeana.entitymanagement.web.xml.model.XmlBaseEntityImpl; +import eu.europeana.entitymanagement.web.xml.model.metis.EnrichmentResultList; public class MetisDereferenceUtils { @@ -59,4 +60,34 @@ public static XmlBaseEntityImpl parseMetisResponse( return entityOptional.get(); } + + public static List> parseMetisResponseMany( + Unmarshaller unmarshaller, String metisResponseBody) throws EuropeanaApiException { + EnrichmentResultList derefResult; + + try { + derefResult = + (EnrichmentResultList) unmarshaller.unmarshal(new StringReader(metisResponseBody)); + } catch (JAXBException | RuntimeException e) { + throw new DatasourceDereferenceException( + String.format( + "Error while deserializing metis dereference response %s: ", metisResponseBody), + e); + } + + if (derefResult == null + || derefResult.getEnrichmentBaseResultWrapperList().isEmpty() + || derefResult + .getEnrichmentBaseResultWrapperList() + .get(0) + .getEnrichmentBaseList() + .isEmpty()) { + // Metis returns an empty XML response if de-referencing is unsuccessful, + // instead of throwing an error + return null; + } + + return derefResult.getEnrichmentBaseResultWrapperList().get(0).getEnrichmentBaseList(); + + } } diff --git a/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/service/BaseZohoAccess.java b/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/service/BaseZohoAccess.java index ba6783a4f..8dd9aa028 100644 --- a/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/service/BaseZohoAccess.java +++ b/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/service/BaseZohoAccess.java @@ -326,7 +326,7 @@ List performEntityRegistration(SortedSet createOperations, Zo */ private void performEntityRegistration(Operation operation, ZohoSyncReport zohoSyncReport, List entitiesToUpdate) { Organization zohoOrganization = - ZohoOrganizationConverter.convertToOrganizationEntity(operation.getZohoRecord(), zohoConfiguration.getZohoBaseUrl(), emConfiguration.getCountryMappings()); + ZohoOrganizationConverter.convertToOrganizationEntity(operation.getZohoRecord(), zohoConfiguration.getZohoBaseUrl(), emConfiguration.getCountryMappings(), emConfiguration.getRoleMappings()); try { List existingEntities = diff --git a/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/service/EntityRecordService.java b/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/service/EntityRecordService.java index e21191c3e..c0f1d9f66 100644 --- a/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/service/EntityRecordService.java +++ b/entity-management-web/src/main/java/eu/europeana/entitymanagement/web/service/EntityRecordService.java @@ -47,6 +47,7 @@ import eu.europeana.entitymanagement.definitions.model.Organization; import eu.europeana.entitymanagement.definitions.model.Place; import eu.europeana.entitymanagement.definitions.model.TimeSpan; +import eu.europeana.entitymanagement.definitions.model.Vocabulary; import eu.europeana.entitymanagement.definitions.web.EntityIdDisabledStatus; import eu.europeana.entitymanagement.exception.EntityAlreadyExistsException; import eu.europeana.entitymanagement.exception.EntityCreationException; @@ -57,6 +58,7 @@ import eu.europeana.entitymanagement.exception.MultipleChoicesException; import eu.europeana.entitymanagement.exception.ingestion.EntityUpdateException; import eu.europeana.entitymanagement.mongo.repository.EntityRecordRepository; +import eu.europeana.entitymanagement.mongo.repository.VocabularyRepository; import eu.europeana.entitymanagement.solr.exception.SolrServiceException; import eu.europeana.entitymanagement.solr.service.SolrService; import eu.europeana.entitymanagement.utils.EMCollectionUtils; @@ -79,6 +81,8 @@ public class EntityRecordService { private final EntityRecordRepository entityRecordRepository; + + private final VocabularyRepository vocabRepository; final EntityManagementConfiguration emConfiguration; @@ -94,10 +98,11 @@ public class EntityRecordService { private static final Set ignoredMergeFields = Set.of(WebEntityFields.TYPE); @Autowired - public EntityRecordService(EntityRecordRepository entityRecordRepository, + public EntityRecordService(EntityRecordRepository entityRecordRepository, VocabularyRepository vocabRepository, EntityManagementConfiguration emConfiguration, ZohoConfiguration zohoConfiguration, DataSources datasources, SolrService solrService) throws IOException { this.entityRecordRepository = entityRecordRepository; + this.vocabRepository=vocabRepository; this.emConfiguration = emConfiguration; this.zohoConfiguration = zohoConfiguration; this.datasources = datasources; @@ -160,7 +165,7 @@ void dereferenceLinkedEntities(EntityRecord entityRecord) { } private void dereferenceLinkedEntities(Organization org) { - // in case of dereference profile + //dereference country if (org.getCountryId() != null) { EntityRecord countryRecord = entityRecordRepository.findByEntityId(org.getCountryId(), true); if (countryRecord != null) { @@ -169,6 +174,10 @@ private void dereferenceLinkedEntities(Organization org) { org.setCountry(country); } } + //dereference role + if(org.getEuropeanaRoleIds()!=null && !org.getEuropeanaRoleIds().isEmpty()) { + org.setEuropeanaRole(vocabRepository.findByVocabularyUris(org.getEuropeanaRoleIds())); + } } /** @@ -1279,6 +1288,7 @@ && isStringOrPrimitive(mapFirstValue.getClass())) { public void dropRepository() { this.entityRecordRepository.dropCollection(); + this.vocabRepository.dropCollection(); } /** @@ -1462,7 +1472,7 @@ void updateEuropeanaIDFieldInZoho(String zohoOrganizationUrl, String europeanaId public void processReferenceFields(Entity entity) { if (EntityTypes.isOrganization(entity.getType())) { Organization org = (Organization) entity; - + //country reference if (StringUtils.isNotEmpty(org.getCountryId())) { EntityRecord orgCountry = entityRecordRepository.findByEntityId(org.getCountryId()); if (orgCountry == null) { @@ -1473,6 +1483,17 @@ public void processReferenceFields(Entity entity) { org.setCountryRef(orgCountry); } } + //role reference + if(org.getEuropeanaRoleIds()!=null && !org.getEuropeanaRoleIds().isEmpty()) { + List vocabs=vocabRepository.findByVocabularyUris(org.getEuropeanaRoleIds()); + if (vocabs.isEmpty()) { + logger.info( + "No vocabularies with the uris: {} were found in the database. Cannot assign role reference to organization with id {}", + org.getEuropeanaRoleIds(), org.getEntityId()); + } else { + org.setEuropeanaRoleRefs(vocabs); + } + } } } } diff --git a/entity-management-web/src/main/resources/entitymanagement.properties b/entity-management-web/src/main/resources/entitymanagement.properties index 7938774ae..a21f91cfe 100644 --- a/entity-management-web/src/main/resources/entitymanagement.properties +++ b/entity-management-web/src/main/resources/entitymanagement.properties @@ -76,4 +76,5 @@ zoho.sync.register.deprecated = false #disable generation of entity ids #zoho.generate.organization.europeanaid=: false -zoho.country.mapping=/zoho_country_mapping.json \ No newline at end of file +zoho.country.mapping=/zoho_country_mapping.json +zoho.role.mapping=/zoho_role_mapping.json \ No newline at end of file diff --git a/entity-management-web/src/main/resources/entitymanagement.user.properties.template b/entity-management-web/src/main/resources/entitymanagement.user.properties.template index 4b2dbaacd..15c8a4fe3 100644 --- a/entity-management-web/src/main/resources/entitymanagement.user.properties.template +++ b/entity-management-web/src/main/resources/entitymanagement.user.properties.template @@ -48,4 +48,5 @@ europeana.searchapi.urlPrefix=https:///record/v2/search.json?wskey #enable/disable generation of entity ids for organizations (should be enabled only in productive environment) #zoho.generate.organization.europeanaid=false -zoho.country.mapping= \ No newline at end of file +zoho.country.mapping= +zoho.role.mapping= \ No newline at end of file diff --git a/entity-management-web/src/main/resources/zoho_role_mapping.json b/entity-management-web/src/main/resources/zoho_role_mapping.json new file mode 100644 index 000000000..2e88e0d62 --- /dev/null +++ b/entity-management-web/src/main/resources/zoho_role_mapping.json @@ -0,0 +1,18 @@ +[ + { + "Zoho Label": "providing institution", + "Entity URI": "http://data.europeana.eu/vocabulary/role/ProvidingInstitution" + }, + { + "Zoho Label": "aggregator", + "Entity URI": "http://data.europeana.eu/vocabulary/role/Aggregator" + }, + { + "Zoho Label": "accredited aggregator", + "Entity URI": "http://data.europeana.eu/vocabulary/role/AccreditedAggregator" + }, + { + "Zoho Label": "potential providing institution", + "Entity URI": "http://data.europeana.eu/vocabulary/role/ProvidingInstitution" + } +] diff --git a/entity-management-web/src/test/java/eu/europeana/entitymanagement/web/UtilityTests.java b/entity-management-web/src/test/java/eu/europeana/entitymanagement/web/UtilityTests.java index 6a56a16ff..893be8f31 100644 --- a/entity-management-web/src/test/java/eu/europeana/entitymanagement/web/UtilityTests.java +++ b/entity-management-web/src/test/java/eu/europeana/entitymanagement/web/UtilityTests.java @@ -2,16 +2,23 @@ import static eu.europeana.entitymanagement.solr.SolrUtils.createSolrEntity; import java.util.List; +import javax.xml.bind.JAXBContext; import org.junit.jupiter.api.Disabled; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import eu.europeana.entitymanagement.config.AppConfig; +import eu.europeana.entitymanagement.definitions.model.Concept; import eu.europeana.entitymanagement.definitions.model.EntityRecord; +import eu.europeana.entitymanagement.definitions.model.Vocabulary; import eu.europeana.entitymanagement.exception.ingestion.EntityUpdateException; import eu.europeana.entitymanagement.mongo.repository.EntityRecordRepository; +import eu.europeana.entitymanagement.mongo.repository.VocabularyRepository; import eu.europeana.entitymanagement.solr.exception.SolrServiceException; import eu.europeana.entitymanagement.solr.service.SolrService; +import eu.europeana.entitymanagement.testutils.UnitTestUtils; +import eu.europeana.entitymanagement.web.xml.model.XmlBaseEntityImpl; +import eu.europeana.entitymanagement.web.xml.model.XmlConceptImpl; @SpringBootTest @Disabled("Excluded from automated runs") @@ -23,6 +30,11 @@ public class UtilityTests { @Autowired private EntityRecordRepository entityRecordRepository; + + @Autowired + VocabularyRepository vocabularyRepo; + + @Autowired protected JAXBContext jaxbContext; /** * This test can be used to reindex the local/other solr from mongo, when the schema fields change. @@ -40,5 +52,20 @@ public void reindexSolrFromMongo() throws EntityUpdateException { } } } + + //@Test + public void saveVocabulariesToMongo() throws Exception { + List> xmlEntities = MetisDereferenceUtils.parseMetisResponseMany( + jaxbContext.createUnmarshaller(), UnitTestUtils.loadFile("/metis-deref-unittest/roles.xml")); + for(XmlBaseEntityImpl xmlEntity : xmlEntities) { + XmlConceptImpl xmlConcept = (XmlConceptImpl) xmlEntity; + Concept concept = xmlConcept.toEntityModel(); + Vocabulary vocab = new Vocabulary(); + vocab.setVocabularyUri(concept.getEntityId()); + vocab.setInScheme(concept.getInScheme()); + vocab.setPrefLabel(concept.getPrefLabel()); + vocabularyRepo.save(vocab); + } + } } diff --git a/entity-management-web/src/test/resources/metis-deref-unittest/roles.xml b/entity-management-web/src/test/resources/metis-deref-unittest/roles.xml new file mode 100644 index 000000000..509bab698 --- /dev/null +++ b/entity-management-web/src/test/resources/metis-deref-unittest/roles.xml @@ -0,0 +1,30 @@ + + + + + Providing Institution + + + + + Aggregator + + + + + Accredited Aggregator + + + + \ No newline at end of file diff --git a/entity-management-web/src/test/resources/zoho_role_mapping.json b/entity-management-web/src/test/resources/zoho_role_mapping.json new file mode 100644 index 000000000..da1a058a9 --- /dev/null +++ b/entity-management-web/src/test/resources/zoho_role_mapping.json @@ -0,0 +1,4 @@ +[ + { + } +] diff --git a/entity-management-zoho/src/main/java/eu/europeana/entitymanagement/zoho/organization/ZohoDereferenceService.java b/entity-management-zoho/src/main/java/eu/europeana/entitymanagement/zoho/organization/ZohoDereferenceService.java index 2208d30e2..fa926f4ac 100644 --- a/entity-management-zoho/src/main/java/eu/europeana/entitymanagement/zoho/organization/ZohoDereferenceService.java +++ b/entity-management-zoho/src/main/java/eu/europeana/entitymanagement/zoho/organization/ZohoDereferenceService.java @@ -8,10 +8,8 @@ import org.springframework.stereotype.Service; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.Gson; import com.zoho.crm.api.record.Record; import eu.europeana.entitymanagement.common.config.EntityManagementConfiguration; import eu.europeana.entitymanagement.definitions.model.Entity; @@ -42,7 +40,8 @@ public Optional dereferenceEntityById(@NonNull String id) throws Excepti ZohoOrganizationConverter.convertToOrganizationEntity( zohoOrganization.get(), zohoConfiguration.getZohoBaseUrl(), - emConfig.getCountryMappings())); + emConfig.getCountryMappings(), + emConfig.getRoleMappings())); } else { return Optional.empty(); } diff --git a/entity-management-zoho/src/main/java/eu/europeana/entitymanagement/zoho/organization/ZohoOrganizationConverter.java b/entity-management-zoho/src/main/java/eu/europeana/entitymanagement/zoho/organization/ZohoOrganizationConverter.java index d2c535d74..b16c99c3f 100644 --- a/entity-management-zoho/src/main/java/eu/europeana/entitymanagement/zoho/organization/ZohoOrganizationConverter.java +++ b/entity-management-zoho/src/main/java/eu/europeana/entitymanagement/zoho/organization/ZohoOrganizationConverter.java @@ -6,7 +6,6 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; @@ -15,9 +14,9 @@ import com.zoho.crm.api.record.Record; import com.zoho.crm.api.users.User; import eu.europeana.entitymanagement.definitions.model.Address; -import eu.europeana.entitymanagement.definitions.model.CountryMapping; import eu.europeana.entitymanagement.definitions.model.Organization; import eu.europeana.entitymanagement.definitions.model.WebResource; +import eu.europeana.entitymanagement.definitions.model.ZohoLabelUriMapping; import eu.europeana.entitymanagement.utils.EntityUtils; import eu.europeana.entitymanagement.zoho.utils.ZohoConstants; import eu.europeana.entitymanagement.zoho.utils.ZohoUtils; @@ -28,7 +27,8 @@ public class ZohoOrganizationConverter { private static final String POSITION_SEPARATOR = "_"; - public static Organization convertToOrganizationEntity(Record zohoRecord, String zohoBaseUrl, @NonNull final Map countryMappings) { + public static Organization convertToOrganizationEntity(Record zohoRecord, String zohoBaseUrl, @NonNull final Map countryMappings, + @NonNull final Map roleMappings) { Organization org = new Organization(); Long zohoId = zohoRecord.getId(); org.setAbout(ZohoUtils.buildZohoOrganizationId(zohoBaseUrl, zohoRecord.getId())); @@ -51,12 +51,19 @@ public static Organization convertToOrganizationEntity(Record zohoRecord, String String logoFieldName = ZohoConstants.LOGO_LINK_TO_WIKIMEDIACOMMONS_FIELD; org.setLogo(buildWebResource(zohoRecord, logoFieldName)); org.setHomepage(getStringFieldValue(zohoRecord, ZohoConstants.WEBSITE_FIELD)); - List organizationRoleStringList = + + List orgRoleLabels = ZohoUtils.stringListSupplier(zohoRecord.getKeyValue(ZohoConstants.ORGANIZATION_ROLE_FIELD)); - if (!organizationRoleStringList.isEmpty()) { - org.setEuropeanaRole( - ZohoUtils.createLanguageMapOfStringList( - Locale.ENGLISH.getLanguage(), organizationRoleStringList)); + if (!orgRoleLabels.isEmpty()) { + List orgRoleIds = new ArrayList<>(); + for(String roleLabel : orgRoleLabels) { + if(roleMappings.containsKey(roleLabel.toLowerCase())) { + orgRoleIds.add(roleMappings.get(roleLabel.toLowerCase())); + } + } + if(! orgRoleIds.isEmpty()) { + org.setEuropeanaRoleIds(orgRoleIds); + } } //build address object