Project

General

Profile

Download (14.1 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
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
import org.apache.commons.lang.StringUtils;
17
import org.hibernate.annotations.Cascade;
18
import org.hibernate.annotations.CascadeType;
19
import org.hibernate.envers.Audited;
20

    
21
import eu.etaxonomy.cdm.model.agent.AgentBase;
22
import eu.etaxonomy.cdm.model.media.Media;
23
import eu.etaxonomy.cdm.model.name.TaxonName;
24
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
25
import eu.etaxonomy.cdm.model.reference.Reference;
26
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
27

    
28
/**
29
 * This class represents a link to another CDM Base class from within a text.
30
 * If a text, e.g. a LanguageString links parts of its text to an other CDM Base
31
 * one may create a tag around the according text including id and uuid as attributes
32
 * and adding an IntextReference to the LanguageString. The IntextReference then points
33
 * to the according CdmBase.
34
 * This way we may keep referential integrity and we may also support correct
35
 * deduplication or deletion of the referenced objects.
36
 *
37
 * @see #4706
38
 *
39
 * @author a.mueller
40
 *
41
 */
42
@XmlAccessorType(XmlAccessType.FIELD)
43
@XmlType(name = "IntextReference", propOrder = {
44
    "taxonName",
45
    "taxon",
46
    "occurrence",
47
    "agent",
48
    "reference",
49
    "media",
50
    "languageString",
51
    "annotation",
52
    "startPos",
53
    "endPos"
54
})
55
@Entity
56
@Audited
57
public class IntextReference extends VersionableEntity {
58
	private static final long serialVersionUID = -7002541566256975424L;
59

    
60
    @XmlElement(name = "TaxonName")
61
    @XmlIDREF
62
    @XmlSchemaType(name = "IDREF")
63
    @ManyToOne(fetch = FetchType.LAZY)
64
	private TaxonName taxonName;
65

    
66
    @XmlElement(name = "Taxon")
67
    @XmlIDREF
68
    @XmlSchemaType(name = "IDREF")
69
    @ManyToOne(fetch = FetchType.LAZY)
70
	private TaxonBase<?> taxon;
71

    
72
    @XmlElement(name = "Occurrence")
73
    @XmlIDREF
74
    @XmlSchemaType(name = "IDREF")
75
    @ManyToOne(fetch = FetchType.LAZY)
76
	private SpecimenOrObservationBase<?> occurrence;
77

    
78
    @XmlElement(name = "Agent")
79
    @XmlIDREF
80
    @XmlSchemaType(name = "IDREF")
81
    @ManyToOne(fetch = FetchType.LAZY)
82
	private AgentBase<?> agent;
83

    
84
    @XmlElement(name = "Reference")
85
    @XmlIDREF
86
    @XmlSchemaType(name = "IDREF")
87
    @ManyToOne(fetch = FetchType.LAZY)
88
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
89
    private Reference reference;
90

    
91
    @XmlElement(name = "Media")
92
    @XmlIDREF
93
    @XmlSchemaType(name = "IDREF")
94
    @ManyToOne(fetch = FetchType.LAZY)
95
	private Media media;
96

    
97
    //TODO or do we want to link to LanguageString Base??
98
    @XmlElement(name = "LanguageString")
99
    @XmlIDREF
100
    @XmlSchemaType(name = "IDREF")
101
    @ManyToOne(fetch = FetchType.LAZY)
102
    private LanguageString languageString;
103

    
104
    //TODO or do we want to link to LanguageString Base??
105
    @XmlElement(name = "Annotation")
106
    @XmlIDREF
107
    @XmlSchemaType(name = "IDREF")
108
    @ManyToOne(fetch = FetchType.LAZY)
109
    private Annotation annotation;
110

    
111
	private int startPos;
112

    
113
	private int endPos;
114

    
115

    
116
    private enum CDM_INTEXT_CLASS{
117
        REFERENCE("reference"),
118
        TAXONNAME("name"),
119
        AGENT("agent"),
120
        MEDIA("media"),
121
        OCCURRENCE("occurrence"),
122
        TAXON("taxon")
123
        ;
124
        String tag;
125

    
126
         private CDM_INTEXT_CLASS(String tag) {
127
            this.tag = tag;
128
        }
129

    
130
        public String tag(){
131
            return this.tag;
132
        }
133
    }
134

    
135

    
136

    
137
// ***************** FACTORY METHOD ***********************************
138

    
139
    public static IntextReference NewInstance(IIntextReferenceTarget target,
140
            IIntextReferencable referencedEntity, int start, int end){
141
        IntextReference result = new IntextReference(target, referencedEntity, start, end);
142
        return result;
143
    }
144

    
145
//	public static IntextReference NewTaxonNameInstance(TaxonName taxonName, LanguageStringBase languageString, int start, int end){
146
//		return new IntextReference(taxonName, null, null, null, null, null, languageString, start, end);
147
//	}
148
//
149
//	public static IntextReference NewTaxonInstance(TaxonBase<?> taxon, LanguageStringBase languageString, int start, int end){
150
//		return new IntextReference(null, taxon, null, null, null, null, languageString, start, end);
151
//	}
152
//
153
//	public static IntextReference NewOccurrenceInstance(SpecimenOrObservationBase<?> occurrence, LanguageStringBase languageString, int start, int end){
154
//		return new IntextReference(null, null, occurrence, null, null, null, languageString, start, end);
155
//	}
156
//
157
//	public static IntextReference NewAgentInstance(AgentBase<?> agent, LanguageStringBase languageString, int start, int end){
158
//		return new IntextReference(null, null, null, agent, null, null, languageString, start, end);
159
//	}
160
//
161
//	public static IntextReference NewReferenceInstance(Reference reference, LanguageStringBase languageString, int start, int end){
162
//		return new IntextReference(null, null, null, null, reference, null, languageString, start, end);
163
//	}
164
//
165
//	public static IntextReference NewMediaInstance(Media media, LanguageStringBase languageString, int start, int end){
166
//		return new IntextReference(null, null, null, null, null, media, languageString, start, end);
167
//	}
168

    
169
	public static LanguageString NewReferencedLanguageString(IIntextReferenceTarget target, String pre, String middle, String post, Language language){
170
        LanguageString result = LanguageString.NewInstance(null, language);
171
        IntextReference intextReference = IntextReference.NewInstance(target, result, 0, 0);
172
	    result.addIntextReference(intextReference);
173
	    result.setText(pre + intextReference.toInlineString(middle) + post);
174
        return result;
175
    }
176

    
177
    public static LanguageString NewReferencedLanguageString(IIntextReferenceTarget target, String text, int start, int end, Language language){
178
        if (start < 0 || end < 0 || start > end || end > text.length()){
179
            throw new IndexOutOfBoundsException("Start and end must be within bounds");
180
        }
181
        LanguageString result = LanguageString.NewInstance(text, language);
182
        IntextReference intextReference = IntextReference.NewInstance(target, result, start, end);
183
        result.addIntextReference(intextReference);
184
        String intext = text.substring(0, start) +
185
                intextReference.toInlineString(text.substring(start, end)) + text.substring(end);
186
        result.setText(intext);
187
        return result;
188
    }
189

    
190
//********************** CONSTRUCTOR ********************************************/
191

    
192
	/**
193
	 * @deprecated for internal use only
194
	 */
195
	@Deprecated //for hibernate use only
196
	private IntextReference(){}
197

    
198
//	private IntextReference(TaxonName taxonName, TaxonBase<?> taxon,
199
//				SpecimenOrObservationBase<?> occurrence, AgentBase<?> agent,
200
//				Reference reference, Media media, LanguageStringBase languageString, int start, int end) {
201
//			super();
202
//			this.taxonName = taxonName;
203
//			this.taxon = taxon;
204
//			this.occurrence = occurrence;
205
//			this.agent = agent;
206
//			this.reference = reference;
207
//			this.media = media;
208
//			if (languageString != null && languageString.isInstanceOf(LanguageString.class)){
209
//				this.languageString = CdmBase.deproxy(languageString, LanguageString.class);
210
//				this.languageString.addIntextReference(this);
211
//			}else if (languageString != null && languageString.isInstanceOf(Annotation.class)){
212
//				this.annotation = CdmBase.deproxy(languageString, Annotation.class);
213
//				this.annotation.addIntextReference(this);
214
//			}
215
//			this.startPos = start;
216
//			this.endPos = end;
217
//	}
218

    
219
	   private IntextReference(IIntextReferenceTarget target, IIntextReferencable referencedEntity, int start, int end) {
220
           super();
221
           setTarget(target);
222
           setReferencedEntity(referencedEntity);
223

    
224
           this.startPos = start;
225
           this.endPos = end;
226
   }
227

    
228

    
229
    private CDM_INTEXT_CLASS myClass(){
230
        if (agent != null){
231
            return CDM_INTEXT_CLASS.AGENT;
232
        }else if (media != null){
233
            return CDM_INTEXT_CLASS.MEDIA;
234
        }else if (taxonName != null){
235
            return CDM_INTEXT_CLASS.TAXONNAME;
236
        }else if (taxon != null){
237
            return CDM_INTEXT_CLASS.TAXON;
238
        }else if (reference != null){
239
            return CDM_INTEXT_CLASS.REFERENCE;
240
        }else if (occurrence != null){
241
            return CDM_INTEXT_CLASS.OCCURRENCE;
242
        }else{
243
            throw new IllegalStateException("Intext reference has no target object defined");
244
        }
245
    }
246

    
247
// ****************    GETTER / SETTER ******************************************/
248

    
249
   /**
250
    * Returns the target object. Throws an {@link IllegalStateException} if no target
251
    * is defined.
252
    *
253
    * @return
254
    */
255
   public IIntextReferenceTarget getTarget() {
256
       if (agent != null){
257
           return agent;
258
       }else if (media != null){
259
           return media;
260
       }else if (taxonName != null){
261
           return taxonName;
262
       }else if (taxon != null){
263
           return taxon;
264
       }else if (reference != null){
265
           return reference;
266
       }else if (occurrence != null){
267
           return occurrence;
268
       }else{
269
           throw new IllegalStateException("Intext reference has no target object defined");
270
       }
271
   }
272

    
273
   /**
274
     * @param target
275
     */
276
    private void setTarget(IIntextReferenceTarget target) {
277
        target = CdmBase.deproxy(target);
278
        if (target instanceof TaxonName){
279
            this.taxonName = (TaxonName<?,?>)target;
280
        }else if (target instanceof TaxonBase){
281
            this.taxon = (TaxonBase<?>)target;
282
        }else if (target instanceof SpecimenOrObservationBase){
283
            this.occurrence = (SpecimenOrObservationBase<?>)target;
284
        }else if (target instanceof AgentBase){
285
            this.agent = (AgentBase<?>)target;
286
        }else if (target instanceof Reference){
287
            this.reference = (Reference)target;
288
        }else if (target instanceof Media){
289
            this.media = (Media)target;
290
        }else{
291
            throw new IllegalArgumentException("Target entity not yet handled: " + target.getClass().getName());
292
        }
293
    }
294

    
295
   public IIntextReferencable getReferencedEntity() {
296
       if (languageString != null){
297
           return languageString;
298
       }else if (annotation != null){
299
           return annotation;
300
       }else{
301
           return null;
302
       }
303
   }
304

    
305
   /**
306
    * @param referencedEntity
307
    */
308
   public void setReferencedEntity(IIntextReferencable referencedEntity) {
309
       if (referencedEntity == null){
310
           this.annotation = null;
311
           this.languageString = null;
312
       }else if (this.getReferencedEntity() == referencedEntity){
313
           //do nothing
314
       }else{
315
           referencedEntity = CdmBase.deproxy(referencedEntity);
316
           if (referencedEntity instanceof LanguageString){
317
               this.languageString = (LanguageString)referencedEntity;
318
               this.annotation = null;
319
           }else if (referencedEntity instanceof Annotation){
320
               this.annotation = (Annotation)referencedEntity;
321
               this.languageString = null;
322
           }else{
323
               throw new IllegalArgumentException("Referenced entity type not yet supported: " + referencedEntity.getClass().getName());
324
           }
325
           if (!referencedEntity.getIntextReferences().contains(this)){
326
               referencedEntity.addIntextReference(this);
327
           }
328
       }
329
   }
330

    
331
//	public TaxonName getTaxonName() {
332
//		return taxonName;
333
//	}
334
//	public void setTaxonName(TaxonName taxonName) {
335
//		this.taxonName = taxonName;
336
//	}
337
//
338
//
339
//	public TaxonBase<?> getTaxon() {
340
//		return taxon;
341
//	}
342
//	public void setTaxon(TaxonBase<?> taxon) {
343
//		this.taxon = taxon;
344
//	}
345
//
346
//	public SpecimenOrObservationBase<?> getOccurrence() {
347
//		return occurrence;
348
//	}
349
//	public void setOccurrence(SpecimenOrObservationBase<?> occurrence) {
350
//		this.occurrence = occurrence;
351
//	}
352
//
353
//	public AgentBase<?> getAgent() {
354
//		return agent;
355
//	}
356
//	public void setAgent(AgentBase<?> agent) {
357
//		this.agent = agent;
358
//	}
359
//
360
//	public Reference getReference() {
361
//		return reference;
362
//	}
363
//	public void setReference(Reference reference) {
364
//		this.reference = reference;
365
//	}
366
//
367
//	public Media getMedia() {
368
//		return media;
369
//	}
370
//	public void setMedia(Media media) {
371
//		this.media = media;
372
//	}
373

    
374
//	public LanguageString getLanguageString() {
375
//		return languageString;
376
//	}
377
//	protected void setLanguageString(LanguageString languageString) {
378
//		this.languageString = languageString;
379
//	}
380
//
381
//	public Annotation getAnnotation() {
382
//		return annotation;
383
//	}
384
//
385
//	public void setAnnotation(Annotation annotation) {
386
//		this.annotation = annotation;
387
//	}
388

    
389
	public int getStartPos() {
390
		return startPos;
391
	}
392
	public void setStartPos(int startPos) {
393
		this.startPos = startPos;
394
	}
395

    
396
	public int getEndPos() {
397
		return endPos;
398
	}
399
	public void setEndPos(int endPos) {
400
		this.endPos = endPos;
401
	}
402

    
403
	private static final String CDM_PREFIX = "cdm:";
404
	public String toInlineString(String innerText){
405
	    String tag = CDM_PREFIX + myClass().tag();
406
	    IIntextReferenceTarget entity = getTarget();
407
	    String attributes = " cdmId='" + entity.getUuid() + "' intextId='" + this.getUuid() + "'" + otherAttributes(entity);
408
	    String result;
409
	    if (StringUtils.isNotEmpty(innerText)){
410
	        result = "<" + tag + attributes + ">" + innerText + "</" + tag + ">";
411
	    }else{
412
            result = "<" + tag + attributes + "/>";
413
	    }
414
	    return result;
415
	}
416

    
417
    /**
418
     * Entity class dependent attributes
419
     * @param entity
420
     * @return
421
     */
422
    private String otherAttributes(IIntextReferenceTarget entity) {
423
        return "";
424
    }
425

    
426

    
427
}
(40-40/77)