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