Project

General

Profile

Download (10.6 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

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

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

    
26

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

    
54
    private static final int VALUE_LENGTH = 1023;
55

    
56
    private static final long serialVersionUID = 4307599154287181582L;
57

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

    
63

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

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

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

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

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

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

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

    
114

    
115
	@EmbeddedId
116
	private PrefKey key;
117

    
118
	@Column(length=VALUE_LENGTH)
119
	private String value;
120

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

    
126
    @Embeddable
127
    public static class PrefKey implements Serializable{
128

    
129
        private static final long serialVersionUID = 9019957853773606194L;
130

    
131
        //required syntax:  /([A-Za-z]+\[.*\])?
132
        //examples /  ,  /TaxonNode[#t10#44#1456#]  for a taxon node preference
133
        @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
134
        private String subject;
135

    
136
        @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
137
        private String predicate;
138

    
139
        //for hibernate use only
140
        private PrefKey(){}
141

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

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

    
167

    
168

    
169
            this.subject = subject;
170
            this.predicate = predicate;
171
        }
172

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

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

    
196
        public String getSubject() {
197
            return subject;
198
        }
199

    
200
        public String getPredicate() {
201
            return predicate;
202
        }
203

    
204
    }
205

    
206
//****************** CONSTRUCTOR **********************/
207

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

    
212

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

    
222

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

    
235

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

    
250
	}
251

    
252
//************************ GETTER / SETTER ***************************/
253

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

    
258

    
259
	/**
260
	 * @return the subject of the preference
261
	 */
262
	public String getSubject() {
263
		return key.subject;
264
	}
265

    
266
	/**
267
	 * @return the predicate of the preference
268
	 */
269
	public String getPredicate() {
270
		return key.predicate;
271
	}
272

    
273
	/**
274
	 * @return the value of the preference
275
	 */
276
	public String getValue() {
277
		return value;
278
	}
279

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

    
306

    
307
//
308
//  we try to avoid setting of values
309
//  public void setValue(String value) {
310
//      this.value = value;
311
//  }
312

    
313
	public PrefKey getKey() {
314
		return key;
315
	}
316

    
317
    public boolean isAllowOverride() {
318
        return allowOverride;
319
    }
320

    
321
    public void setAllowOverride(boolean allowOverride) {
322
        this.allowOverride = allowOverride;
323
    }
324

    
325
}
(3-3/8)