cleanup and some java doc
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / reference / OriginalSourceBase.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
10 package eu.etaxonomy.cdm.model.reference;
11
12
13 import java.util.HashSet;
14 import java.util.Set;
15
16 import javax.persistence.Column;
17 import javax.persistence.Entity;
18 import javax.persistence.FetchType;
19 import javax.persistence.Inheritance;
20 import javax.persistence.InheritanceType;
21 import javax.persistence.ManyToOne;
22 import javax.persistence.OneToMany;
23 import javax.persistence.OneToOne;
24 import javax.persistence.Table;
25 import javax.validation.constraints.NotNull;
26 import javax.xml.bind.annotation.XmlAccessType;
27 import javax.xml.bind.annotation.XmlAccessorType;
28 import javax.xml.bind.annotation.XmlAttribute;
29 import javax.xml.bind.annotation.XmlElement;
30 import javax.xml.bind.annotation.XmlElementWrapper;
31 import javax.xml.bind.annotation.XmlIDREF;
32 import javax.xml.bind.annotation.XmlRootElement;
33 import javax.xml.bind.annotation.XmlSchemaType;
34 import javax.xml.bind.annotation.XmlType;
35
36 import org.apache.commons.lang3.StringUtils;
37 import org.apache.log4j.Logger;
38 import org.hibernate.annotations.Cascade;
39 import org.hibernate.annotations.CascadeType;
40 import org.hibernate.annotations.Type;
41 import org.hibernate.envers.Audited;
42 import org.springframework.util.Assert;
43
44 import eu.etaxonomy.cdm.common.CdmUtils;
45 import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
46 import eu.etaxonomy.cdm.model.common.IIntextReferenceTarget;
47 import eu.etaxonomy.cdm.model.media.ExternalLink;
48 import eu.etaxonomy.cdm.strategy.merge.Merge;
49 import eu.etaxonomy.cdm.strategy.merge.MergeMode;
50
51 /**
52 * Abstract base class for classes implementing {@link eu.etaxonomy.cdm.model.reference.IOriginalSource IOriginalSource}.
53 * @see eu.etaxonomy.cdm.model.reference.IOriginalSource
54 *
55 * @author m.doering
56 * @since 08-Nov-2007 13:06:22
57 */
58
59 @XmlAccessorType(XmlAccessType.FIELD)
60 @XmlType(name = "OriginalSource", propOrder = {
61 "type",
62 "idInSource",
63 "idNamespace",
64 "originalNameString",
65 "citation",
66 "citationMicroReference",
67 "cdmSource",
68 "links"
69 })
70 @XmlRootElement(name = "OriginalSource")
71 @Entity
72 @Audited
73 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
74 @Table(name="OriginalSourceBase")
75 public abstract class OriginalSourceBase<T extends ISourceable>
76 extends AnnotatableEntity
77 implements IOriginalSource<T>, IIntextReferenceTarget {
78
79 private static final long serialVersionUID = -1972959999261181462L;
80 @SuppressWarnings("unused")
81 private static final Logger logger = Logger.getLogger(OriginalSourceBase.class);
82
83 /**
84 * The {@link OriginalSourceType type} of this source. According to PROV the type has to be thought as
85 * an activity that leads from the source entity to the current entity. It is not a property of the
86 * source itself.
87 */
88 @XmlAttribute(name ="type")
89 @Column(name="sourceType")
90 @NotNull
91 @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
92 parameters = {@org.hibernate.annotations.Parameter(name="enumClass", value="eu.etaxonomy.cdm.model.reference.OriginalSourceType")}
93 )
94 @Audited
95 private OriginalSourceType type;
96
97 //The object's ID in the source, where the alternative string comes from
98 @XmlElement(name = "IdInSource")
99 private String idInSource;
100
101 @XmlElement(name = "IdNamespace")
102 private String idNamespace;
103
104 @XmlElement(name = "Citation")
105 @XmlIDREF
106 @XmlSchemaType(name = "IDREF")
107 @ManyToOne(fetch = FetchType.LAZY)
108 @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
109 private Reference citation;
110
111 //Details of the reference. These are mostly (implicitly) pages but can also be tables or any other element of a
112 //publication. {if the citationMicroReference exists then there must be also a reference}
113 @XmlElement(name = "CitationMicroReference")
114 private String citationMicroReference;
115
116 @XmlElement(name = "OriginalNameString")
117 private String originalNameString;
118
119 @XmlElement(name = "CdmSource")
120 @XmlIDREF
121 @XmlSchemaType(name = "IDREF")
122 @OneToOne(fetch = FetchType.EAGER, orphanRemoval=true) //EAGER to avoid LIEs cdmSource should always be part of the OriginalSource itself
123 @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE, CascadeType.DELETE})
124 private CdmLinkSource cdmSource;
125
126 @XmlElementWrapper(name = "Links", nillable = true)
127 @XmlElement(name = "Link")
128 @OneToMany(fetch=FetchType.LAZY, orphanRemoval=true)
129 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
130 @Merge(MergeMode.ADD_CLONE)
131 private Set<ExternalLink> links = new HashSet<>();
132
133 //***************** CONSTRUCTOR ***********************/
134
135 //for hibernate use only
136 protected OriginalSourceBase() {
137
138 }
139
140 /**
141 * Constructor
142 * @param type
143 */
144 protected OriginalSourceBase(OriginalSourceType type){
145 if (type == null){
146 throw new IllegalArgumentException("OriginalSourceType must not be null");
147 }
148 this.type = type;
149 }
150
151 //**************** GETTER / SETTER *******************************/
152
153 @Override
154 public OriginalSourceType getType() {
155 return type;
156 }
157 @Override
158 public void setType(OriginalSourceType type) {
159 Assert.notNull(type, "OriginalSourceType must not be null");
160 this.type = type;
161 }
162
163 @Override
164 public String getIdInSource(){
165 return this.idInSource;
166 }
167 @Override
168 public void setIdInSource(String idInSource){
169 this.idInSource = idInSource;
170 }
171
172 @Override
173 public String getIdNamespace() {
174 return idNamespace;
175 }
176 @Override
177 public void setIdNamespace(String idNamespace) {
178 this.idNamespace = idNamespace;
179 }
180
181 @Override
182 public Reference getCitation(){
183 return this.citation;
184 }
185 @Override
186 public void setCitation(Reference citation) {
187 this.citation = citation;
188 }
189
190 @Override
191 public String getCitationMicroReference(){
192 return this.citationMicroReference;
193 }
194 @Override
195 public void setCitationMicroReference(String citationMicroReference){
196 this.citationMicroReference = citationMicroReference;
197 }
198
199 public String getOriginalNameString(){
200 return this.originalNameString;
201 }
202 public void setOriginalNameString(String originalNameString){
203 this.originalNameString = originalNameString;
204 }
205
206 @Override
207 public ICdmTarget getCdmSource() {
208 return cdmSource == null? null: cdmSource.getTarget();
209 }
210 /* this method was implemented in the context of the CdmLinkSourceBeanProcessor which is unused
211 * method is preserved for the time when the REST API will be revised (#8637)
212 @Override
213 public CdmLinkSource getCdmSource() {
214 if(cdmSource != null){
215 logger.error("NOT NULL");
216 }
217 return cdmSource;
218 }
219 */
220
221
222 // @Override
223 // public void setCdmSource(CdmLinkSource cdmSource) {
224 // this.cdmSource = cdmSource;
225 // }
226 @Override
227 public void setCdmSource(ICdmTarget cdmTarget){
228 if (cdmTarget != null){
229 this.cdmSource = CdmLinkSource.NewInstance(cdmTarget);
230 }else{
231 this.cdmSource = null;
232 }
233 }
234
235 //********************** External Links **********************************************
236
237
238 public Set<ExternalLink> getLinks(){
239 return this.links;
240 }
241 public void setLinks(Set<ExternalLink> links){
242 this.links = links;
243 }
244 public void addLink(ExternalLink link){
245 if (link != null){
246 links.add(link);
247 }
248 }
249 public void removeLink(ExternalLink link){
250 if(links.contains(link)) {
251 links.remove(link);
252 }
253 }
254
255 //********************** CLONE ************************************************/
256
257 @Override
258 public OriginalSourceBase<T> clone() throws CloneNotSupportedException{
259
260 @SuppressWarnings("unchecked")
261 OriginalSourceBase<T> result = (OriginalSourceBase<T>)super.clone();
262
263 Set<ExternalLink> links = new HashSet<>();
264 result.setLinks(links);
265 for(ExternalLink link : this.links){
266 result.addLink(link.clone());
267 }
268
269 if (this.cdmSource != null){
270 result.setCdmSource(this.cdmSource.getTarget());
271 }
272
273 //no changes to: type, idInSource, idNamespace,
274 // citation, citationMicroReference, originalNameString
275 return result;
276 }
277
278 // **************** EMPTY ************************/
279
280 @Override
281 protected boolean checkEmpty(){
282 return checkEmpty(false);
283 }
284
285 /**
286 * Checks if the source is completely empty.
287 *
288 * @param excludeType if <code>true</code> the source type
289 * is ignored for the check.
290 *
291 * @see #checkEmpty()
292 * @return <code>true</code> if empty
293 */
294 public boolean checkEmpty(boolean excludeType){
295 return super.checkEmpty()
296 && (excludeType || this.type == null)
297 && this.getCitation() == null
298 && isBlank(this.getCitationMicroReference())
299 && isBlank(this.getOriginalNameString())
300 && isBlank(this.getIdInSource())
301 && isBlank(this.getIdNamespace())
302 && this.links.isEmpty()
303 && this.cdmSource == null
304 ;
305 }
306
307 //************************ toString ***************************************/
308 @Override
309 public String toString(){
310 if (isNotBlank(idInSource) || isNotBlank(idNamespace) ){
311 return "OriginalSource:" + CdmUtils.concat(":", idNamespace, idInSource);
312 }else{
313 return super.toString();
314 }
315 }
316
317 //*********************************** EQUALS *********************************************************/
318
319 /**
320 * Indicates whether some other object is "equal to" this one.
321 *
322 * Uses a content based compare strategy which avoids bean initialization. This is achieved by
323 * comparing the cdm entity ids.
324 */
325 public boolean equalsByShallowCompare(OriginalSourceBase<T> other) {
326
327 int thisCitationId = -1;
328 int otherCitationId = -1;
329 if(this.getCitation() != null) {
330 thisCitationId = this.getCitation().getId();
331 }
332 if(other.getCitation() != null) {
333 otherCitationId = other.getCitation().getId();
334 }
335
336 if(thisCitationId != otherCitationId
337 || !StringUtils.equals(this.getCitationMicroReference(), other.getCitationMicroReference())
338 || !StringUtils.equals(this.getOriginalNameString(), other.getOriginalNameString())
339 ){
340 return false;
341 }
342
343 OriginalSourceBase<T> theOther = other;
344 if(!StringUtils.equals(this.getIdInSource(), theOther.getIdInSource())
345 || !CdmUtils.nullSafeEqual(this.getIdNamespace(), theOther.getIdNamespace())
346 || !CdmUtils.nullSafeEqual(this.getType(), theOther.getType())
347 || !CdmUtils.nullSafeEqual(this.getCdmSource(), theOther.getCdmSource())
348 || !CdmUtils.nullSafeEqual(this.getLinks(), theOther.getLinks())) {
349 return false;
350 }
351
352 return true;
353 }
354 }