Merge branch 'release/5.45.0'
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / jaxb / CdmIDResolver.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.cdm.io.jaxb;
10
11 import java.util.HashMap;
12 import java.util.UUID;
13 import java.util.concurrent.Callable;
14
15 import javax.xml.bind.ValidationEventHandler;
16
17 import org.apache.logging.log4j.LogManager;
18 import org.apache.logging.log4j.Logger;
19 import org.springframework.beans.factory.annotation.Autowired;
20 import org.xml.sax.SAXException;
21
22 import com.sun.xml.bind.IDResolver;
23
24 import eu.etaxonomy.cdm.api.service.IAgentService;
25 import eu.etaxonomy.cdm.api.service.ICollectionService;
26 import eu.etaxonomy.cdm.api.service.IDescriptionService;
27 import eu.etaxonomy.cdm.api.service.IMediaService;
28 import eu.etaxonomy.cdm.api.service.INameService;
29 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
30 import eu.etaxonomy.cdm.api.service.IReferenceService;
31 import eu.etaxonomy.cdm.api.service.IService;
32 import eu.etaxonomy.cdm.api.service.ITaxonService;
33 import eu.etaxonomy.cdm.api.service.ITermService;
34 import eu.etaxonomy.cdm.api.service.ITermTreeService;
35 import eu.etaxonomy.cdm.api.service.IUserService;
36 import eu.etaxonomy.cdm.api.service.IVocabularyService;
37 import eu.etaxonomy.cdm.jaxb.UUIDAdapter;
38 import eu.etaxonomy.cdm.model.agent.AgentBase;
39 import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
40 import eu.etaxonomy.cdm.model.description.DescriptionBase;
41 import eu.etaxonomy.cdm.model.media.Media;
42 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
43 import eu.etaxonomy.cdm.model.name.TaxonName;
44 import eu.etaxonomy.cdm.model.occurrence.Collection;
45 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
46 import eu.etaxonomy.cdm.model.permission.User;
47 import eu.etaxonomy.cdm.model.reference.Reference;
48 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
49 import eu.etaxonomy.cdm.model.term.DefinedTermBase;
50 import eu.etaxonomy.cdm.model.term.TermTree;
51 import eu.etaxonomy.cdm.model.term.TermVocabulary;
52
53 public class CdmIDResolver extends IDResolver {
54
55 private static final Logger logger = LogManager.getLogger();
56
57 private IUserService userService;
58
59 private IAgentService agentService;
60
61 private ITermService termService;
62
63 private IVocabularyService vocabularyService;
64
65 private IDescriptionService descriptionService;
66
67 private ITermTreeService termTreeService;
68
69 private IMediaService mediaService;
70
71 private INameService nameService;
72
73 private IOccurrenceService occurrenceService;
74
75 private ICollectionService collectionService;
76
77 private IReferenceService referenceService;
78
79 private ITaxonService taxonService;
80
81 @Autowired
82 public void setUserService(IUserService userService) {
83 this.userService = userService;
84 }
85
86 @Autowired
87 public void setAgentService(IAgentService agentService) {
88 this.agentService = agentService;
89 }
90
91 @Autowired
92 public void setTermService(ITermService termService) {
93 this.termService = termService;
94 }
95
96 @Autowired
97 public void setVocabularyService(IVocabularyService vocabularyService) {
98 this.vocabularyService = vocabularyService;
99 }
100
101 @Autowired
102 public void setDescriptionService(IDescriptionService descriptionService) {
103 this.descriptionService = descriptionService;
104 }
105
106 @Autowired
107 public void setTermTreeService(ITermTreeService termTreeService) {
108 this.termTreeService = termTreeService;
109 }
110
111 @Autowired
112 public void setMediaService(IMediaService mediaService) {
113 this.mediaService = mediaService;
114 }
115
116 @Autowired
117 public void setNameService(INameService nameService) {
118 this.nameService = nameService;
119 }
120
121 @Autowired
122 public void setOccurrenceService(IOccurrenceService occurrenceService) {
123 this.occurrenceService = occurrenceService;
124 }
125
126 @Autowired
127 public void setCollectionService(ICollectionService collectionService) {
128 this.collectionService = collectionService;
129 }
130
131 @Autowired
132 public void setReferenceService(IReferenceService referenceService) {
133 this.referenceService = referenceService;
134 }
135
136 @Autowired
137 public void setTaxonService(ITaxonService taxonService) {
138 this.taxonService = taxonService;
139 }
140
141 private HashMap<String,Object> idmap = null;
142
143 @Override
144 public void startDocument(ValidationEventHandler eventHandler) throws SAXException {
145 if(idmap!=null) {
146 idmap.clear();
147 }
148 }
149
150 @Override
151 public void bind(String id, Object obj) throws SAXException {
152 if(idmap==null) {
153 idmap = new HashMap<>();
154 }
155 idmap.put(id,obj);
156 }
157
158
159 @Override
160 public Callable<Object> resolve(final String id, final Class targetType) throws SAXException {
161 return new Callable<Object>() {
162 @Override
163 public Object call() throws Exception {
164 logger.info("Resolving " + id + " for class " + targetType);
165
166 if(idmap==null || !idmap.containsKey(id)) {
167
168 String uuidPart = id.substring(UUIDAdapter.UUID_URN_PREFIX.length());
169 UUID uuid = UUID.fromString(uuidPart);
170 logger.info(uuid + " not in idmap, looking in database");
171 if(targetType.equals(User.class)) {
172 return resolveObject(uuid, targetType, userService);
173 } else if(AgentBase.class.isAssignableFrom(targetType) || INomenclaturalAuthor.class.isAssignableFrom(targetType)) {
174 return resolveObject(uuid, targetType, agentService);
175 } else if(DefinedTermBase.class.isAssignableFrom(targetType)) {
176 return resolveObject(uuid, targetType, termService);
177 } else if(TermVocabulary.class.isAssignableFrom(targetType)) {
178 return resolveObject(uuid, targetType, vocabularyService);
179 } else if(DescriptionBase.class.isAssignableFrom(targetType)) {
180 return resolveObject(uuid, targetType, descriptionService);
181 } else if(TermTree.class.isAssignableFrom(targetType)) {
182 return resolveObject(uuid, targetType, termTreeService);
183 } else if(Media.class.isAssignableFrom(targetType)) {
184 return resolveObject(uuid, targetType, mediaService);
185 } else if(TaxonName.class.isAssignableFrom(targetType)) {
186 return resolveObject(uuid, targetType, nameService);
187 } else if(SpecimenOrObservationBase.class.isAssignableFrom(targetType)) {
188 return resolveObject(uuid, targetType, occurrenceService);
189 } else if(Collection.class.isAssignableFrom(targetType)) {
190 return resolveObject(uuid, targetType, collectionService);
191 } else if(Reference.class.isAssignableFrom(targetType)) {
192 return resolveObject(uuid, targetType, referenceService);
193 } else if(TaxonBase.class.isAssignableFrom(targetType)) {
194 return resolveObject(uuid, targetType, taxonService);
195 } else if(HomotypicalGroup.class.isAssignableFrom(targetType)) {
196 Object object = nameService.findHomotypicalGroup(uuid);
197 if(object == null) {
198 throw new SAXException(targetType.getSimpleName() + " with " + uuid + " not found");
199 }
200 return object;
201 } else {
202 /**
203 * Collections of IDREFS do not have a type at runtime
204 * https://jaxb.dev.java.net/issues/show_bug.cgi?id=546
205 *
206 * Maybe in the future we'll be able to add targetType to IDREF
207 * but the spec has to be changed first so no fix is likely at the moment
208 *
209 */
210
211 AgentBase<?> agent = agentService.find(uuid);
212 if(agent != null) {
213 return agent;
214 }
215 DefinedTermBase<?> term = termService.find(uuid);
216 if(term != null) {
217 return term;
218 }
219 Media media = mediaService.find(uuid);
220 if(media != null) {
221 return media;
222 }
223 throw new SAXException(targetType.getSimpleName() + " with " + uuid + " not found");
224 }
225 } else {
226 return idmap.get(id);
227 }
228 }
229 };
230 }
231
232 private Object resolveObject(UUID uuid, Class targetType, IService service) throws SAXException {
233 Object object = service.find(uuid);
234 if(object == null) {
235 throw new SAXException(targetType.getSimpleName() + " with " + uuid + " not found");
236 }
237 return object;
238 }
239 }