Project

General

Profile

Download (10.8 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 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
package eu.etaxonomy.cdm.model.metadata;
10

    
11
import java.io.Serializable;
12
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.List;
15
import java.util.UUID;
16

    
17
import javax.persistence.Column;
18
import javax.persistence.Embeddable;
19
import javax.persistence.EmbeddedId;
20
import javax.persistence.Entity;
21
import javax.persistence.Lob;
22

    
23
import org.apache.commons.lang3.StringUtils;
24

    
25
import eu.etaxonomy.cdm.common.CdmUtils;
26

    
27

    
28
/**
29
 * This class may hold all preferences data for a CDM database.
30
 * E.g. one may store what the default nomenclatural code is,
31
 * or which default formatter (cache strategy) to use for a
32
 * certain class.
33
 * The structure represents a triple where the first item
34
 * (subject) defines for which object the given information is valid.
35
 * The second item (predicate) describes the type of information
36
 * and the third item (value) represents the actual value.
37
 *
38
 *  E.g. for defining a database wide default nomenclatural code
39
 *  you may define a triple ("database", "eu.etaxonomy.cdm.model.name.NomenclaturalCode", "ICZN").
40
 *  The set of allowed values and semantics for each combination
41
 *  is up to implementing classes.
42
 *  The only restrictions we have is the length of the fields and
43
 *  the fact that the first two items (subject, predicate) do
44
 *  create a unique key.
45
 *
46
 *  Size of single fields may be enlarged in future versions. "Value" may
47
 *  become a CLOB #7859.
48
 *
49
 * @author a.mueller
50
 * @since 03.07.2013
51
 */
52
@Entity
53
public final class CdmPreference implements Serializable {
54

    
55
    private static final int VALUE_LENGTH = 65536; //= CdmBase.CLOB_LENGTH;
56

    
57
    private static final long serialVersionUID = 4307599154287181582L;
58

    
59
    public static final CdmPreference NewInstance(PreferenceSubject subject,
60
            IPreferencePredicate<?> predicate, String value){
61
        return new CdmPreference(subject, predicate, value);
62
    }
63

    
64

    
65
    public static final CdmPreference NewInstance(PreferenceSubject subject, IPreferencePredicate<?> predicate, List<UUID> value){
66
        return new CdmPreference(subject, predicate, uuidListStr(value));
67
    }
68
    public static final CdmPreference NewInstance(PreferenceSubject subject, IPreferencePredicate<?> predicate, UUID ... value){
69
        return new CdmPreference(subject, predicate, uuidListStr(Arrays.asList(value)));
70
    }
71

    
72
    public static final CdmPreference NewInstance(PreferenceSubject subject, IPreferencePredicate<?> predicate, UUID value){
73
        return new CdmPreference(subject, predicate, value.toString());
74
    }
75

    
76
    /**
77
     * @param predicate
78
     * @param value
79
     * @return
80
     */
81
    public static CdmPreference NewDatabaseInstance(IPreferencePredicate<?> predicate, String value) {
82
        return new CdmPreference(PreferenceSubject.NewDatabaseInstance(), predicate, value);
83
    }
84

    
85
    /**
86
     * @param predicate
87
     * @param value
88
     * @return
89
     */
90
    public static CdmPreference NewVaadinInstance(IPreferencePredicate<?> predicate, String value) {
91
        return new CdmPreference(PreferenceSubject.NewVaadinInstance(), predicate, value);
92
    }
93

    
94
    /**
95
     * @param predicate
96
     * @param value
97
     * @return
98
     */
99
    public static CdmPreference NewTaxEditorInstance(IPreferencePredicate<?> predicate, String value) {
100
        return new CdmPreference(PreferenceSubject.NewTaxEditorInstance(), predicate, value);
101
    }
102

    
103
    public static PrefKey NewKey(PreferenceSubject subject, IPreferencePredicate<?> predicate){
104
      return new PrefKey(subject, predicate);
105
    }
106

    
107
//	public static final CdmPreference NewInstance(PreferenceSubjectEnum subject, PreferencePredicate predicate, String value){
108
//		return new CdmPreference(subject, predicate, value);
109
//	}
110
//
111
//	public static PrefKey NewKey(PreferenceSubjectEnum subject, PreferencePredicate predicate){
112
//		return new PrefKey(subject, predicate);
113
//	}
114

    
115

    
116
	@EmbeddedId
117
	private PrefKey key;
118

    
119
	@Column(length=VALUE_LENGTH)
120
	@Lob
121
	private String value;
122

    
123
    //if false, the preference should not be overridden by local preferences,
124
	//if true existing local preferences override database preferences
125
	    //and the database preference only defines the default.
126
    private boolean allowOverride = true;
127

    
128
    @Embeddable
129
    public static class PrefKey implements Serializable{
130

    
131
        private static final long serialVersionUID = 9019957853773606194L;
132

    
133
        //required syntax:  /([A-Za-z]+\[.*\])?
134
        //examples /  ,  /TaxonNode[#t10#44#1456#]  for a taxon node preference
135
        @Column(name="key_subject", length=100) //for now we keep the combined key short as indizes for such keys are very limited in size in some DBMS. Size may be increased later
136
        private String subject;
137

    
138
        @Column(name="key_predicate", length=100) //for now we keep the combined key short as indizes for such keys are very limited in size in some DBMS. Size may be increased later
139
        private String predicate;
140

    
141
        //for hibernate use only
142
        private PrefKey(){}
143

    
144
        private PrefKey(PreferenceSubject subject, IPreferencePredicate<?> predicate){
145
            this(subject.toString(), predicate.getKey());
146
        }
147
//      private PrefKey(PreferenceSubjectEnum subject, PreferencePredicate predicate){
148
//          this(subject.getKey(), predicate.getKey());
149
//      }
150

    
151
        private PrefKey(String subject, String predicate){
152
            if (subject == null) {
153
                throw new IllegalArgumentException("Subject must not be null for preference");
154
            }
155
            if (predicate == null) {
156
                throw new IllegalArgumentException("Predicate must not be null for preference");
157
            }
158
            if (subject.length() > 255) {
159
                throw new IllegalArgumentException("Subject must not be longer then 255 for preference");
160
            }
161
            if (predicate.length() > 255) {
162
                throw new IllegalArgumentException("Predicate must not be longer then 255 for preference");
163
            }
164
            if (!(subject.matches(PreferenceSubject.ROOT + "(([A-Za-z]+(\\[.*\\])?|"+PreferenceSubject.VAADIN+")"+PreferenceSubject.SEP+")*")
165
                    || subject.matches(PreferenceSubject.ROOT + "(([A-Za-z]+(\\[.*\\])?|"+PreferenceSubject.TAX_EDITOR+")"+PreferenceSubject.SEP+")*"))){
166
                throw new IllegalArgumentException("Subject does not follow the required syntax");
167
            }
168

    
169

    
170

    
171
            this.subject = subject;
172
            this.predicate = predicate;
173
        }
174

    
175
        @Override
176
        public int hashCode() {
177
            final int prime = 31;
178
            int result = 1;
179
            result = prime * result + ((predicate == null) ? 0 : predicate.hashCode());
180
            result = prime * result + ((subject == null) ? 0 : subject.hashCode());
181
            return result;
182
        }
183

    
184
        @Override
185
        public boolean equals(Object obj) {
186
            if (this == obj){
187
                return true;
188
            } else if (obj == null){
189
                return false;
190
            }else if (getClass() != obj.getClass()){
191
                return false;
192
            }else{
193
                PrefKey other = (PrefKey) obj;
194
                return ( predicate.equals(other.predicate) && subject.equals(other.subject));
195
            }
196
        }
197

    
198
        public String getSubject() {
199
            return subject;
200
        }
201

    
202
        public String getPredicate() {
203
            return predicate;
204
        }
205

    
206
    }
207

    
208
//****************** CONSTRUCTOR **********************/
209

    
210
	//for hibernate use only
211
	@SuppressWarnings("unused")
212
	private CdmPreference(){}
213

    
214

    
215
	private CdmPreference(PreferenceSubject subject, IPreferencePredicate<?> predicate, String value){
216
		this.key = new PrefKey(subject, predicate);
217
		//TODO are null values allowed?		assert predicate != null : "value must not be null for preference";
218
		if (value != null && value.length() > 1023) {throw new IllegalArgumentException(
219
				String.format("value must not be longer then 1023 characters for preference. Value = %s", value));
220
		}
221
		this.value = value;
222
	}
223

    
224

    
225
    /**
226
     * @param value
227
     * @return
228
     */
229
    protected static String uuidListStr(List<UUID> value) {
230
        String valueStr = "";
231
        for (UUID uuid : value){
232
            valueStr = CdmUtils.concat(",",valueStr, uuid.toString());
233
        }
234
        return valueStr;
235
    }
236

    
237

    
238
	/**
239
	 * Constructor.
240
	 * @param subject must not be null and must not be longer then 255 characters.
241
	 * @param predicate must not be null and must not be longer then 255 characters.
242
	 * @param value must not be longer then 1023 characters.
243
	 */
244
	public CdmPreference(String subject, String predicate, String value){
245
		this.key = new PrefKey(subject, predicate);
246
		//TODO are null values allowed?		assert predicate != null : "value must not be null for preference";
247
		if (value != null && value.length() > VALUE_LENGTH) {throw new IllegalArgumentException(
248
			String.format("value must not be longer then "+VALUE_LENGTH+" characters for preference. Value = %s", value));
249
		}
250
		this.value = value;
251

    
252
	}
253

    
254
//************************ GETTER / SETTER ***************************/
255

    
256
	public boolean isDatabasePref(){
257
	    return PreferenceSubject.ROOT.equals(key.subject);
258
	}
259

    
260

    
261
	/**
262
	 * @return the subject of the preference
263
	 */
264
	public String getSubjectString() {
265
		return key.subject;
266
	}
267
	   /**
268
     * @return the subject of the preference
269
     */
270
    public PreferenceSubject getSubject() {
271
        return PreferenceSubject.fromKey(key);
272
    }
273

    
274

    
275
	/**
276
	 * @return the predicate of the preference
277
	 */
278
	public String getPredicate() {
279
		return key.predicate;
280
	}
281

    
282
	/**
283
	 * @return the value of the preference
284
	 */
285
	public String getValue() {
286
		return value;
287
	}
288

    
289
	/**
290
	 * Returns the {@link #getValue() value} as {@link UUID} List.
291
	 * Throws an exception if the value can not be parsed as UUID list.
292
	 * @return
293
	 * @throws IllegalArgumentException
294
	 */
295
	public List<UUID> getValueUuidList() throws IllegalArgumentException {
296
	    List<UUID> result = new ArrayList<>();
297
	    if (StringUtils.isBlank(value)){
298
	        return result;
299
	    }
300
	    String[] splits = getValue().split("[,;]");
301
	    for (String split : splits ){
302
	        try {
303
                if (StringUtils.isBlank(split)){
304
                    continue; //neglect trailing separators
305
                }
306
	            UUID uuid = UUID.fromString(split.trim());
307
                result.add(uuid);
308
            } catch (IllegalArgumentException e) {
309
                throw e;
310
            }
311
	    }
312
	    return result;
313
    }
314

    
315

    
316
//
317
//  we try to avoid setting of values
318
//  public void setValue(String value) {
319
//      this.value = value;
320
//  }
321

    
322
	public PrefKey getKey() {
323
		return key;
324
	}
325

    
326
    public boolean isAllowOverride() {
327
        return allowOverride;
328
    }
329

    
330
    public void setAllowOverride(boolean allowOverride) {
331
        this.allowOverride = allowOverride;
332
    }
333

    
334
}
(3-3/13)