1 /*
2 * Copyright 2003 - 2013 The eFaps Team
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Revision: $Rev$
17 * Last Changed: $Date$
18 * Last Changed By: $Author$
19 */
20
21 package org.efaps.admin.user;
22
23 import java.io.Serializable;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.Set;
28
29 import org.efaps.admin.datamodel.Type;
30 import org.efaps.ci.CIAdminUser;
31 import org.efaps.db.Insert;
32 import org.efaps.db.InstanceQuery;
33 import org.efaps.db.MultiPrintQuery;
34 import org.efaps.db.QueryBuilder;
35 import org.efaps.db.Update;
36 import org.efaps.util.EFapsException;
37
38 /**
39 * This class represents a set of UserAttribute related to a User.<br>
40 * For each User a set of UserAttribute can be made to store user-related
41 * content. e.g. Color of the UserInterface etc. The Class will read all Already
42 * in the eFpas-DataBase existing UserAttribute and store them in a map. A new
43 * or altered UserAttribute which is created/altered during the Session will
44 * only be stored in the map and not into the eFaps-DataBase. To store the
45 * UserAttribute into the eFapsDataBase the method {@link #storeInDb()} must be
46 * called explicitly.
47 *
48 * @author The eFasp Team
49 * @version $Id$
50 */
51 public class UserAttributesSet
52 implements Serializable
53 {
54
55 /**
56 * This static variable is the Key used to store the UserAttribtues into the
57 * SessionContext {@link #org.efaps.db.Context.getUserAttribute()}.
58 */
59 public static final String CONTEXTMAPKEY = UserAttributesSet.class.getName() + ".UserAttributes";
60
61 /**
62 * Needed for serialization.
63 */
64 private static final long serialVersionUID = 1L;
65
66 /**
67 * this static Map contains the name-to=UserAttribute Relation used by the
68 * enumeration.
69 */
70 private static final Map<String, UserAttributesSet.UserAttributesDefinition> MAPPER
71 = new HashMap<String, UserAttributesSet.UserAttributesDefinition>();
72
73 /**
74 * This enumeration is used to get a relation to the necessary types in the
75 * eFaps database for the attribute set.
76 */
77 public enum UserAttributesDefinition {
78 /**
79 *
80 */
81 ATTRIBUTE("Admin_User_Attribute", "Key", "Value");
82
83 /**
84 * stores the name of the Type.
85 */
86 private final String name;
87
88 /**
89 * Name of the attribute containing the Key.
90 */
91 private final String keyAttribute;
92
93 /**
94 * Name of the attribute containing the Value.
95 */
96 private final String valueAttribute;
97
98 /**
99 * Initializes the relationship definition for an user attribute set.
100 *
101 * @param _name name of type (relationship)
102 * @param _keyAttribute name of the key attribute
103 * @param _value name of the value attribute
104 */
105 private UserAttributesDefinition(final String _name,
106 final String _keyAttribute,
107 final String _value)
108 {
109 this.name = _name;
110 this.keyAttribute = _keyAttribute;
111 this.valueAttribute = _value;
112 UserAttributesSet.MAPPER.put(_name, this);
113 }
114
115 }
116
117 /**
118 * instance map to store a Key-to-UserAttribute Relation.
119 */
120 private final Map<String, UserAttribute> attributes = new HashMap<String, UserAttribute>();
121
122 /**
123 * this instance variable stores the Id of the User this UserAttributeSet
124 * belongs to.
125 */
126 private final Long userId;
127
128 /**
129 * Constructor using the constructor {@link #UserAttributesSet(long)}
130 * through searching the person id for the given name.
131 *
132 * @param _userName name of the user this attribute set will belong to
133 * @throws EFapsException if user attribute set could not be fetched from
134 * eFaps database
135 */
136 public UserAttributesSet(final String _userName)
137 throws EFapsException
138 {
139 this(Person.get(_userName).getId());
140 }
141
142 /**
143 * Constructor setting the {@link #userId} of the user this user attribute
144 * set belongs to and fetching the user attributes for this {@link #userId}
145 * from the eFaps database..
146 *
147 * @param _userId id of the user this user attribute set will belong to
148 * @throws EFapsException if attribute set could not be read from eFaps
149 * @see #readUserAttributes()
150 */
151 public UserAttributesSet(final long _userId)
152 throws EFapsException
153 {
154 this.userId = _userId;
155 readUserAttributes();
156 }
157
158 /**
159 * Initialize this user attribute set.
160 *
161 * @throws EFapsException if this attribute set could not be read from the
162 * eFaps database
163 * @see #readUserAttributes()
164 */
165 public void initialise()
166 throws EFapsException
167 {
168 readUserAttributes();
169 }
170
171 /**
172 * Check if this user attribute set contains an attribute for given
173 * <code>_key</code>.
174 *
175 * @param _key key to check if this user attribute set contains it
176 * @return <i>true</i> if the key was found; otherwise <i>false</i>
177 */
178 public boolean containsKey(final String _key)
179 {
180 return this.attributes.containsKey(_key);
181 }
182
183 /**
184 * Returns the value for a key as a String.
185 *
186 * @param _key key for the searched value
187 * @return string of the value if exist; otherwise <code>null</code>
188 */
189 public String getString(final String _key)
190 {
191 String ret = null;
192 if (this.attributes.containsKey(_key)) {
193 ret = this.attributes.get(_key).getValue();
194 }
195 return ret;
196 }
197
198 /**
199 * Sets a key-value pair for the attribute set of this attribute set. It
200 * uses {@link #set(String, String, UserAttributesDefinition)} to set the
201 * the relationship information. It will search in the {@link #MAPPER} to
202 * retrieve the definition of the attribute. If found it will use the found
203 * one, else it will use the a default
204 * {@link UserAttributesDefinition#ATTRIBUTE}.
205 *
206 * @param _key key to be set
207 * @param _value value to be set
208 * @throws EFapsException if <code>_key</code> or <code>_value</code> is
209 * <code>null</code>
210 */
211 public void set(final String _key,
212 final String _value)
213 throws EFapsException
214 {
215 if (UserAttributesSet.MAPPER.containsKey(_key)) {
216 set(_key, _value, UserAttributesSet.MAPPER.get(_key));
217 } else {
218 set(_key, _value, UserAttributesSet.UserAttributesDefinition.ATTRIBUTE);
219 }
220 }
221
222 /**
223 * Sets a key-value pair into the attribute set of an user. The method will
224 * search for the key and if the key already exists it will update the user
225 * attribute in this set. If the key does not exist a new user attribute
226 * will be added to this set.
227 *
228 * @param _key key to be set
229 * @param _value value to be set
230 * @param _definition type of the key-value pair
231 * @throws EFapsException if <code>_key</code> or <code>_value</code> is
232 * <code>null</code>
233 */
234 public void set(final String _key,
235 final String _value,
236 final UserAttributesDefinition _definition)
237 throws EFapsException
238 {
239 if (_key == null || _value == null) {
240 throw new EFapsException(this.getClass(), "set", _key, _value, _definition);
241 } else {
242 final UserAttribute userattribute = this.attributes.get(_key);
243 if (userattribute == null) {
244 this.attributes.put(_key, new UserAttribute(_definition.name, _value.trim(), true));
245 } else if (!userattribute.getValue().equals(_value.trim())) {
246 userattribute.setUpdate(true);
247 userattribute.setValue(_value.trim());
248 }
249 }
250 }
251
252 /**
253 * This method stores all user attributes of this user attributes set into
254 * the eFaps database. Only user attributes which where added or updated in
255 * this session will be updated/inserted in the eFpas database.
256 *
257 * @throws EFapsException if update of the user attributes failed
258 */
259 public void storeInDb()
260 throws EFapsException
261 {
262 for (final Entry<String, UserAttribute> entry : this.attributes.entrySet()) {
263 if (entry.getValue().isUpdate()) {
264 final QueryBuilder queryBldr = new QueryBuilder(Type.get(entry.getValue().getType()));
265 queryBldr.addWhereAttrEqValue("UserLink", this.userId.toString());
266 if (UserAttributesSet.MAPPER.get(entry.getValue().getType()).keyAttribute != null) {
267 queryBldr.addWhereAttrEqValue(UserAttributesSet.MAPPER.get(entry.getValue().getType()).keyAttribute,
268 entry.getKey());
269 }
270 final InstanceQuery query = queryBldr.getQuery();
271 query.execute();
272 Update update;
273 if (query.next()) {
274 update = new Update(query.getCurrentValue());
275 } else {
276 update = new Insert(entry.getValue().getType());
277 if (UserAttributesSet.MAPPER.get(entry.getValue().getType()).keyAttribute != null) {
278 update.add(UserAttributesSet.MAPPER.get(entry.getValue().getType()).keyAttribute,
279 entry.getKey());
280 }
281 update.add("UserLink", this.userId.toString());
282 }
283 update.add("Value", entry.getValue().getValue());
284 update.execute();
285 update.close();
286 }
287 }
288 this.attributes.clear();
289 }
290
291 /**
292 * Reads all {@link UserAttribute user attributes} from the eFaps database
293 * which belong to the user this user attribute set is read to and caches
294 * them in a map for fast access.
295 *
296 * @see #UserAttribute
297 * @throws EFapsException if attributes could not be read from eFaps
298 */
299 private void readUserAttributes()
300 throws EFapsException
301 {
302 // if the MAPPER is empty it must be initialized
303 if (UserAttributesSet.MAPPER.isEmpty()) {
304 UserAttributesSet.UserAttributesDefinition.values();
305 }
306
307 final Set<Type> types = CIAdminUser.AttributeAbstract.getType().getChildTypes();
308 for (final Type type : types) {
309 if (UserAttributesSet.MAPPER.containsKey(type.getName())) {
310 final UserAttributesDefinition definition = UserAttributesSet.MAPPER.get(type.getName());
311 final QueryBuilder queryBldr = new QueryBuilder(Type.get(definition.name));
312 queryBldr.addWhereAttrEqValue("UserLink", this.userId);
313 final MultiPrintQuery multi = queryBldr.getPrint();
314 multi.addAttribute(definition.valueAttribute);
315 if (definition.keyAttribute != null) {
316 multi.addAttribute(definition.keyAttribute);
317 }
318 multi.executeWithoutAccessCheck();
319 while (multi.next()) {
320 String key;
321 if (definition.keyAttribute == null) {
322 key = definition.name;
323 } else {
324 key = multi.getAttribute(definition.keyAttribute).toString().trim();
325 }
326 this.attributes.put(key,
327 new UserAttribute(definition.name, multi.getAttribute(definition.valueAttribute)
328 .toString().trim(), false));
329 }
330 }
331 }
332 }
333
334 /**
335 * Each instance of this class represents one UserAttribute for this user
336 * attribute set.
337 */
338 private class UserAttribute
339 implements Serializable
340 {
341
342 /**
343 * Needed for serialization.
344 */
345 private static final long serialVersionUID = 1L;
346
347 /**
348 * Value of this user attribute.
349 */
350 private String value;
351
352 /**
353 * Must this user attribute updated in the eFaps database?
354 */
355 private boolean update;
356
357 /**
358 * Type of this user attribute.
359 */
360 private final String type;
361
362 /**
363 *
364 * @param _type type of this user attribute set
365 * @param _value value of this user attribute set
366 * @param _update <i>true</i> if the attribute must be updated in eFaps
367 */
368 public UserAttribute(final String _type,
369 final String _value,
370 final boolean _update)
371 {
372 this.type = _type;
373 this.value = _value;
374 this.update = _update;
375 }
376
377 /**
378 * This is the getter method for the instance variable {@link #value}.
379 *
380 * @return value of instance variable {@link #value}
381 */
382 public String getValue()
383 {
384 return this.value;
385 }
386
387 /**
388 * This is the setter method for the instance variable {@link #value}.
389 *
390 * @param _value the value to set
391 */
392 public void setValue(final String _value)
393 {
394 this.value = _value;
395 }
396
397 /**
398 * This is the getter method for the instance variable {@link #update}.
399 *
400 * @return value of instance variable {@link #update}
401 */
402 public boolean isUpdate()
403 {
404 return this.update;
405 }
406
407 /**
408 * This is the setter method for the instance variable {@link #update}.
409 *
410 * @param _update the update to set
411 */
412 public void setUpdate(final boolean _update)
413 {
414 this.update = _update;
415 }
416
417 /**
418 * This is the getter method for the instance variable {@link #type}.
419 *
420 * @return value of instance variable {@link #type}
421 */
422 public String getType()
423 {
424 return this.type;
425 }
426 }
427 }