Allow DwC-A import to filter streams and fix database mapping
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / stream / StreamImportStateBase.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.cdm.io.stream;
12
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.UUID;
20
21 import org.apache.log4j.Logger;
22
23 import eu.etaxonomy.cdm.api.service.IIdentifiableEntityService;
24 import eu.etaxonomy.cdm.io.common.ImportStateBase;
25 import eu.etaxonomy.cdm.io.dwca.TermUri;
26 import eu.etaxonomy.cdm.io.dwca.in.IImportMapping;
27 import eu.etaxonomy.cdm.io.dwca.in.IImportMapping.CdmKey;
28 import eu.etaxonomy.cdm.io.dwca.in.InMemoryMapping;
29 import eu.etaxonomy.cdm.io.dwca.in.MappedCdmBase;
30 import eu.etaxonomy.cdm.io.dwca.in.MappingEntry;
31 import eu.etaxonomy.cdm.model.common.CdmBase;
32 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
33 import eu.etaxonomy.cdm.model.reference.Reference;
34
35 /**
36 * @author a.mueller
37 * @created 23.11.2011
38 */
39 public abstract class StreamImportStateBase<CONFIG extends StreamImportConfiguratorBase, IO extends StreamImportBase> extends ImportStateBase<CONFIG, IO>{
40 private static final Logger logger = Logger.getLogger(StreamImportStateBase.class);
41
42 private UUID uuid = UUID.randomUUID();
43
44 boolean taxaCreated;
45 private Map<String, Map<String, IdentifiableEntity>> partitionStore;
46
47 private final IImportMapping mapping;
48
49 public StreamImportStateBase(CONFIG config) {
50 super(config);
51 if (config.getStateUuid()!= null){
52 uuid = config.getStateUuid();
53 }else{
54 String message = "State uuid: " + uuid.toString();
55 logger.warn(message);
56 System.out.println(message);
57 }
58 mapping = getConfig().getMappingType().getMappingInstance(uuid.toString(), getConfig().getDatabaseMappingFile());
59 }
60
61 /**
62 * True, if taxa have been fully created.
63 * @return
64 */
65 public boolean isTaxaCreated() {
66 return taxaCreated;
67
68 }
69
70 /**
71 * @param taxaCreated the taxaCreated to set
72 */
73 public void setTaxaCreated(boolean taxaCreated) {
74 this.taxaCreated = taxaCreated;
75 }
76
77 public void finish(){
78 this.mapping.finish();
79 }
80
81 //********************* MAPPING ACCESS *********************************
82 //TODO this may move to an external class soon
83
84 public void putMapping(MappedCdmBase mappedCdmBase) throws IllegalArgumentException{
85 if (! mappedCdmBase.getCdmBase().isInstanceOf(IdentifiableEntity.class)){
86 throw new IllegalArgumentException("Mapped cdmBase does not map an identifiable entity");
87 }
88 mapping.putMapping(mappedCdmBase.getNamespace(), mappedCdmBase.getSourceId(), CdmBase.deproxy(mappedCdmBase.getCdmBase(), IdentifiableEntity.class));
89 }
90
91
92 public void putMapping(String namespace, Integer sourceKey, IdentifiableEntity<?> destinationObject){
93 mapping.putMapping(namespace, sourceKey, destinationObject);
94 }
95
96 public void putMapping(String namespace, String sourceKey, IdentifiableEntity<?> destinationObject){
97 mapping.putMapping(namespace, sourceKey, destinationObject);
98 }
99
100
101 public List<IdentifiableEntity> get(String namespace, String sourceKey){
102 return get(namespace, sourceKey, null);
103 }
104
105 public <CLASS extends IdentifiableEntity> List<CLASS> get(String namespace, String sourceKey,Class<CLASS> destinationClass){
106 List<CLASS> result = new ArrayList<CLASS>();
107 if (this.partitionStore != null){
108 Map<String, IdentifiableEntity> namespaceMap = this.partitionStore.get(namespace);
109 if (namespaceMap != null){
110 IdentifiableEntity<?> cdmBase = namespaceMap.get(sourceKey);
111 if (cdmBase == null){
112 logger.info("CdmBase does not exist in mapping: " + sourceKey);
113 }else if (cdmBase.isInstanceOf(destinationClass)){
114 CLASS typedCdmBase = CdmBase.deproxy(cdmBase, destinationClass);
115 result.add(typedCdmBase);
116 }
117
118 }
119 }else{
120 Set<CdmKey> keySet = mapping.get(namespace, sourceKey);
121 for (CdmKey<CLASS> key: keySet){
122 if (destinationClass == null || destinationClass.isAssignableFrom(key.getClazz())){
123 IIdentifiableEntityService<CLASS> service = getCurrentIO().getServiceByClass(key.getClazz());
124 CLASS entity = CdmBase.deproxy(service.find(key.getId()), key.getClazz());
125 result.add(entity);
126 }
127 }
128 return result;
129 }
130 return result;
131 }
132
133 public boolean exists(String namespace, String sourceKey,Class<?> destinationClass){
134 return mapping.exists(namespace, sourceKey, destinationClass);
135 }
136
137
138 public void loadRelatedObjects (InMemoryMapping mapping){
139 Map<String, Map<String, IdentifiableEntity>> result = new HashMap<String, Map<String,IdentifiableEntity>>();
140
141 List<MappingEntry<String, String, Class, Integer>> mappingEntryList = mapping.getEntryList();
142
143 //order ids by destination classes
144 Map<Class, Set<Integer>> destinationNamespaceMap = new HashMap<Class, Set<Integer>>();
145 for (MappingEntry<String, String, Class, Integer> entry : mappingEntryList){
146 Set<Integer> idSet = destinationNamespaceMap.get(entry.getDestinationNamespace());
147 if (idSet == null){
148 idSet = new HashSet<Integer>();
149 destinationNamespaceMap.put(entry.getDestinationNamespace(), idSet);
150 }
151 idSet.add(entry.getDestinationId());
152 }
153
154 //retrieve cdm objects per class
155 Map<Class, Map<Integer, IdentifiableEntity>> classMap = new HashMap<Class, Map<Integer,IdentifiableEntity>>();
156 for (Class<?> cdmClass : destinationNamespaceMap.keySet()){
157 IIdentifiableEntityService<?> classService = getCurrentIO().getServiceByClass(cdmClass);
158 Set<Integer> idSet = destinationNamespaceMap.get(cdmClass);
159 List<? extends IdentifiableEntity> relatedObjects = classService.findById(idSet);
160
161 //put into id map
162 Map<Integer, IdentifiableEntity> idMap = new HashMap<Integer, IdentifiableEntity>();
163 for (IdentifiableEntity<?> identEnt : relatedObjects){
164 idMap.put(identEnt.getId(), identEnt);
165 }
166
167 //add to class map
168 classMap.put(cdmClass, idMap);
169 }
170
171 //fill related object map
172 for (MappingEntry<String, String, Class, Integer> entry : mappingEntryList){
173 IdentifiableEntity cdmBase = getCdmObject(classMap, entry);
174
175 Map<String, IdentifiableEntity> namespaceMap = getOrMakeNamespaceMap(result, entry.getNamespace());
176 if (cdmBase != null){
177 namespaceMap.put(entry.getSourceKey(), cdmBase);
178 }else{
179 logger.info("CdmBase not found for mapping entry.");
180 }
181 }
182
183 //store
184 this.partitionStore = result;
185
186 }
187
188 public void addRelatedObject(String sourceNamespace, String sourceKey, IdentifiableEntity<?> cdmEntity){
189 Map<String, IdentifiableEntity> namespaceMap = getOrMakeNamespaceMap(this.partitionStore, sourceNamespace);
190 if (cdmEntity != null){
191 namespaceMap.put(sourceKey, cdmEntity);
192 }else{
193 logger.info("CdmBase is null and will not be added to related objects.");
194 }
195 }
196
197
198 // public Map<String, Map<String, IdentifiableEntity>> getPartitionStore() {
199 // return partitionStore;
200 // }
201
202 public void unloadPartitionStore(Map<String, Map<String, IdentifiableEntity>> partitionStore) {
203 this.partitionStore = new HashMap<String, Map<String,IdentifiableEntity>>();
204 }
205
206 public IImportMapping getMapping() {
207 return this.mapping;
208 }
209
210
211 private Map<String, IdentifiableEntity> getOrMakeNamespaceMap(Map<String, Map<String, IdentifiableEntity>> relatedObjectMap2, String namespace) {
212 Map<String, IdentifiableEntity> namespaceMap = relatedObjectMap2.get(namespace);
213 if (namespaceMap == null){
214 namespaceMap = new HashMap<String, IdentifiableEntity>();
215 relatedObjectMap2.put(namespace, namespaceMap);
216 }
217 return namespaceMap;
218 }
219
220
221 private IdentifiableEntity getCdmObject(Map<Class, Map<Integer, IdentifiableEntity>> classMap,
222 MappingEntry<String, String, Class, Integer> entry) {
223 Class<?> cdmClass = entry.getDestinationNamespace();
224 Integer cdmKey = entry.getDestinationId();
225 Map<Integer, IdentifiableEntity> idMap = classMap.get(cdmClass);
226 if (idMap != null){
227 return idMap.get(cdmKey);
228 }else{
229 return null;
230 }
231 }
232
233 /**
234 * Returns the source reference object that is attached to the current transaction.
235 * @return
236 */
237 public Reference<?> getTransactionalSourceReference() {
238 TermUri namespaceSourceReference = TermUri.CDM_SOURCE_REFERENCE;
239 UUID sourceReferenceUuid = getConfig().getSourceRefUuid();
240 List<Reference> references = this.get(namespaceSourceReference.toString(), sourceReferenceUuid.toString(), Reference.class);
241 if (references.isEmpty()){
242 //TODO better fire warning, but not yet available for state
243 throw new RuntimeException("Source reference can not be found. This should not happen.");
244 }else if (references.size() > 1){
245 //TODO better fire warning, but not yet available for state
246 throw new RuntimeException("More than 1 source reference found. This is not yet handled.");
247 }else{
248 return references.get(0);
249 }
250
251
252
253 }
254
255
256
257
258
259
260 }