1 /*******************************************************************************
2 * Imixs Workflow
3 * Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,
4 * http://www.imixs.com
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You can receive a copy of the GNU General Public
17 * License at http://www.gnu.org/licenses/gpl.html
18 *
19 * Project:
20 * http://www.imixs.org
21 * http://java.net/projects/imixs-workflow
22 *
23 * Contributors:
24 * Imixs Software Solutions GmbH - initial API and implementation
25 * Ralph Soika - Software Developer
26 *******************************************************************************/
27
28 package org.imixs.workflow.jee.jpa;
29
30 import java.util.ArrayList;
31 import java.util.Calendar;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Vector;
35
36 import javax.persistence.Basic;
37 import javax.persistence.ElementCollection;
38 import javax.persistence.FetchType;
39 import javax.persistence.Id;
40 import javax.persistence.Lob;
41 import javax.persistence.OneToMany;
42 import javax.persistence.OrderBy;
43 import javax.persistence.PrePersist;
44 import javax.persistence.PreUpdate;
45 import javax.persistence.Temporal;
46 import javax.persistence.TemporalType;
47 import javax.persistence.Version;
48
49 import org.imixs.workflow.WorkflowKernel;
50
51 /**
52 * This Entity ejb is a wrapper class for the org.imixs.workflow.ItemCollection
53 * which is used in all Imixs Workflow Interfaces. The Entity is used by the
54 * EntityServiceBean to store ItemCollections into a database using the JEE Java
55 * Persistence API. Each Entity contains a universal unique ID to identify the
56 * Entity. Also the Entiy supports the additional properties
57 * <ul>
58 * <li>type
59 * <li>created
60 * <li>modified
61 * <li>readAccess
62 * <li>writeAccess
63 * <li>textItems
64 * <li>calendarItems
65 * <li>integerItems
66 * <li>
67 * </ul>
68 *
69 * The creation time represents the point of time where the ItemCollection was
70 * first saved by the EntityService to the Database. The modify property
71 * represents the point of time where the ItemCollection was last saved by the
72 * EntityService. The type property is used to categorize entities in a
73 * database. This property is used by the save() method of the
74 * EntityServiceBean. So if an ItemCollection contains the attriubte 'type' the
75 * value will be automatically mapped to the type property. The properties read-
76 * and writeAccess containing the current access restrictions to an
77 * ItemCollection managed by the EntityService.
78 * <p>
79 * The data attribute is used to hold the ItemCollection data. It is mapped by a
80 * OR-Mapper to a large object (Lob). There is no way to query single attributes
81 * using the EJB Query Language. To support the powerful EJB Query language the
82 * Entity contains additional index properties to branch properties of an
83 * ItemCollection into onToMany relationships. These are the supported Index
84 * properties:
85 * <ul>
86 * <li>TextItem
87 * <li>IntegerItem
88 * <li>DoubleItem
89 * <li>CalendarItem
90 * </ul>
91 * A Client should not work directly with an instance of the Entity EJB or its
92 * index Properties. Its recommended to use the EntityService which acts as a
93 * session facade to manage instances of ItemCollection in a database system.
94 * <p>
95 * Notice: All relationships are marked as FetchType=EAGER. This is because the
96 * load and find Methods of the EntiyServiceBean do a clear() call to the
97 * PersitenceContext because the implodeEntity() method of the EntityServiceBean
98 * will modifies the values of an entity. So the Entity needs to be detached
99 * Immediately.
100 * <p>
101 * Why did the Entity Table use Join tables to link to OneToMany relationships ?
102 * <p>
103 * The default schema-level mapping for unidirectional one-to-many relationships
104 * uses a join table, as described in JSR 220 - Section 2.1.8.5. Unidirectional
105 * one-to-many relationships may be implemented using one-to-many foreign key
106 * mappings, however, such support is not required in this release. Applications
107 * that want to use a foreign key mapping strategy for one-to-many relationships
108 * should make these relationships bidirectional to ensure portability.
109 * <p>
110 * To store the Text-, Integer-, Double- and Calendar- Lists we can not use
111 * HashSet because the order in which elements are returned by a HashSet's
112 * iterator is not specified. This is the reason why we use Vectors to store the
113 * values and check for duplicates manually. So we make sure that values added
114 * to the list are not recorded
115 *
116 *
117 * @see org.imixs.workflow.jee.ejb.EntityService
118 * @see org.imixs.workflow.jee.ejb.EntityService
119 * @author rsoika
120 * @version 1.0
121 */
122
123 @javax.persistence.Entity
124 public class Entity implements java.io.Serializable {
125
126 private static final long serialVersionUID = 1L;
127 private String id;
128 private Integer version;
129 private String type;
130 private Calendar created;
131 private Calendar modified;
132 private Map<String,Object> data;
133 private List<ReadAccess> readAccessList;
134 private List<WriteAccess> writeAccessList;
135
136 private List<TextItem> textItems;
137 private List<IntegerItem> integerItems;
138 private List<DoubleItem> doubleItems;
139 private List<CalendarItem> calendarItems;
140
141
142 /**
143 * A Entity will be automatically initialized with a unique id and a
144 * creation date.
145 */
146 public Entity() {
147 /*
148 * Generate a new uniqueId
149 */
150 id=WorkflowKernel.generateUniqueID();
151 /*
152 String sIDPart1 = Long.toHexString(System.currentTimeMillis());
153 Double d = Math.random() * 900000000;
154 int i = d.intValue();
155 String sIDPart2 = Integer.toHexString(i);
156 id = sIDPart1 + "-" + sIDPart2;
157 */
158
159 // Initialize objects
160 Calendar cal = Calendar.getInstance();
161 created = cal;
162 }
163
164 /**
165 * This constructor allows the creation of an Entity Instance with a default
166 * uniqueID
167 *
168 * @param aID
169 */
170 public Entity(String aID) {
171 this();
172 if (aID != null && !"".equals(aID))
173 id = aID;
174 }
175
176 /**
177 * returns the unique identifier for the Entity.
178 *
179 * @return universal id
180 */
181 @Id
182 public String getId() {
183 return id;
184 }
185
186 protected void setId(String aID) {
187 id = aID;
188 }
189
190
191
192
193 @Version
194 public Integer getVersion() {
195 return version;
196 }
197
198 public void setVersion(Integer version) {
199 this.version = version;
200 }
201
202 /**
203 * returns the type property of the entity instance. This property can be
204 * provided by an itemColleciton in the attribute 'type'. Values will be
205 * case sensitive!
206 *
207 * @see org.imixs.workflow.jee.ejb.EntityService
208 * @return
209 */
210 public String getType() {
211 return type;
212 }
213
214 public void setType(String type) {
215 this.type = type;
216 }
217
218 /**
219 * returns the creation point of time.
220 *
221 * @return time of creation
222 */
223 @Temporal(TemporalType.TIMESTAMP)
224 public Calendar getCreated() {
225 return created;
226 }
227
228 public void setCreated(Calendar created) {
229 this.created = created;
230 }
231
232 /**
233 * returns the last modification point of time
234 *
235 * @return time of modification
236 */
237 @Temporal(TemporalType.TIMESTAMP)
238 public Calendar getModified() {
239 return modified;
240 }
241
242 public void setModified(Calendar modified) {
243 this.modified = modified;
244 }
245
246 /**
247 * updates the modification time before a update by a persistence manager is
248 * performed.
249 */
250 @SuppressWarnings("unused")
251 @PrePersist
252 @PreUpdate
253 private void updateModified() {
254 Calendar cal = Calendar.getInstance();
255 modified = cal;
256 }
257
258 /**
259 * returns the data object part of the Entity represented by a
260 * java.util.Map
261 *
262 * @return Map
263 */
264 @Lob
265 @Basic(fetch = FetchType.LAZY)
266 public Map<String,Object> getData() {
267 return data;
268 }
269
270 /**
271 * sets a data object for this Entity.
272 *
273 * @param data
274 */
275 public void setData(Map<String,Object> itemCol) {
276 this.data = itemCol;
277 }
278
279 /**
280 * ReadAccess list is loaded eager as this need to be check on every access
281 *
282 * @return ReadAccess list for the entity
283 */
284 @OneToMany(fetch = FetchType.EAGER)
285 public List<ReadAccess> getReadAccessList() {
286 if (readAccessList==null)
287 readAccessList=new ArrayList<ReadAccess>();
288 return readAccessList;
289 }
290
291 public void setReadAccessList(List<ReadAccess> readAccessList) {
292 this.readAccessList = readAccessList;
293 }
294
295
296
297 /**
298 * WrateAccess list is loaded lazy as this a check is only on update method
299 * needed
300 *
301 * @return WriteAccess list for the entity
302 */
303 @OneToMany(fetch = FetchType.LAZY)
304 public List<WriteAccess> getWriteAccessList() {
305 if (writeAccessList==null)
306 writeAccessList=new ArrayList<WriteAccess>();
307 return writeAccessList;
308 }
309
310 public void setWriteAccessList(List<WriteAccess> writeAccessList) {
311 this.writeAccessList = writeAccessList;
312 }
313
314
315 /**
316 * returns a list of all textItems joined to this Entity.
317 *
318 * @return a collection of TextItem objects
319 */
320 @OneToMany(fetch = FetchType.LAZY)
321 public List<TextItem> getTextItems() {
322 if (textItems == null)
323 textItems = new Vector<TextItem>();
324 return textItems;
325 }
326
327 public void setTextItems(List<TextItem> textItems) {
328 this.textItems = textItems;
329 }
330
331
332 /**
333 * returns a list of all integerItems joined to this Entity
334 *
335 * @return a collection of IntegerItem objects
336 */
337 @OneToMany(fetch = FetchType.LAZY)
338 public List<IntegerItem> getIntegerItems() {
339 if (integerItems == null)
340 integerItems = new Vector<IntegerItem>();
341 return integerItems;
342 }
343
344 public void setIntegerItems(List<IntegerItem> integerItems) {
345 this.integerItems = integerItems;
346 }
347
348 /**
349 * returns a list of all doubleItems joined to this Entity
350 *
351 * @return a collection of DoubleItem objects
352 */
353 @OneToMany(fetch = FetchType.LAZY)
354 public List<DoubleItem> getDoubleItems() {
355 if (doubleItems == null)
356 doubleItems = new Vector<DoubleItem>();
357 return doubleItems;
358 }
359
360 public void setDoubleItems(List<DoubleItem> doubleItems) {
361 this.doubleItems = doubleItems;
362 }
363
364 /**
365 * returns a list of all calendarItems joined to this Entity
366 *
367 * @return a collection of CalendarItem objects
368 */
369 @OneToMany(fetch = FetchType.LAZY)
370 public List<CalendarItem> getCalendarItems() {
371 if (calendarItems == null)
372 calendarItems = new Vector<CalendarItem>();
373 return calendarItems;
374 }
375
376 public void setCalendarItems(List<CalendarItem> calendarItems) {
377 this.calendarItems = calendarItems;
378 }
379
380
381
382
383
384 /*
385 @ElementCollection(fetch = FetchType.LAZY)
386 public List<TextItem> getTextItems() {
387 return textItems;
388 }
389
390 public void setTextItems(List<TextItem> textItems) {
391 this.textItems = textItems;
392 }
393 */
394
395
396 /*
397 @ElementCollection(fetch = FetchType.LAZY)
398 public Map<String, List<String>> getTextItems() {
399 return textItems;
400 }
401
402 public void setTextItems(Map<String,List<String>> textItems) {
403 this.textItems = textItems;
404 }
405
406 @ElementCollection(fetch = FetchType.LAZY)
407 public Map<String, List<Integer>> getIntegerItems() {
408 return integerItems;
409 }
410
411 public void setIntegerItems(Map<String, List<Integer>> integerItems) {
412 this.integerItems = integerItems;
413 }
414 */
415 }