Project

General

Profile

Download (8.95 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=30)
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
    public String getInverseSymbol() {
228
        return inverseSymbol;
229
    }
230
    public void setInverseSymbol(String inverseSymbol) {
231
        this.inverseSymbol = inverseSymbol;
232
    }
233

    
234
//**************** CSV *************************/
235

    
236
	@Override
237
	public T readCsvLine(Class<T> termClass, List<String> csvLine, Map<UUID,DefinedTermBase> terms, boolean abbrevAsId) {
238
		T newInstance = super.readCsvLine(termClass, csvLine, terms, abbrevAsId);
239

    
240
		String inverseText = csvLine.get(6).trim();
241
		String inverseLabel = csvLine.get(5).trim();
242
		String inverseLabelAbbrev = csvLine.get(7).trim();
243
		newInstance.addInverseRepresentation(new Representation(inverseText, inverseLabel, inverseLabelAbbrev, Language.CSV_LANGUAGE()) );
244
		newInstance.setSymmetric(Boolean.parseBoolean(csvLine.get(8)));
245
		newInstance.setTransitive(Boolean.parseBoolean(csvLine.get(9)));
246
		return newInstance;
247
	}
248

    
249
	@Override
250
	public void writeCsvLine(CSVWriter writer,T term) {
251
		String [] line = new String[8];
252
		line[0] = term.getUuid().toString();
253
		line[1] = term.getUri().toString();
254
		line[2] = term.getLabel();
255
		line[3] = term.getDescription();
256
		line[4] = term.getDescription();
257
		line[5] = term.getInverseLabel();
258
		line[6] = term.getInverseDescription();
259
		line[7] = String.valueOf(term.isSymmetric());
260
		line[8] = String.valueOf(term.isTransitive());
261
		writer.writeNext(line);
262
	}
263
	//*********************************** CLONE *********************************************************/
264

    
265
	/* (non-Javadoc)
266
	 * @see eu.etaxonomy.cdm.model.common.DefinedTermBase#clone()
267
	 * @see java.lang.Object#clone()
268
	 */
269
	@Override
270
	public Object clone() {
271
		RelationshipTermBase<?> result = (RelationshipTermBase<?>)super.clone();
272

    
273
		result.inverseRepresentations = new HashSet<Representation>();
274
		for (Representation rep: this.inverseRepresentations){
275
			result.addInverseRepresentation((Representation)rep.clone());
276
		}
277

    
278
		//no changes to: symmetric, transitiv
279
		return result;
280
	}
281

    
282

    
283
}
(60-60/72)