Merge branch 'release/5.15.0'
[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.OneToMany;
22 import javax.persistence.OneToOne;
23 import javax.persistence.Table;
24 import javax.validation.constraints.NotNull;
25 import javax.xml.bind.annotation.XmlAccessType;
26 import javax.xml.bind.annotation.XmlAccessorType;
27 import javax.xml.bind.annotation.XmlAttribute;
28 import javax.xml.bind.annotation.XmlElement;
29 import javax.xml.bind.annotation.XmlElementWrapper;
30 import javax.xml.bind.annotation.XmlIDREF;
31 import javax.xml.bind.annotation.XmlRootElement;
32 import javax.xml.bind.annotation.XmlSchemaType;
33 import javax.xml.bind.annotation.XmlType;
34
35 import org.apache.commons.lang.StringUtils;
36 import org.apache.log4j.Logger;
37 import org.hibernate.annotations.Cascade;
38 import org.hibernate.annotations.CascadeType;
39 import org.hibernate.annotations.Type;
40 import org.hibernate.envers.Audited;
41 import org.springframework.util.Assert;
42
43 import eu.etaxonomy.cdm.common.CdmUtils;
44 import eu.etaxonomy.cdm.model.common.IIntextReferenceTarget;
45 import eu.etaxonomy.cdm.model.common.ReferencedEntityBase;
46 import eu.etaxonomy.cdm.model.media.ExternalLink;
47 import eu.etaxonomy.cdm.strategy.merge.Merge;
48 import eu.etaxonomy.cdm.strategy.merge.MergeMode;
49
50 /**
51 * Abstract base class for classes implementing {@link eu.etaxonomy.cdm.model.reference.IOriginalSource IOriginalSource}.
52 * @see eu.etaxonomy.cdm.model.reference.IOriginalSource
53 *
54 * @author m.doering
55 * @since 08-Nov-2007 13:06:22
56 */
57
58 @XmlAccessorType(XmlAccessType.FIELD)
59 @XmlType(name = "OriginalSource", propOrder = {
60 "type",
61 "idInSource",
62 "idNamespace",
63 "cdmSource",
64 "links"
65 })
66 @XmlRootElement(name = "OriginalSource")
67 @Entity
68 @Audited
69 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
70 @Table(name="OriginalSourceBase")
71 public abstract class OriginalSourceBase<T extends ISourceable>
72 extends ReferencedEntityBase
73 implements IOriginalSource<T>, IIntextReferenceTarget {
74
75 private static final long serialVersionUID = -1972959999261181462L;
76 @SuppressWarnings("unused")
77 private static final Logger logger = Logger.getLogger(OriginalSourceBase.class);
78
79 /**
80 * The {@link OriginalSourceType type} of this source. According to PROV the type has to be thought as
81 * an activity that leads from the source entity to the current entity. It is not a property of the
82 * source itself.
83 */
84 @XmlAttribute(name ="type")
85 @Column(name="sourceType")
86 @NotNull
87 @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
88 parameters = {@org.hibernate.annotations.Parameter(name="enumClass", value="eu.etaxonomy.cdm.model.reference.OriginalSourceType")}
89 )
90 @Audited
91 private OriginalSourceType type;
92
93 //The object's ID in the source, where the alternative string comes from
94 @XmlElement(name = "IdInSource")
95 private String idInSource;
96
97 @XmlElement(name = "IdNamespace")
98 private String idNamespace;
99
100 @XmlElement(name = "CdmSource")
101 @XmlIDREF
102 @XmlSchemaType(name = "IDREF")
103 @OneToOne(fetch = FetchType.EAGER, orphanRemoval=true) //EAGER to avoid LIEs cdmSource should always be part of the OriginalSource itself
104 @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE, CascadeType.DELETE})
105 private CdmLinkSource cdmSource;
106
107 @XmlElementWrapper(name = "Links", nillable = true)
108 @XmlElement(name = "Link")
109 @OneToMany(fetch=FetchType.LAZY, orphanRemoval=true)
110 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
111 @Merge(MergeMode.ADD_CLONE)
112 private Set<ExternalLink> links = new HashSet<>();
113
114 //***************** CONSTRUCTOR ***********************/
115
116 //for hibernate use only
117 protected OriginalSourceBase() {
118
119 }
120
121 /**
122 * Constructor
123 * @param type2
124 */
125 protected OriginalSourceBase(OriginalSourceType type){
126 if (type == null){
127 throw new IllegalArgumentException("OriginalSourceType must not be null");
128 }
129 this.type = type;
130 }
131
132 //**************** GETTER / SETTER *******************************/
133
134
135 @Override
136 public String getIdInSource(){
137 return this.idInSource;
138 }
139 @Override
140 public void setIdInSource(String idInSource){
141 this.idInSource = idInSource;
142 }
143
144
145 @Override
146 public String getIdNamespace() {
147 return idNamespace;
148 }
149 @Override
150 public void setIdNamespace(String idNamespace) {
151 this.idNamespace = idNamespace;
152 }
153
154
155 @Override
156 public OriginalSourceType getType() {
157 return type;
158 }
159 @Override
160 public void setType(OriginalSourceType type) {
161 Assert.notNull(type, "OriginalSourceType must not be null");
162 this.type = type;
163 }
164
165 @Override
166 public ICdmTarget getCdmSource() {
167 return cdmSource == null? null: cdmSource.getTarget();
168 }
169 /* this method was implemented in the context of the CdmLinkSourceBeanProcessor which is unused
170 * method is preserved for the time when the REST API will be revised (#8637)
171 @Override
172 public CdmLinkSource getCdmSource() {
173 if(cdmSource != null){
174 logger.error("NOT NULL");
175 }
176 return cdmSource;
177 }
178 */
179
180
181 // @Override
182 // public void setCdmSource(CdmLinkSource cdmSource) {
183 // this.cdmSource = cdmSource;
184 // }
185 @Override
186 public void setCdmSource(ICdmTarget cdmTarget){
187 if (cdmTarget != null){
188 this.cdmSource = CdmLinkSource.NewInstance(cdmTarget);
189 }else{
190 this.cdmSource = null;
191 }
192 }
193
194 //********************** External Links **********************************************
195
196
197 public Set<ExternalLink> getLinks(){
198 return this.links;
199 }
200 public void setLinks(Set<ExternalLink> links){
201 this.links = links;
202 }
203 public void addLink(ExternalLink link){
204 if (link != null){
205 links.add(link);
206 }
207 }
208 public void removeLink(ExternalLink link){
209 if(links.contains(link)) {
210 links.remove(link);
211 }
212 }
213
214 //********************** CLONE ************************************************/
215
216 @Override
217 public Object clone() throws CloneNotSupportedException{
218 OriginalSourceBase<?> result = (OriginalSourceBase<?>)super.clone();
219
220 Set<ExternalLink> links = new HashSet<>();
221 result.setLinks(links);
222 for(ExternalLink link : this.links){
223 result.addLink(link.clone());
224 }
225
226 if (this.cdmSource != null){
227 result.setCdmSource(this.cdmSource.getTarget());
228 }
229
230 //no changes to: idInSource
231 return result;
232 }
233
234 // **************** EMPTY ************************/
235
236 @Override
237 protected boolean checkEmpty(){
238 return checkEmpty(false);
239 }
240
241 public boolean checkEmpty(boolean excludeType){
242 return super.checkEmpty()
243 && isBlank(this.getIdInSource())
244 && isBlank(this.getIdNamespace())
245 && this.links.isEmpty()
246 && this.cdmSource == null
247 && (excludeType || this.type == null)
248 ;
249 }
250
251 //************************ toString ***************************************/
252 @Override
253 public String toString(){
254 if (isNotBlank(idInSource) || isNotBlank(idNamespace) ){
255 return "OriginalSource:" + CdmUtils.concat(":", idNamespace, idInSource);
256 }else{
257 return super.toString();
258 }
259 }
260
261 //*********************************** EQUALS *********************************************************/
262
263 @Override
264 public boolean equalsByShallowCompare(ReferencedEntityBase other) {
265
266 if(!super.equalsByShallowCompare(other)) {
267 return false;
268 }
269 @SuppressWarnings("unchecked")
270 OriginalSourceBase<T> theOther = (OriginalSourceBase<T>)other;
271 if(!StringUtils.equals(this.getIdInSource(), theOther.getIdInSource())
272 || !CdmUtils.nullSafeEqual(this.getIdNamespace(), theOther.getIdNamespace())
273 || !CdmUtils.nullSafeEqual(this.getType(), theOther.getType())
274 || !CdmUtils.nullSafeEqual(this.getCdmSource(), theOther.getCdmSource())
275 || !CdmUtils.nullSafeEqual(this.getLinks(), theOther.getLinks())) {
276 return false;
277 }
278
279 return true;
280 }
281
282 }