Project

General

Profile

Download (8.66 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.JoinColumn;
23
import javax.persistence.JoinTable;
24
import javax.persistence.OneToMany;
25
import javax.persistence.Transient;
26
import javax.xml.bind.annotation.XmlAccessType;
27
import javax.xml.bind.annotation.XmlAccessorType;
28
import javax.xml.bind.annotation.XmlElement;
29
import javax.xml.bind.annotation.XmlElementWrapper;
30
import javax.xml.bind.annotation.XmlSeeAlso;
31
import javax.xml.bind.annotation.XmlType;
32

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

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

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

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

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

    
80
	@XmlElementWrapper(name = "InverseRepresentations")
81
	@XmlElement(name = "Representation")
82
	@OneToMany(fetch = FetchType.LAZY)
83
	@JoinTable(
84
	        name="RelationshipTermBase_inverseRepresentation",
85
	        joinColumns = @JoinColumn(name="DefinedTermBase_id")
86
	)
87
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
88
	@IndexedEmbedded(depth = 2)
89
	private Set<Representation> inverseRepresentations = new HashSet<Representation>();
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)