Project

General

Profile

Download (8.71 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2009 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.common;
11

    
12
import java.util.HashSet;
13
import java.util.Iterator;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.Set;
17
import java.util.UUID;
18

    
19
import javax.persistence.Column;
20
import javax.persistence.Entity;
21
import javax.persistence.FetchType;
22
import javax.persistence.JoinTable;
23
import javax.persistence.OneToMany;
24
import javax.persistence.Transient;
25
import javax.xml.bind.annotation.XmlAccessType;
26
import javax.xml.bind.annotation.XmlAccessorType;
27
import javax.xml.bind.annotation.XmlElement;
28
import javax.xml.bind.annotation.XmlElementWrapper;
29
import javax.xml.bind.annotation.XmlSeeAlso;
30
import javax.xml.bind.annotation.XmlType;
31

    
32
import org.apache.log4j.Logger;
33
import org.hibernate.annotations.Cascade;
34
import org.hibernate.annotations.CascadeType;
35
import org.hibernate.envers.Audited;
36
import org.hibernate.search.annotations.Analyze;
37
import org.hibernate.search.annotations.Field;
38
import org.hibernate.search.annotations.IndexedEmbedded;
39

    
40
import au.com.bytecode.opencsv.CSVWriter;
41
import eu.etaxonomy.cdm.model.description.TextData;
42
import eu.etaxonomy.cdm.model.name.HybridRelationshipType;
43
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
44
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
45
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
46

    
47
@XmlAccessorType(XmlAccessType.FIELD)
48
@XmlType(name = "RelationshipTermBase", propOrder = {
49
    "symmetric",
50
    "transitive",
51
    "inverseRepresentations",
52
    "inverseSymbol"
53
})
54
@XmlSeeAlso({
55
	HybridRelationshipType.class,
56
	NameRelationshipType.class,
57
	SynonymRelationshipType.class,
58
	TaxonRelationshipType.class
59
})
60
@Entity
61
@Audited
62
public abstract class RelationshipTermBase<T extends RelationshipTermBase> extends OrderedTermBase<T> {
63
	private static final long serialVersionUID = 5497187985269083971L;
64
	@SuppressWarnings("unused")
65
	private static final Logger logger = Logger.getLogger(RelationshipTermBase.class);
66

    
67
	@XmlElement(name = "Symmetrical")
68
	@Field(analyze = Analyze.NO)
69
	@Column(name="symmetrical") //to be compatible with PostGreSQL
70
	private boolean symmetric;
71

    
72
	@XmlElement(name = "Transitive")
73
	@Field(analyze = Analyze.NO)
74
	private boolean transitive;
75

    
76
	@XmlElementWrapper(name = "InverseRepresentations")
77
	@XmlElement(name = "Representation")
78
	@OneToMany(fetch = FetchType.LAZY)
79
	@JoinTable(name="RelationshipTermBase_inverseRepresentation")
80
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
81
	@IndexedEmbedded(depth = 2)
82
	private Set<Representation> inverseRepresentations = new HashSet<Representation>();
83

    
84
    @XmlElement(name = "inverseSymbol")
85
    @Column(length=10)
86
    //the symbol to be used in String representations for the reverse representation of this term #5734
87
    //this term can be changed by the database instance even if the term is not managed by this instance as it is only for representation and has no semantic or identifying character
88
    //empty string is explicitly allowed and should be distinguished from NULL!
89
    private String inverseSymbol;
90

    
91
//******************** CONSTRUCTOR ************************/
92

    
93
    //for JAXB only, TODO needed?
94
    @Deprecated
95
    private RelationshipTermBase(){super();}
96

    
97

    
98
	protected RelationshipTermBase(TermType type) {
99
		super(type);
100
	}
101
	public RelationshipTermBase(TermType type, String term, String label, String labelAbbrev, boolean symmetric, boolean transitive) {
102
		super(type, term, label, labelAbbrev);
103
		setSymmetric(symmetric);
104
		setTransitive(transitive);
105
	}
106

    
107
//************************** METHODS ********************************
108

    
109
	public boolean isSymmetric() {
110
		return symmetric;
111
	}
112
	public void setSymmetric(boolean symmetric) {
113
		this.symmetric = symmetric;
114
	}
115

    
116
	public boolean isTransitive() {
117
		return transitive;
118
	}
119
	public void setTransitive(boolean transitive) {
120
		this.transitive = transitive;
121
	}
122

    
123
	public Set<Representation> getInverseRepresentations() {
124
		return inverseRepresentations;
125
	}
126

    
127
	public void addInverseRepresentation(Representation inverseRepresentation) {
128
		this.inverseRepresentations.add(inverseRepresentation);
129
	}
130
	public void removeInverseRepresentation(Representation inverseRepresentation) {
131
		this.inverseRepresentations.remove(inverseRepresentation);
132
	}
133
	public void addRepresentation(Representation representation, Representation inverseRepresentation) {
134
		this.addRepresentation(representation);
135
		this.addInverseRepresentation(inverseRepresentation);
136
	}
137

    
138
	public Representation getInverseRepresentation(Language lang) {
139
		Representation result = null;
140
		if (this.isSymmetric()){
141
			for (Representation repr : this.getRepresentations()){
142
				if (lang.equals(repr.getLanguage())){
143
					result = repr;
144
				}
145
			}
146
		}else{
147
			for (Representation repr : this.getInverseRepresentations()){
148
				if (lang.equals(repr.getLanguage())){
149
					result = repr;
150
				}
151
			}
152
		}
153
		return result;
154
	}
155

    
156
	/**
157
	 * Returns the InverseRepresentation in the preferred language. Preferred languages
158
	 * are specified by the parameter languages, which receives a list of
159
	 * Language instances in the order of preference. If no representation in
160
	 * any preferred languages is found the method falls back to return the
161
	 * Representation in Language.DEFAULT() and if necessary further falls back
162
	 * to return the first element found if any.
163
	 *
164
	 * TODO think about this fall-back strategy &
165
	 * see also {@link TextData#getPreferredLanguageString(List)}
166
	 * see also {@link TermBase#getPreferredRepresentation(List)}
167
	 *
168
	 * @param languages
169
	 * @return
170
	 */
171
	public Representation getPreferredInverseRepresentation(List<Language> languages) {
172
		Representation repr = null;
173
		if(languages != null){
174
			for(Language language : languages) {
175
				repr = getInverseRepresentation(language);
176
				if(repr != null){
177
					return repr;
178
				}
179
			}
180
		}
181
		if(repr == null){
182
			repr = getInverseRepresentation(Language.DEFAULT());
183
		}
184
		if(repr == null){
185
			Iterator<Representation> it = getInverseRepresentations().iterator();
186
			if(it.hasNext()){
187
				repr = getInverseRepresentations().iterator().next();
188
			}
189
		}
190
		return repr;
191
	}
192

    
193
	/*
194
	 * Inverse representation convenience methods similar to TermBase.xxx
195
	 * @see eu.etaxonomy.cdm.model.common.TermBase#getLabel()
196
	 */
197
	@Transient
198
	public String getInverseLabel() {
199
		if(getInverseLabel(Language.DEFAULT())!=null){
200
			return this.getInverseRepresentation(Language.DEFAULT()).getLabel();
201
		}else{
202
			for (Representation r : inverseRepresentations){
203
				return r.getLabel();
204
			}
205
		}
206
		return super.getUuid().toString();
207
	}
208

    
209
	public String getInverseLabel(Language lang) {
210
		Representation r = this.getInverseRepresentation(lang);
211
		if(r==null){
212
			return null;
213
		}else{
214
			return r.getLabel();
215
		}
216
	}
217

    
218
	@Transient
219
	public String getInverseDescription() {
220
		return this.getInverseRepresentation(Language.DEFAULT()).getDescription();
221
	}
222

    
223
	public String getInverseDescription(Language lang) {
224
		return this.getInverseRepresentation(lang).getDescription();
225
	}
226

    
227
	@Override
228
	public T readCsvLine(Class<T> termClass, List<String> csvLine, Map<UUID,DefinedTermBase> terms, boolean abbrevAsId) {
229
		T newInstance = super.readCsvLine(termClass, csvLine, terms, abbrevAsId);
230

    
231
		String inverseText = csvLine.get(6).trim();
232
		String inverseLabel = csvLine.get(5).trim();
233
		String inverseLabelAbbrev = csvLine.get(7).trim();
234
		newInstance.addInverseRepresentation(new Representation(inverseText, inverseLabel, inverseLabelAbbrev, Language.CSV_LANGUAGE()) );
235
		newInstance.setSymmetric(Boolean.parseBoolean(csvLine.get(8)));
236
		newInstance.setTransitive(Boolean.parseBoolean(csvLine.get(9)));
237
		return newInstance;
238
	}
239

    
240
	@Override
241
	public void writeCsvLine(CSVWriter writer,T term) {
242
		String [] line = new String[8];
243
		line[0] = term.getUuid().toString();
244
		line[1] = term.getUri().toString();
245
		line[2] = term.getLabel();
246
		line[3] = term.getDescription();
247
		line[4] = term.getDescription();
248
		line[5] = term.getInverseLabel();
249
		line[6] = term.getInverseDescription();
250
		line[7] = String.valueOf(term.isSymmetric());
251
		line[8] = String.valueOf(term.isTransitive());
252
		writer.writeNext(line);
253
	}
254
	//*********************************** CLONE *********************************************************/
255

    
256
	/* (non-Javadoc)
257
	 * @see eu.etaxonomy.cdm.model.common.DefinedTermBase#clone()
258
	 * @see java.lang.Object#clone()
259
	 */
260
	@Override
261
	public Object clone() {
262
		RelationshipTermBase<?> result = (RelationshipTermBase<?>)super.clone();
263

    
264
		result.inverseRepresentations = new HashSet<Representation>();
265
		for (Representation rep: this.inverseRepresentations){
266
			result.addInverseRepresentation((Representation)rep.clone());
267
		}
268

    
269
		//no changes to: symmetric, transitiv
270
		return result;
271
	}
272

    
273

    
274
}
(60-60/72)