Project

General

Profile

Download (8.55 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.Indexed;
39
import org.hibernate.search.annotations.IndexedEmbedded;
40

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

    
48
@XmlAccessorType(XmlAccessType.FIELD)
49
@XmlType(name = "RelationshipTermBase", propOrder = {
50
    "symmetric",
51
    "transitive",
52
    "inverseRepresentations"
53
})
54
@XmlSeeAlso({
55
	HybridRelationshipType.class,
56
	NameRelationshipType.class,
57
	SynonymRelationshipType.class,
58
	TaxonRelationshipType.class
59
})
60
@Entity
61
@Audited
62
// even if hibernate complains "Abstract classes can never insert index documents. Remove @Indexed."
63
// this is needed, otherwise the fields of the also abstract super class are missed during indexing
64
@Indexed(index = "eu.etaxonomy.cdm.model.common.DefinedTermBase")
65
public abstract class RelationshipTermBase<T extends RelationshipTermBase> extends OrderedTermBase<T> {
66
	private static final long serialVersionUID = 5497187985269083971L;
67
	@SuppressWarnings("unused")
68
	private static final Logger logger = Logger.getLogger(RelationshipTermBase.class);
69

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

    
75
	@XmlElement(name = "Transitive")
76
	@Field(analyze = Analyze.NO)
77
	private boolean transitive;
78

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

    
87
//******************** CONSTRUCTOR ************************/
88
	
89
    //for JAXB only, TODO needed?
90
    @Deprecated
91
    private RelationshipTermBase(){super();}
92

    
93
	
94
	protected RelationshipTermBase(TermType type) {
95
		super(type);
96
	}
97
	public RelationshipTermBase(TermType type, String term, String label, String labelAbbrev, boolean symmetric, boolean transitive) {
98
		super(type, term, label, labelAbbrev);
99
		setSymmetric(symmetric);
100
		setTransitive(transitive);
101
	}
102

    
103
//************************** METHODS ********************************
104

    
105
	public boolean isSymmetric() {
106
		return symmetric;
107
	}
108
	public void setSymmetric(boolean symmetric) {
109
		this.symmetric = symmetric;
110
	}
111

    
112
	public boolean isTransitive() {
113
		return transitive;
114
	}
115
	public void setTransitive(boolean transitive) {
116
		this.transitive = transitive;
117
	}
118

    
119
	public Set<Representation> getInverseRepresentations() {
120
		return inverseRepresentations;
121
	}
122

    
123
	public void addInverseRepresentation(Representation inverseRepresentation) {
124
		this.inverseRepresentations.add(inverseRepresentation);
125
	}
126
	public void removeInverseRepresentation(Representation inverseRepresentation) {
127
		this.inverseRepresentations.remove(inverseRepresentation);
128
	}
129
	public void addRepresentation(Representation representation, Representation inverseRepresentation) {
130
		this.addRepresentation(representation);
131
		this.addInverseRepresentation(inverseRepresentation);
132
	}
133

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

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

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

    
205
	public String getInverseLabel(Language lang) {
206
		Representation r = this.getInverseRepresentation(lang);
207
		if(r==null){
208
			return null;
209
		}else{
210
			return r.getLabel();
211
		}
212
	}
213

    
214
	@Transient
215
	public String getInverseDescription() {
216
		return this.getInverseRepresentation(Language.DEFAULT()).getDescription();
217
	}
218

    
219
	public String getInverseDescription(Language lang) {
220
		return this.getInverseRepresentation(lang).getDescription();
221
	}
222

    
223
	@Override
224
	public T readCsvLine(Class<T> termClass, List<String> csvLine, Map<UUID,DefinedTermBase> terms, boolean abbrevAsId) {
225
		T newInstance = super.readCsvLine(termClass, csvLine, terms, abbrevAsId);
226

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

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

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

    
260
		result.inverseRepresentations = new HashSet<Representation>();
261
		for (Representation rep: this.inverseRepresentations){
262
			result.addInverseRepresentation((Representation)rep.clone());
263
		}
264

    
265
		//no changes to: symmetric, transitiv
266
		return result;
267
	}
268

    
269

    
270
}
(57-57/70)