View Javadoc

1   /*
2    * Copyright 2015 Data Archiving and Networked Services (an institute of
3    * Koninklijke Nederlandse Akademie van Wetenschappen), King's College London,
4    * Georg-August-Universitaet Goettingen Stiftung Oeffentlichen Rechts
5    *
6    * Licensed under the EUPL, Version 1.1 or – as soon they will be approved by
7    * the European Commission - subsequent versions of the EUPL (the "Licence");
8    * You may not use this work except in compliance with the Licence.
9    * You may obtain a copy of the Licence at:
10   *
11   * https://joinup.ec.europa.eu/software/page/eupl
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the Licence is distributed on an "AS IS" basis,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the Licence for the specific language governing
17   * permissions and limitations under the Licence.
18   */
19  
20  package eu.ehri.project.importers.eac;
21  
22  import com.google.common.collect.Lists;
23  import com.google.common.collect.Maps;
24  import com.tinkerpop.frames.FramedGraph;
25  import eu.ehri.project.acl.SystemScope;
26  import eu.ehri.project.definitions.Entities;
27  import eu.ehri.project.definitions.Ontology;
28  import eu.ehri.project.exceptions.ValidationError;
29  import eu.ehri.project.importers.ImportLog;
30  import eu.ehri.project.importers.base.AbstractImporter;
31  import eu.ehri.project.importers.links.LinkResolver;
32  import eu.ehri.project.importers.util.ImportHelpers;
33  import eu.ehri.project.models.AccessPointType;
34  import eu.ehri.project.models.EntityClass;
35  import eu.ehri.project.models.HistoricalAgent;
36  import eu.ehri.project.models.base.Accessor;
37  import eu.ehri.project.models.base.Actioner;
38  import eu.ehri.project.models.base.Description;
39  import eu.ehri.project.models.base.PermissionScope;
40  import eu.ehri.project.models.cvoc.AuthoritativeSet;
41  import eu.ehri.project.persistence.Bundle;
42  import eu.ehri.project.persistence.BundleManager;
43  import eu.ehri.project.persistence.Mutation;
44  import org.slf4j.Logger;
45  import org.slf4j.LoggerFactory;
46  
47  import java.util.List;
48  import java.util.Map;
49  
50  /**
51   * Import EAC for a given repository into the database.
52   */
53  public class EacImporter extends AbstractImporter<Map<String, Object>, HistoricalAgent> {
54  
55      private static final Logger logger = LoggerFactory.getLogger(EacImporter.class);
56      private static final String REL_TYPE = "type";
57      private static final String REL_NAME = "name";
58  
59      private final LinkResolver linkResolver;
60  
61      /**
62       * Construct an EacImporter object.
63       *
64       * @param graph           the framed graph
65       * @param permissionScope the permission scope
66       * @param log             the import log
67       */
68      public EacImporter(FramedGraph<?> graph, PermissionScope permissionScope, Actioner actioner, ImportLog log) {
69          super(graph, permissionScope, actioner, log);
70          linkResolver = new LinkResolver(graph, actioner.as(Accessor.class));
71      }
72  
73      @Override
74      public HistoricalAgent importItem(Map<String, Object> itemData, List<String> idPath) throws
75              ValidationError {
76          return importItem(itemData);
77      }
78  
79      /**
80       * @param itemData the item data map
81       */
82      @Override
83      public HistoricalAgent importItem(Map<String, Object> itemData) throws ValidationError {
84  
85          BundleManager persister = new BundleManager(framedGraph, permissionScope.idPath());
86          Bundle descBundle = Bundle.of(EntityClass.HISTORICAL_AGENT_DESCRIPTION,
87                  extractUnitDescription(itemData, EntityClass.HISTORICAL_AGENT_DESCRIPTION));
88  
89          // Add dates and descriptions to the bundle since they're @Dependent
90          // relations.
91          for (Map<String, Object> dpb : ImportHelpers.extractDates(itemData)) {
92              descBundle = descBundle.withRelation(Ontology.ENTITY_HAS_DATE, Bundle.of(EntityClass.DATE_PERIOD, dpb));
93          }
94  
95          // add the address to the description bundle
96          Map<String, Object> address = ImportHelpers.extractAddress(itemData);
97          if (!address.isEmpty()) {
98              descBundle = descBundle.withRelation(Ontology.ENTITY_HAS_ADDRESS, Bundle.of(EntityClass.ADDRESS, address));
99          }
100 
101         Map<String, Object> unknowns = ImportHelpers.extractUnknownProperties(itemData);
102         if (!unknowns.isEmpty()) {
103             logger.debug("Unknown Properties found");
104             descBundle = descBundle.withRelation(Ontology.HAS_UNKNOWN_PROPERTY, Bundle.of(EntityClass.UNKNOWN_PROPERTY, unknowns));
105         }
106 
107         for (Map<String, Object> dpb : ImportHelpers.extractSubNodes(Entities.MAINTENANCE_EVENT, itemData)) {
108             logger.debug("maintenance event found");
109             //dates in maintenanceEvents are no DatePeriods, they are not something to search on
110             descBundle = descBundle.withRelation(Ontology.HAS_MAINTENANCE_EVENT, Bundle.of(EntityClass.MAINTENANCE_EVENT, dpb));
111         }
112 
113         for (Map<String, Object> rel : extractRelations(itemData)) {
114             if (rel.containsKey(REL_TYPE) && rel.get(REL_TYPE).equals(AccessPointType.subject.name())) {
115                 logger.debug("relation found");
116                 descBundle = descBundle.withRelation(Ontology.HAS_ACCESS_POINT,
117                         Bundle.of(EntityClass.ACCESS_POINT, rel));
118             }
119         }
120 
121         Bundle unit = Bundle.of(EntityClass.HISTORICAL_AGENT, extractUnit(itemData))
122                 .withRelation(Ontology.DESCRIPTION_FOR_ENTITY, descBundle);
123 
124         Mutation<HistoricalAgent> mutation = persister.createOrUpdate(unit, HistoricalAgent.class);
125         HistoricalAgent frame = mutation.getNode();
126         linkResolver.solveUndeterminedRelationships(frame);
127 
128         // There may or may not be a specific scope here...
129         if (!permissionScope.equals(SystemScope.getInstance())
130                 && mutation.created()) {
131             permissionScope.as(AuthoritativeSet.class).addItem(frame);
132             frame.setPermissionScope(permissionScope);
133         }
134 
135         handleCallbacks(mutation);
136         return frame;
137 
138     }
139 
140     private Iterable<Map<String, Object>> extractRelations(Map<String, Object> itemData) {
141         List<Map<String, Object>> list = Lists.newArrayList();
142         for (String key : itemData.keySet()) {
143             if (key.equals(Entities.ACCESS_POINT)) {
144                 //name identifier
145                 for (Map<String, Object> origRelation : (List<Map<String, Object>>) itemData.get(key)) {
146                     Map<String, Object> relationNode = Maps.newHashMap();
147                     for (String eventkey : origRelation.keySet()) {
148                         if (eventkey.equals(REL_TYPE)) {
149                             relationNode.put(Ontology.ACCESS_POINT_TYPE, origRelation.get(eventkey));
150                         } else if (eventkey.equals(REL_NAME)) {
151                             //try to find the original identifier
152                             relationNode.put(ImportHelpers.LINK_TARGET, origRelation.get("concept"));
153                             //try to find the original name
154                             relationNode.put(Ontology.NAME_KEY, origRelation.get(REL_NAME));
155                             relationNode.put("cvoc", origRelation.get("cvoc"));
156                         } else {
157                             relationNode.put(eventkey, origRelation.get(eventkey));
158                         }
159                     }
160                     if (!relationNode.containsKey(Ontology.ACCESS_POINT_TYPE)) {
161                         // Corporate bodies are the default type
162                         relationNode.put(Ontology.ACCESS_POINT_TYPE, AccessPointType.corporateBody);
163                     }
164                     list.add(relationNode);
165                 }
166             }
167         }
168         return list;
169     }
170 
171     protected Map<String, Object> extractUnitDescription(Map<String, Object> itemData, EntityClass entity) {
172         Map<String, Object> description = Maps.newHashMap();
173         description.put(Ontology.CREATION_PROCESS, Description.CreationProcess.IMPORT.toString());
174 
175         for (String key : itemData.keySet()) {
176             if (key.equals("descriptionIdentifier")) {
177                 description.put(Ontology.IDENTIFIER_KEY, itemData.get(key));
178             } else if (!key.startsWith(ImportHelpers.UNKNOWN_PREFIX)
179                     && !key.equals(ImportHelpers.OBJECT_IDENTIFIER)
180                     && !key.equals(Ontology.OTHER_IDENTIFIERS)
181                     && !key.equals(Ontology.IDENTIFIER_KEY)
182                     && !key.startsWith(Entities.MAINTENANCE_EVENT)
183                     && !key.startsWith(Entities.ACCESS_POINT)
184                     && !key.startsWith("IGNORE")
185                     && !key.startsWith("address/")) {
186                 description.put(key, ImportHelpers.flattenNonMultivaluedProperties(key, itemData.get(key), entity));
187             }
188         }
189 
190         return description;
191     }
192 
193     private Map<String, Object> extractUnit(Map<String, Object> itemData) throws ValidationError {
194         Map<String, Object> data = ImportHelpers.extractIdentifiers(itemData);
195         data.put("typeOfEntity", itemData.get("typeOfEntity"));
196         return data;
197     }
198 }