Project

General

Profile

Download (11.4 KB) Statistics
| Branch: | Tag: | Revision:
1 e902c13e Andreas Müller
/**
2
 *
3
 */
4
package eu.etaxonomy.cdm.model.common;
5
6
import javax.persistence.Entity;
7
import javax.persistence.FetchType;
8
import javax.persistence.ManyToOne;
9
import javax.xml.bind.annotation.XmlAccessType;
10
import javax.xml.bind.annotation.XmlAccessorType;
11
import javax.xml.bind.annotation.XmlElement;
12
import javax.xml.bind.annotation.XmlIDREF;
13
import javax.xml.bind.annotation.XmlSchemaType;
14
import javax.xml.bind.annotation.XmlType;
15
16 530a12a5 Andreas Müller
import org.apache.commons.lang.StringUtils;
17
import org.hibernate.annotations.Cascade;
18
import org.hibernate.annotations.CascadeType;
19 e902c13e Andreas Müller
import org.hibernate.envers.Audited;
20
21
import eu.etaxonomy.cdm.model.agent.AgentBase;
22 4afd76e7 Andreas Müller
import eu.etaxonomy.cdm.model.description.PolytomousKey;
23 e902c13e Andreas Müller
import eu.etaxonomy.cdm.model.media.Media;
24 9dc896c9 Andreas Müller
import eu.etaxonomy.cdm.model.name.TaxonName;
25 e902c13e Andreas Müller
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
26
import eu.etaxonomy.cdm.model.reference.Reference;
27
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
28
29
/**
30
 * This class represents a link to another CDM Base class from within a text.
31
 * If a text, e.g. a LanguageString links parts of its text to an other CDM Base
32
 * one may create a tag around the according text including id and uuid as attributes
33
 * and adding an IntextReference to the LanguageString. The IntextReference then points
34
 * to the according CdmBase.
35
 * This way we may keep referential integrity and we may also support correct
36
 * deduplication or deletion of the referenced objects.
37
 *
38
 * @see #4706
39
 *
40
 * @author a.mueller
41
 *
42
 */
43
@XmlAccessorType(XmlAccessType.FIELD)
44
@XmlType(name = "IntextReference", propOrder = {
45
    "taxonName",
46
    "taxon",
47
    "occurrence",
48
    "agent",
49
    "reference",
50 bef05816 Andreas Müller
    "source",
51 e902c13e Andreas Müller
    "media",
52 4afd76e7 Andreas Müller
    "key",
53 e902c13e Andreas Müller
    "languageString",
54
    "annotation",
55
    "startPos",
56
    "endPos"
57
})
58
@Entity
59
@Audited
60
public class IntextReference extends VersionableEntity {
61
	private static final long serialVersionUID = -7002541566256975424L;
62
63
    @XmlElement(name = "TaxonName")
64
    @XmlIDREF
65
    @XmlSchemaType(name = "IDREF")
66
    @ManyToOne(fetch = FetchType.LAZY)
67 9dc896c9 Andreas Müller
	private TaxonName taxonName;
68 e902c13e Andreas Müller
69
    @XmlElement(name = "Taxon")
70
    @XmlIDREF
71
    @XmlSchemaType(name = "IDREF")
72
    @ManyToOne(fetch = FetchType.LAZY)
73
	private TaxonBase<?> taxon;
74
75
    @XmlElement(name = "Occurrence")
76
    @XmlIDREF
77
    @XmlSchemaType(name = "IDREF")
78
    @ManyToOne(fetch = FetchType.LAZY)
79
	private SpecimenOrObservationBase<?> occurrence;
80
81
    @XmlElement(name = "Agent")
82
    @XmlIDREF
83
    @XmlSchemaType(name = "IDREF")
84
    @ManyToOne(fetch = FetchType.LAZY)
85
	private AgentBase<?> agent;
86
87
    @XmlElement(name = "Reference")
88
    @XmlIDREF
89
    @XmlSchemaType(name = "IDREF")
90
    @ManyToOne(fetch = FetchType.LAZY)
91 530a12a5 Andreas Müller
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
92
    private Reference reference;
93 e902c13e Andreas Müller
94 bef05816 Andreas Müller
    @XmlElement(name = "Source")
95
    @XmlIDREF
96
    @XmlSchemaType(name = "IDREF")
97
    @ManyToOne(fetch = FetchType.LAZY)
98
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
99
    private OriginalSourceBase<?> source;
100
101 e902c13e Andreas Müller
    @XmlElement(name = "Media")
102
    @XmlIDREF
103
    @XmlSchemaType(name = "IDREF")
104
    @ManyToOne(fetch = FetchType.LAZY)
105
	private Media media;
106
107 4afd76e7 Andreas Müller
    @XmlElement(name = "SingleAccessKey")
108
    @XmlIDREF
109
    @XmlSchemaType(name = "IDREF")
110
    @ManyToOne(fetch = FetchType.LAZY)
111
    private PolytomousKey key;
112
113
114 e902c13e Andreas Müller
    //TODO or do we want to link to LanguageString Base??
115
    @XmlElement(name = "LanguageString")
116
    @XmlIDREF
117
    @XmlSchemaType(name = "IDREF")
118
    @ManyToOne(fetch = FetchType.LAZY)
119
    private LanguageString languageString;
120
121
    //TODO or do we want to link to LanguageString Base??
122
    @XmlElement(name = "Annotation")
123
    @XmlIDREF
124
    @XmlSchemaType(name = "IDREF")
125
    @ManyToOne(fetch = FetchType.LAZY)
126
    private Annotation annotation;
127
128
	private int startPos;
129
130
	private int endPos;
131
132 530a12a5 Andreas Müller
133 f75d81b1 Katja Luther
    public enum CDM_INTEXT_CLASS{
134 530a12a5 Andreas Müller
        REFERENCE("reference"),
135 bef05816 Andreas Müller
        SOURCE("source"),
136 530a12a5 Andreas Müller
        TAXONNAME("name"),
137
        AGENT("agent"),
138
        MEDIA("media"),
139
        OCCURRENCE("occurrence"),
140 4afd76e7 Andreas Müller
        TAXON("taxon"),
141
        KEY("key")
142 530a12a5 Andreas Müller
        ;
143
        String tag;
144
145
         private CDM_INTEXT_CLASS(String tag) {
146
            this.tag = tag;
147
        }
148
149
        public String tag(){
150
            return this.tag;
151
        }
152
    }
153
154
155
156 e902c13e Andreas Müller
// ***************** FACTORY METHOD ***********************************
157
158 3c6ba3cd Andreas Müller
    public static IntextReference NewInstance(IIntextReferenceTarget target,
159
            IIntextReferencable referencedEntity, int start, int end){
160
        IntextReference result = new IntextReference(target, referencedEntity, start, end);
161
        return result;
162
    }
163 e902c13e Andreas Müller
164 3c6ba3cd Andreas Müller
165
	public static LanguageString NewReferencedLanguageString(IIntextReferenceTarget target, String pre, String middle, String post, Language language){
166
        LanguageString result = LanguageString.NewInstance(null, language);
167
        IntextReference intextReference = IntextReference.NewInstance(target, result, 0, 0);
168
	    result.addIntextReference(intextReference);
169
	    result.setText(pre + intextReference.toInlineString(middle) + post);
170
        return result;
171
    }
172 e902c13e Andreas Müller
173 3c6ba3cd Andreas Müller
    public static LanguageString NewReferencedLanguageString(IIntextReferenceTarget target, String text, int start, int end, Language language){
174
        if (start < 0 || end < 0 || start > end || end > text.length()){
175
            throw new IndexOutOfBoundsException("Start and end must be within bounds");
176
        }
177
        LanguageString result = LanguageString.NewInstance(text, language);
178
        IntextReference intextReference = IntextReference.NewInstance(target, result, start, end);
179
        result.addIntextReference(intextReference);
180
        String intext = text.substring(0, start) +
181
                intextReference.toInlineString(text.substring(start, end)) + text.substring(end);
182
        result.setText(intext);
183
        return result;
184
    }
185 e902c13e Andreas Müller
186
//********************** CONSTRUCTOR ********************************************/
187
188
	/**
189
	 * @deprecated for internal use only
190
	 */
191
	@Deprecated //for hibernate use only
192
	private IntextReference(){}
193
194 3c6ba3cd Andreas Müller
	   private IntextReference(IIntextReferenceTarget target, IIntextReferencable referencedEntity, int start, int end) {
195
           super();
196
           setTarget(target);
197
           setReferencedEntity(referencedEntity);
198
199
           this.startPos = start;
200
           this.endPos = end;
201
   }
202 e902c13e Andreas Müller
203
204 815a9015 Katja Luther
    public CDM_INTEXT_CLASS myClass(){
205 530a12a5 Andreas Müller
        if (agent != null){
206
            return CDM_INTEXT_CLASS.AGENT;
207
        }else if (media != null){
208
            return CDM_INTEXT_CLASS.MEDIA;
209
        }else if (taxonName != null){
210
            return CDM_INTEXT_CLASS.TAXONNAME;
211
        }else if (taxon != null){
212
            return CDM_INTEXT_CLASS.TAXON;
213
        }else if (reference != null){
214
            return CDM_INTEXT_CLASS.REFERENCE;
215 bef05816 Andreas Müller
        }else if (source != null){
216
            return CDM_INTEXT_CLASS.SOURCE;
217 530a12a5 Andreas Müller
        }else if (occurrence != null){
218
            return CDM_INTEXT_CLASS.OCCURRENCE;
219 4afd76e7 Andreas Müller
        }else if (key != null){
220
            return CDM_INTEXT_CLASS.KEY;
221 530a12a5 Andreas Müller
        }else{
222
            throw new IllegalStateException("Intext reference has no target object defined");
223
        }
224
    }
225
226 3c6ba3cd Andreas Müller
// ****************    GETTER / SETTER ******************************************/
227
228
   /**
229
    * Returns the target object. Throws an {@link IllegalStateException} if no target
230
    * is defined.
231
    *
232
    * @return
233
    */
234
   public IIntextReferenceTarget getTarget() {
235 530a12a5 Andreas Müller
       if (agent != null){
236
           return agent;
237
       }else if (media != null){
238
           return media;
239
       }else if (taxonName != null){
240
           return taxonName;
241
       }else if (taxon != null){
242
           return taxon;
243
       }else if (reference != null){
244
           return reference;
245 bef05816 Andreas Müller
       }else if (source != null){
246
           return source;
247 530a12a5 Andreas Müller
       }else if (occurrence != null){
248
           return occurrence;
249 4afd76e7 Andreas Müller
       }else if (key != null){
250
           return key;
251 530a12a5 Andreas Müller
       }else{
252
           throw new IllegalStateException("Intext reference has no target object defined");
253
       }
254
   }
255
256 3c6ba3cd Andreas Müller
   /**
257
     * @param target
258
     */
259
    private void setTarget(IIntextReferenceTarget target) {
260
        target = CdmBase.deproxy(target);
261 9dc896c9 Andreas Müller
        if (target instanceof TaxonName){
262 db183545 Andreas Müller
            this.taxonName = (TaxonName)target;
263 3c6ba3cd Andreas Müller
        }else if (target instanceof TaxonBase){
264
            this.taxon = (TaxonBase<?>)target;
265
        }else if (target instanceof SpecimenOrObservationBase){
266
            this.occurrence = (SpecimenOrObservationBase<?>)target;
267
        }else if (target instanceof AgentBase){
268
            this.agent = (AgentBase<?>)target;
269
        }else if (target instanceof Reference){
270
            this.reference = (Reference)target;
271 bef05816 Andreas Müller
        }else if (target instanceof OriginalSourceBase){
272
            this.source = (OriginalSourceBase<?>)target;
273 3c6ba3cd Andreas Müller
        }else if (target instanceof Media){
274
            this.media = (Media)target;
275 4afd76e7 Andreas Müller
        }else if (target instanceof PolytomousKey){
276
            this.key = (PolytomousKey)target;
277 3c6ba3cd Andreas Müller
        }else{
278
            throw new IllegalArgumentException("Target entity not yet handled: " + target.getClass().getName());
279
        }
280
    }
281 e902c13e Andreas Müller
282 3c6ba3cd Andreas Müller
   public IIntextReferencable getReferencedEntity() {
283
       if (languageString != null){
284
           return languageString;
285
       }else if (annotation != null){
286
           return annotation;
287
       }else{
288
           return null;
289
       }
290
   }
291 e902c13e Andreas Müller
292 3c6ba3cd Andreas Müller
   /**
293
    * @param referencedEntity
294
    */
295
   public void setReferencedEntity(IIntextReferencable referencedEntity) {
296
       if (referencedEntity == null){
297
           this.annotation = null;
298
           this.languageString = null;
299
       }else if (this.getReferencedEntity() == referencedEntity){
300
           //do nothing
301
       }else{
302
           referencedEntity = CdmBase.deproxy(referencedEntity);
303
           if (referencedEntity instanceof LanguageString){
304
               this.languageString = (LanguageString)referencedEntity;
305
               this.annotation = null;
306
           }else if (referencedEntity instanceof Annotation){
307
               this.annotation = (Annotation)referencedEntity;
308
               this.languageString = null;
309
           }else{
310
               throw new IllegalArgumentException("Referenced entity type not yet supported: " + referencedEntity.getClass().getName());
311
           }
312
           if (!referencedEntity.getIntextReferences().contains(this)){
313
               referencedEntity.addIntextReference(this);
314
           }
315
       }
316
   }
317 e902c13e Andreas Müller
318
	public int getStartPos() {
319
		return startPos;
320
	}
321
	public void setStartPos(int startPos) {
322
		this.startPos = startPos;
323
	}
324
325
	public int getEndPos() {
326
		return endPos;
327
	}
328
	public void setEndPos(int endPos) {
329
		this.endPos = endPos;
330
	}
331
332 530a12a5 Andreas Müller
	private static final String CDM_PREFIX = "cdm:";
333
	public String toInlineString(String innerText){
334
	    String tag = CDM_PREFIX + myClass().tag();
335 3c6ba3cd Andreas Müller
	    IIntextReferenceTarget entity = getTarget();
336 530a12a5 Andreas Müller
	    String attributes = " cdmId='" + entity.getUuid() + "' intextId='" + this.getUuid() + "'" + otherAttributes(entity);
337
	    String result;
338
	    if (StringUtils.isNotEmpty(innerText)){
339
	        result = "<" + tag + attributes + ">" + innerText + "</" + tag + ">";
340
	    }else{
341
            result = "<" + tag + attributes + "/>";
342
	    }
343
	    return result;
344
	}
345
346
    /**
347
     * Entity class dependent attributes
348
     * @param entity
349
     * @return
350
     */
351 3c6ba3cd Andreas Müller
    private String otherAttributes(IIntextReferenceTarget entity) {
352 530a12a5 Andreas Müller
        return "";
353
    }
354
355
356 e902c13e Andreas Müller
}