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.ImmutableMap;
23  import com.google.common.collect.Lists;
24  import com.google.common.collect.Sets;
25  import eu.ehri.project.definitions.Entities;
26  import eu.ehri.project.definitions.Ontology;
27  import eu.ehri.project.exceptions.ValidationError;
28  import eu.ehri.project.importers.base.ItemImporter;
29  import eu.ehri.project.importers.base.SaxXmlHandler;
30  import eu.ehri.project.importers.properties.XmlImportProperties;
31  import eu.ehri.project.importers.util.ImportHelpers;
32  import eu.ehri.project.models.AccessPoint;
33  import eu.ehri.project.models.DatePeriod;
34  import eu.ehri.project.models.MaintenanceEvent;
35  import eu.ehri.project.models.UnknownProperty;
36  import eu.ehri.project.models.base.Entity;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  import org.xml.sax.SAXException;
40  
41  import java.util.List;
42  import java.util.Locale;
43  import java.util.Map;
44  import java.util.Set;
45  
46  
47  /**
48   * Handler of EAC-CPF files. Creates a {@link Map} for the {@link EacImporter} to
49   * import.
50   * Makes use of eac.properties with format: part/of/path/=attribute
51   */
52  public class EacHandler extends SaxXmlHandler {
53  
54      // Artificial subnodes
55      private static final String NAME_ENTRY = "NameEntry";
56  
57      private final ImmutableMap<String, Class<? extends Entity>> possibleSubNodes = ImmutableMap
58              .<String, Class<? extends Entity>>builder()
59              .put(Entities.MAINTENANCE_EVENT, MaintenanceEvent.class)
60              .put(Entities.ACCESS_POINT, AccessPoint.class)
61              .put(Entities.DATE_PERIOD, DatePeriod.class)
62              .put(NAME_ENTRY, UnknownProperty.class)
63              .build();
64  
65      private static final Logger logger = LoggerFactory.getLogger(EacHandler.class);
66  
67      public EacHandler(ItemImporter<Map<String, Object>, ?> importer) {
68          super(importer, new XmlImportProperties("eac.properties"));
69      }
70  
71      public EacHandler(ItemImporter<Map<String, Object>, ?> importer, XmlImportProperties properties) {
72          super(importer, properties);
73      }
74  
75      @Override
76      protected boolean needToCreateSubNode(String key) {
77          return possibleSubNodes.containsKey(getMappedProperty(currentPath));
78      }
79  
80      @Override
81      public void endElement(String uri, String localName, String qName) throws SAXException {
82          //if a subnode is ended, add it to the super-supergraph
83          super.endElement(uri, localName, qName);
84          if (needToCreateSubNode(getMappedProperty(currentPath))) {
85              Map<String, Object> currentGraph = currentGraphPath.pop();
86              putSubGraphInCurrentGraph(getMappedProperty(currentPath), currentGraph);
87              depth--;
88          }
89  
90          currentPath.pop();
91  
92          //an EAC file consists of only 1 element, so if we're back at the root, we're done
93          if (currentPath.isEmpty()) {
94              try {
95                  logger.debug("depth close {} {}", depth, qName);
96                  //TODO: add any mandatory fields not yet there:
97                  if (!currentGraphPath.peek().containsKey(ImportHelpers.OBJECT_IDENTIFIER)) {
98                      putPropertyInCurrentGraph(ImportHelpers.OBJECT_IDENTIFIER, "id");
99                  }
100 
101                 //TODO: name can have only 1 value, others are otherFormsOfName
102                 if (currentGraphPath.peek().containsKey(NAME_ENTRY)) {
103                     String name = chooseName(currentGraphPath.peek().get(NAME_ENTRY));
104                     overwritePropertyInCurrentGraph(Ontology.NAME_KEY, name);
105                 }
106                 if (!currentGraphPath.peek().containsKey(Ontology.LANGUAGE_OF_DESCRIPTION)) {
107                     logger.debug("no {} found", Ontology.LANGUAGE_OF_DESCRIPTION);
108                     putPropertyInCurrentGraph(Ontology.LANGUAGE_OF_DESCRIPTION,
109                             Locale.ENGLISH.getISO3Language());
110                 }
111 
112                 importer.importItem(currentGraphPath.pop(), Lists.<String>newArrayList());
113 
114             } catch (ValidationError ex) {
115                 logger.error(ex.getMessage());
116             }
117         }
118     }
119 
120     private String chooseName(Object names) {
121         String nameValue;
122         if (names instanceof String) {
123             nameValue = names.toString();
124         } else if (names instanceof List) {
125             Object firstName = ((List) names).get(0);
126             if (firstName instanceof String) {
127                 nameValue = firstName.toString();
128             } else {
129                 Map nameMap = (Map) firstName;
130                 if (nameMap.get("namePart") instanceof String) {
131                     nameValue = nameMap.get("namePart").toString();
132                 } else if (nameMap.get("namePart") instanceof List) {
133                     nameValue = "";
134                     for (Object p : (List) nameMap.get("namePart")) {
135                         nameValue += p + " ";
136                     }
137 
138                 } else {
139                     nameValue = nameMap.get("namePart").toString();
140                 }
141             }
142 
143             Set<String> otherNames = Sets.newHashSet();
144             for (int i = 1; i < ((List) names).size(); i++) {
145                 Map m = (Map) ((List) names).get(i);
146                 Object namePart = m.get("namePart");
147                 if (namePart != null && !namePart.toString().trim().equalsIgnoreCase(nameValue)) {
148                     otherNames.add(namePart.toString().trim());
149                     logger.debug("other name: {}", namePart);
150                 }
151             }
152             otherNames.forEach(n -> putPropertyInCurrentGraph("otherFormsOfName", n));
153         } else {
154             logger.warn("no {} found", Ontology.NAME_KEY);
155             nameValue = "no title";
156         }
157         return nameValue.trim();
158     }
159 }