ref #7597 Use LongRunningTaskService for taxon aggregation
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / utility / DerivedUnitConverter.java
1 /**
2 * Copyright (C) 2017 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.api.utility;
10
11 import java.lang.reflect.InvocationTargetException;
12 import java.lang.reflect.Method;
13
14 import org.apache.log4j.Logger;
15
16 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
17 import eu.etaxonomy.cdm.model.media.Media;
18 import eu.etaxonomy.cdm.model.name.Registration;
19 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
20 import eu.etaxonomy.cdm.model.name.TaxonName;
21 import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
22 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
23 import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
24 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
25
26 /**
27 *
28 * @author a.kohlbecker
29 * @since Jun 23, 2017
30 *
31 */
32 public class DerivedUnitConverter<TARGET extends DerivedUnit> {
33
34 private DerivedUnit source;
35
36 private SpecimenTypeDesignation specimenTypeDesignation;
37
38 private SpecimenTypeDesignation newSpecimenTypeDesignation;
39
40 private static final Logger logger = Logger.getLogger(DerivedUnitConverter.class);
41
42 /**
43 * @param specimenTypeDesignation
44 */
45 public DerivedUnitConverter(DerivedUnit source) throws Exception {
46 if(source == null){
47 throw new NullPointerException();
48 }
49 this.source = HibernateProxyHelper.deproxy(source, DerivedUnit.class);
50 if(source.getSpecimenTypeDesignations().size() == 1){
51 specimenTypeDesignation = source.getSpecimenTypeDesignations().iterator().next();
52 } else if (source.getSpecimenDescriptions().size() > 1){
53 throw new Exception("can not convert derived unit with multipe type designations");
54 }
55 }
56
57 /**
58 * @param specimenTypeDesignation
59 */
60 public DerivedUnitConverter(SpecimenTypeDesignation specimenTypeDesignation) {
61 if(specimenTypeDesignation == null){
62 throw new NullPointerException();
63 }
64 this.specimenTypeDesignation = HibernateProxyHelper.deproxy(specimenTypeDesignation);
65 this.source = HibernateProxyHelper.deproxy(specimenTypeDesignation.getTypeSpecimen(), DerivedUnit.class);
66 }
67
68 /**
69 * converts the <code>source</code> <code>DerivedUnit</code> this converter has been created
70 * for into a <code>DerivedUnit</code> of the type <code>TARGET</code>.
71 * If the <code>source</code> instance was persisted the target instance will also be written
72 * into data base and the source is deleted from there.
73 *
74 * @param targetType
75 * @param recordBasis
76 * @throws DerivedUnitConversionException
77 */
78 @SuppressWarnings("unchecked")
79 public SpecimenTypeDesignation convertTo(Class<TARGET> targetType, SpecimenOrObservationType recordBasis) throws DerivedUnitConversionException {
80
81 if(source.getClass().equals(targetType)){
82 // nothing to do
83 return specimenTypeDesignation;
84 }
85
86 if(!isSuppoprtedType(targetType)){
87 throw new DerivedUnitConversionException(
88 String.format("Unsupported convertion target type: %s",
89 targetType.getName())
90 );
91 }
92
93 if(!canConvert()){
94 throw new DerivedUnitConversionException(
95 String.format("%s can not be converted into %s as long it contains unconvertable non null properties",
96 source.toString(),
97 targetType.getName())
98 );
99 }
100
101 TARGET newInstance = null;
102 try {
103 Method newInstanceMethod = targetType.getDeclaredMethod("NewInstance", SpecimenOrObservationType.class);
104 newInstance = (TARGET) newInstanceMethod.invoke(SpecimenOrObservationType.class, recordBasis);
105
106 copyPropertiesTo(newInstance);
107
108 } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
109 | InvocationTargetException e) {
110 throw new DerivedUnitConversionException("Error during intantiation of " + targetType.getName(), e);
111 }
112
113 logger.debug("convertion of " + source.instanceToString() + "<--" + specimenTypeDesignation.instanceToString()
114 + " to "
115 + newSpecimenTypeDesignation.getTypeSpecimen().instanceToString() + "<--" + newSpecimenTypeDesignation.instanceToString() );
116 return newSpecimenTypeDesignation;
117
118 }
119
120 /**
121 * @param newInstance
122 */
123 private void copyPropertiesTo(TARGET target) {
124 target.setAccessionNumber(source.getAccessionNumber());
125 target.setBarcode(source.getBarcode());
126 target.setCatalogNumber(source.getCatalogNumber());
127 target.setCollection(source.getCollection());
128 DerivationEvent derivationEvent = source.getDerivedFrom();
129 if(derivationEvent != null){
130 derivationEvent.getDerivatives().remove(source);
131 }
132 target.setDerivedFrom(source.getDerivedFrom());
133 source.setDerivedFrom(null);
134 target.setExsiccatum(source.getExsiccatum());
135 target.setIndividualCount(source.getIndividualCount());
136 target.setKindOfUnit(source.getKindOfUnit());
137 target.setLifeStage(source.getLifeStage());
138 target.setLsid(source.getLsid());
139 target.setOriginalLabelInfo(source.getOriginalLabelInfo());
140 target.setPreferredStableUri(source.getPreferredStableUri());
141 target.setPreservation(source.getPreservation());
142 target.setPublish(source.isPublish());
143 target.setProtectedIdentityCache(source.isProtectedIdentityCache());
144 target.setProtectedTitleCache(source.isProtectedTitleCache());
145 // n.setRecordBasis(source.getRecordBasis()); // not to copy, this it is set for the new instance explicitly
146 target.setSex(source.getSex());
147 target.setStoredUnder(source.getStoredUnder());
148 target.setTitleCache(source.getTitleCache(), target.isProtectedTitleCache());
149 source.getSources().forEach(s -> target.addSource(s));
150 source.getAnnotations().forEach(a -> target.addAnnotation(a));
151 source.getCredits().forEach(c -> target.addCredit(c));
152 source.getDerivationEvents().forEach(de -> target.addDerivationEvent(de));
153 source.getDerivationEvents().clear();
154 source.getDescriptions().forEach(d -> target.addDescription(d));
155 source.getDeterminations().forEach(det -> target.addDetermination(det));
156 source.getDeterminations().clear();
157 source.getExtensions().forEach(e -> target.addExtension(e));
158 source.getIdentifiers().forEach(i -> target.addIdentifier(i));
159 source.getMarkers().forEach(m -> target.addMarker(m));
160 source.getRights().forEach(r -> target.addRights(r));
161 target.addSources(source.getSources());
162 // need to clone the SpecimenTypeDesignation, since the SpecimenTypeDesignations are being deleted by the hibernate delete cascade
163 newSpecimenTypeDesignation = (SpecimenTypeDesignation) specimenTypeDesignation.clone();
164 for(Registration reg : specimenTypeDesignation.getRegistrations()){
165 reg.removeTypeDesignation(specimenTypeDesignation);
166 }
167 for(TaxonName name : specimenTypeDesignation.getTypifiedNames()){
168 name.removeTypeDesignation(specimenTypeDesignation);
169 }
170 target.addSpecimenTypeDesignation(newSpecimenTypeDesignation);
171
172 }
173
174 /**
175 * @param targetType
176 * @return
177 */
178 public boolean isSuppoprtedType(Class<TARGET> targetType) {
179 return targetType.equals(MediaSpecimen.class) || targetType.equals(DerivedUnit.class);
180 }
181
182 /**
183 * @return
184 */
185 private boolean canConvert() {
186
187 if(source.getClass().equals(DerivedUnit.class)) {
188 return true;
189 }
190 if(source.getClass().equals(MediaSpecimen.class)){
191 MediaSpecimen ms = (MediaSpecimen)source;
192 Media media = ms.getMediaSpecimen();
193 return media == null;
194 }
195
196 return false;
197 }
198
199 /**
200 * Returns the derived unit which was the source entity for the conversion.
201 * You may want to delete this entity after the conversion if this makes sense
202 * in the context of the actual use case. By this you can
203 * avoid orphan derived units and type designations.
204 */
205 public DerivedUnit oldDerivedUnit(){
206 return source;
207 }
208
209 }