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.datamodel;
22  
23  import java.sql.PreparedStatement;
24  import java.sql.ResultSet;
25  import java.sql.SQLException;
26  import java.util.ArrayList;
27  import java.util.Collections;
28  import java.util.HashMap;
29  import java.util.HashSet;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Set;
33  import java.util.UUID;
34  
35  import org.apache.commons.lang3.builder.ToStringBuilder;
36  import org.efaps.admin.access.AccessSet;
37  import org.efaps.admin.access.AccessType;
38  import org.efaps.admin.datamodel.attributetype.BitEnumType;
39  import org.efaps.admin.datamodel.attributetype.CompanyLinkType;
40  import org.efaps.admin.datamodel.attributetype.ConsortiumLinkType;
41  import org.efaps.admin.datamodel.attributetype.EnumType;
42  import org.efaps.admin.datamodel.attributetype.GroupLinkType;
43  import org.efaps.admin.datamodel.attributetype.StatusType;
44  import org.efaps.admin.datamodel.attributetype.TypeType;
45  import org.efaps.admin.dbproperty.DBProperties;
46  import org.efaps.admin.event.EventDefinition;
47  import org.efaps.admin.event.EventType;
48  import org.efaps.admin.event.Parameter;
49  import org.efaps.admin.event.Parameter.ParameterValues;
50  import org.efaps.admin.event.Return;
51  import org.efaps.admin.event.Return.ReturnValues;
52  import org.efaps.admin.ui.Form;
53  import org.efaps.admin.ui.Image;
54  import org.efaps.admin.ui.Menu;
55  import org.efaps.ci.CIAdminAccess;
56  import org.efaps.ci.CIAdminDataModel;
57  import org.efaps.ci.CIAdminUserInterface;
58  import org.efaps.ci.CIType;
59  import org.efaps.db.AttributeQuery;
60  import org.efaps.db.Context;
61  import org.efaps.db.Instance;
62  import org.efaps.db.InstanceQuery;
63  import org.efaps.db.MultiPrintQuery;
64  import org.efaps.db.QueryBuilder;
65  import org.efaps.db.QueryCache;
66  import org.efaps.db.transaction.ConnectionResource;
67  import org.efaps.db.wrapper.SQLPart;
68  import org.efaps.db.wrapper.SQLSelect;
69  import org.efaps.util.EFapsException;
70  import org.efaps.util.cache.CacheLogListener;
71  import org.efaps.util.cache.CacheReloadException;
72  import org.efaps.util.cache.InfinispanCache;
73  import org.infinispan.Cache;
74  import org.infinispan.configuration.cache.CacheMode;
75  import org.slf4j.Logger;
76  import org.slf4j.LoggerFactory;
77  
78  /**
79   * This is the class for the type description. The type description holds
80   * information about creation of a new instance of a type with default values.
81   *
82   * @author The eFaps Team
83   * @version $Id$
84   */
85  public class Type
86      extends AbstractDataModelObject
87  {
88  
89      /**
90       * Enum for the different purpose of a type.
91       */
92      public enum Purpose
93          implements IBitEnum
94      {
95          /** Abstract purpose. */
96          ABSTRACT,
97          /** classification purpose. */
98          CLASSIFICATION,
99          /** GeneralInstane. */
100         GENERALINSTANCE,
101         /** No GeneralInstane. */
102         NOGENERALINSTANCE;
103 
104         /**
105          * {@inheritDoc}
106          */
107         @Override
108         public int getInt()
109         {
110             return BitEnumType.getInt4Index(ordinal());
111         }
112 
113         /**
114          * {@inheritDoc}
115          */
116         @Override
117         public int getBitIndex()
118         {
119             return ordinal();
120         }
121     }
122 
123     /**
124      * Needed for serialization.
125      */
126     private static final long serialVersionUID = 1L;
127 
128     /**
129      * Logging instance used in this class.
130      */
131     private static final Logger LOG = LoggerFactory.getLogger(Type.class);
132 
133     /**
134      * SQL select statement to select a type from the database by its UUID.
135      */
136     private static final String SQL_UUID = new SQLSelect()
137                     .column("ID")
138                     .column("UUID")
139                     .column("NAME")
140                     .column("PURPOSE")
141                     .column("PARENTDMTYPE")
142                     .column("PARENTCLASSDMTYPE")
143                     .from("V_ADMINTYPE", 0)
144                     .addPart(SQLPart.WHERE).addColumnPart(0, "UUID").addPart(SQLPart.EQUAL).addValuePart("?")
145                     .toString();
146 
147     /**
148      * SQL select statement to select a type from the database by its ID.
149      */
150     private static final String SQL_ID = new SQLSelect()
151                     .column("ID")
152                     .column("UUID")
153                     .column("NAME")
154                     .column("PURPOSE")
155                     .column("PARENTDMTYPE")
156                     .column("PARENTCLASSDMTYPE")
157                     .from("V_ADMINTYPE", 0)
158                     .addPart(SQLPart.WHERE).addColumnPart(0, "ID").addPart(SQLPart.EQUAL).addValuePart("?").toString();
159 
160     /**
161      * SQL select statement to select a type from the database by its Name.
162      */
163     private static final String SQL_NAME = new SQLSelect()
164                     .column("ID")
165                     .column("UUID")
166                     .column("NAME")
167                     .column("PURPOSE")
168                     .column("PARENTDMTYPE")
169                     .column("PARENTCLASSDMTYPE")
170                     .from("V_ADMINTYPE", 0)
171                     .addPart(SQLPart.WHERE).addColumnPart(0, "NAME").addPart(SQLPart.EQUAL).addValuePart("?")
172                     .toString();
173 
174     /**
175      * SQL select statement to select the ids of child types from the database.
176      */
177     private static final String SQL_CHILD = new SQLSelect()
178                     .column("ID")
179                     .column("PURPOSE")
180                     .from("V_ADMINTYPE", 0)
181                     .addPart(SQLPart.WHERE).addColumnPart(0, "PARENTDMTYPE").addPart(SQLPart.EQUAL).addValuePart("?")
182                     .toString();
183 
184     /**
185      * SQL select statement to select the ids of child types from the database.
186      */
187     private static final String SQL_CLASSCHILD = new SQLSelect()
188                     .column("ID")
189                     .column("PURPOSE")
190                     .from("V_ADMINTYPE", 0)
191                     .addPart(SQLPart.WHERE).addColumnPart(0, "PARENTCLASSDMTYPE")
192                         .addPart(SQLPart.EQUAL).addValuePart("?")
193                     .toString();
194 
195     /**
196      * Name of the Cache by UUID.
197      */
198     private static String UUIDCACHE = Type.class.getName() + ".UUID";
199 
200     /**
201      * Name of the Cache by ID.
202      */
203     private static String IDCACHE = Type.class.getName() + ".ID";
204 
205     /**
206      * Name of the Cache by Name.
207      */
208     private static String NAMECACHE = Type.class.getName() + ".Name";
209 
210     /**
211      * Instance variable for the parent type from which this type is derived.
212      *
213      * @see #getParentType
214      * @see #setParentType
215      */
216     private Long parentTypeId = null;
217 
218     /**
219      * Instance variable for all child types ids derived from this type.
220      *
221      * @see #getChildTypes
222      */
223     private final Set<Long> childTypes = new HashSet<Long>();
224 
225     /**
226      * Classification ids which are classifying this type.
227      */
228     private final Set<Long> classifiedByTypes = new HashSet<Long>();
229 
230     /**
231      * The instance variables stores all attributes for this type object.
232      *
233      * @see #getAttributes()
234      * @see #add(Attribute)
235      * @see #getAttribute
236      * @see #getAttributes(Class)
237      */
238     private final Map<String, Attribute> attributes = new HashMap<String, Attribute>();
239 
240     /**
241      * Instance of a HashSet to store all needed tables for this type. The
242      * tables are automatically added via the method {@link #add(Attribute)}.
243      *
244      * @see #add(Attribute)
245      * @see #getTables
246      */
247     private final Set<SQLTable> tables = new HashSet<SQLTable>();
248 
249     /**
250      * The instance variable stores the main table, which must be inserted
251      * first. In the main table stands also the select statement to get a new
252      * id. The value is automatically set with method {@link #add(Attribute)}.
253      *
254      * @see Table.mainTable
255      * @see #add(Attribute)
256      * @see #getMainTable
257      * @see #setMainTable
258      */
259     private SQLTable mainTable = null;
260 
261     /**
262      * All access sets  ids which are assigned to this type are store in this
263      * instance variable. If <code>null</code> the variable was not evaluated yet;
264      *
265      * @see #addAccessSet
266      * @see #getAccessSets
267      */
268     private final Set<Long> accessSets = new HashSet<Long>();
269 
270     /**
271      * Have the accessSet been evaluated.
272      */
273     private boolean checked4AccessSet = false;
274 
275     /**
276      * Have the children been evaluated.
277      */
278     private boolean checked4Children = false;
279 
280     /**
281      * Internal boolean to store if for this type was already checked if it is
282      * classified by an classification.
283      */
284     private boolean checked4classifiedBy = false;
285 
286     /**
287      * Stores all type of events which are allowed to fire on this type.
288      *
289      * @see #setLinkProperty
290      */
291     private final Set<Long> allowedEventTypes = new HashSet<Long>();
292 
293     /**
294      * Id of the store for this type.
295      */
296     private long storeId;
297 
298     /**
299      * Is the type abstract.
300      */
301     private boolean abstractBool;
302 
303     /**
304      * Are the instance of this type general also. Used as a TRISTATE
305      * <ol>
306      * <li>null = Inherit the value from the parent.</li>
307      * <li>true = The instance of this type are general too</li>
308      * <li>false = The instance are not general</li>
309      * </ol>
310      */
311     private Boolean generalInstance;
312 
313     /**
314      * Stores the name of attribute that contains the status of this type. (if
315      * exist)
316      */
317     private String statusAttributeName;
318 
319     /**
320      * Stores the name of attribute that contains the company of this type. (if
321      * exist)
322      */
323     private String companyAttributeName;
324 
325     /**
326      * Stores the name of attribute that contains the company of this type. (if
327      * exist)
328      */
329     private String groupAttributeName;
330 
331     /**
332      * Stores the name of attribute that contains the type of this type. (if
333      * exist)
334      */
335     private String typeAttributeName;
336 
337     /**
338      * Id of the Menu defined as TypeMenu for this Type.<br/>
339      * TRISTATE:<br/>
340      * <ul>
341      * <li>NULL: TypeMenu not evaluated yet</li>
342      * <li>0: has got no TypeMenu</li>
343      * <li>n: ID of the TypeMenu</li>
344      * </ul>
345      */
346     private Long typeMenu;
347 
348     /**
349      * Id of the Icon defined as TypeIcon for this Type.<br/>
350      * TRISTATE:<br/>
351      * <ul>
352      * <li>NULL: TypeIcon not evaluated yet</li>
353      * <li>0: has got no TypeMenu</li>
354      * <li>n: ID of the TypeMenu</li>
355      * </ul>
356      */
357     private Long typeIcon;
358 
359 
360     /**
361      * Id of the From defined as TypeFrom for this Type.<br/>
362      * TRISTATE:<br/>
363      * <ul>
364      * <li>NULL: TypeFrom not evaluated yet</li>
365      * <li>0: has got no TypeMenu</li>
366      * <li>n: ID of the TypeMenu</li>
367      * </ul>
368      */
369     private Long typeForm;
370 
371     /**
372      * This is the constructor for class Type. Every instance of class Type must
373      * have a name (parameter <i>_name</i>).
374      *
375      * @param _id id of th type
376      * @param _uuid universal unique identifier
377      * @param _name name of the type name of the instance
378      * @throws CacheReloadException on error
379      */
380     protected Type(final long _id,
381                    final String _uuid,
382                    final String _name)
383         throws CacheReloadException
384     {
385         super(_id, _uuid, _name);
386     }
387 
388     /**
389      * Getter method for instance variable {@link #abstractBool}.
390      *
391      * @return value of instance variable {@link #abstractBool}
392      */
393     public boolean isAbstract()
394     {
395         return this.abstractBool;
396     }
397 
398     /**
399      * Setter method for instance variable {@link #abstractBool}.
400      *
401      * @param _abstract value for instance variable {@link #abstractBool}
402      */
403     private void setAbstract(final boolean _abstract)
404     {
405         this.abstractBool = _abstract;
406     }
407 
408     /**
409      * Getter method for the instance variable {@link #generalInstance}.
410      *
411      * @return value of instance variable {@link #generalInstance}
412      */
413     public boolean isGeneralInstance()
414     {
415         boolean ret = true;
416         if (this.generalInstance != null) {
417             ret = this.generalInstance;
418         } else if (getParentType() != null) {
419             ret = getParentType().isGeneralInstance();
420         }
421         return ret;
422     }
423 
424     /**
425      * Setter method for instance variable {@link #generalInstance}.
426      *
427      * @param _generalInstance value for instance variable {@link #generalInstance}
428      */
429 
430     private void setGeneralInstance(final boolean _generalInstance)
431     {
432         this.generalInstance = _generalInstance;
433     }
434 
435     /**
436      * Add attributes to this type and all child types of this type.
437      * Recursive method.
438      * @param _inherited is the attribute inherited or form this type
439      * @param _attributes attributes to add
440      * @throws CacheReloadException on error
441      */
442     protected void addAttributes(final boolean _inherited,
443                                  final Attribute... _attributes)
444         throws CacheReloadException
445     {
446         for (final Attribute attribute : _attributes) {
447             if (!this.attributes.containsKey(attribute.getName())) {
448                 Type.LOG.trace("adding Attribute:'{}' to type: '{}'", attribute.getName(), getName());
449                 // evaluate for type attribute
450                 if (attribute.getAttributeType().getClassRepr().equals(TypeType.class)) {
451                     this.typeAttributeName = attribute.getName();
452                 } else if (attribute.getAttributeType().getClassRepr().equals(StatusType.class) && !_inherited) {
453                     // evaluate for status, an inherited attribute will not
454                     // overwrite the original attribute
455                     this.statusAttributeName = attribute.getName();
456                 } else if (attribute.getAttributeType().getClassRepr().equals(CompanyLinkType.class)
457                                 || attribute.getAttributeType().getClassRepr().equals(ConsortiumLinkType.class)) {
458                     // evaluate for company
459                     this.companyAttributeName = attribute.getName();
460                 } else if (attribute.getAttributeType().getClassRepr().equals(GroupLinkType.class)) {
461                     // evaluate for group
462                     this.groupAttributeName = attribute.getName();
463                 }
464                 this.attributes.put(attribute.getName(), attribute);
465                 if (attribute.getTable() != null) {
466                     this.tables.add(attribute.getTable());
467                     attribute.getTable().addType(getId());
468                     if (getMainTable() == null) {
469                         setMainTable(attribute.getTable());
470                     }
471                 }
472                 setDirty();
473             }
474         }
475     }
476 
477     /**
478      * Inherit Attributes are child types.
479      * @throws CacheReloadException on error
480      */
481     protected void inheritAttributes()
482         throws CacheReloadException
483     {
484         Type parent = getParentType();
485         final List<Attribute> attributesTmp = new ArrayList<Attribute>();
486         while (parent != null) {
487             for (final Attribute attribute : getParentType().getAttributes().values()) {
488                 attributesTmp.add(attribute.copy(getId()));
489             }
490             parent = parent.getParentType();
491         }
492         addAttributes(true, attributesTmp.toArray(new Attribute[attributesTmp.size()]));
493     }
494 
495     /**
496      * Getter method for instance variable {@link #statusAttribute}.
497      *
498      * @return value of instance variable {@link #statusAttribute}
499      */
500     public Attribute getStatusAttribute()
501     {
502         return this.attributes.get(this.statusAttributeName);
503     }
504 
505     /**
506      * Method to evaluate if the status must be checked on an accesscheck.
507      *
508      * @return true if {@link #statusAttribute} !=null , else false
509      */
510     public boolean isCheckStatus()
511     {
512         return this.statusAttributeName != null;
513     }
514 
515     /**
516      * Method to evaluate if this type depends on companies.
517      *
518      * @return true if {@link #companyAttribute} !=null , else false
519      */
520     public boolean isCompanyDepended()
521     {
522         return this.companyAttributeName != null;
523     }
524 
525     /**
526      * Method to evaluate if this type depends on companies.
527      *
528      * @return true if {@link #groupAttributeName} !=null , else false
529      */
530     public boolean isGroupDepended()
531     {
532         return this.groupAttributeName != null;
533     }
534 
535     /**
536      * Get the attribute containing the company information.
537      *
538      * @return attribute containing the company information
539      */
540     public Attribute getCompanyAttribute()
541     {
542         return this.attributes.get(this.companyAttributeName);
543     }
544 
545     /**
546      * Get the attribute containing the group information.
547      *
548      * @return attribute containing the group information
549      */
550     public Attribute getGroupAttribute()
551     {
552         return this.attributes.get(this.groupAttributeName);
553     }
554 
555     /**
556      * Get the attribute containing the type information.
557      *
558      * @return attribute containing the type information
559      */
560     public Attribute getTypeAttribute()
561     {
562         Attribute ret;
563         if (this.typeAttributeName == null && getParentType() != null) {
564             ret = getParentType().getTypeAttribute();
565         } else {
566             ret = this.attributes.get(this.typeAttributeName);
567         }
568         return ret;
569     }
570 
571     /**
572      * Returns for the given parameter <b>_name</b> the attribute.
573      *
574      * @param _name name of the attribute for this type to return
575      * @return instance of class {@link Attribute}
576      */
577     public final Attribute getAttribute(final String _name)
578     {
579         return getAttributes().get(_name);
580     }
581 
582     /**
583      * The instance method returns all attributes which are from the same
584      * attribute type as the described with the parameter <i>_class</i>.
585      *
586      * @param _class searched attribute type
587      * @return all attributes assigned from parameter <i>_class</i>
588      */
589     public final Set<Attribute> getAttributes(final Class<?> _class)
590     {
591         final Set<Attribute> ret = new HashSet<Attribute>();
592         for (final Attribute attr : getAttributes().values()) {
593             if (attr.getAttributeType().getClassRepr().isAssignableFrom(_class)) {
594                 ret.add(attr);
595             }
596         }
597         return ret;
598     }
599 
600     /**
601      * Tests, if this type is kind of the type in the parameter (question is, is
602      * this type a child of the parameter type).
603      *
604      * @param _type type to test for parent
605      * @return true if this type is a child, otherwise false
606      */
607     public boolean isKindOf(final Type _type)
608     {
609         boolean ret = false;
610         Type type = this;
611         while (type != null && type.getId() != _type.getId()) {
612             type = type.getParentType();
613         }
614         if (type != null && type.getId() == _type.getId()) {
615             ret = true;
616         }
617         return ret;
618     }
619 
620     /**
621      * Tests, if this type is kind of the type in the parameter (question is, is
622      * this type a child of the parameter type).
623      *
624      * @param _ciType CIType to test for parent
625      * @return true if this type is a child, otherwise false
626      */
627     public boolean isKindOf(final CIType _ciType)
628     {
629         return isKindOf(_ciType.getType());
630     }
631 
632     /**
633      * Tests, if this type is the given CIType.
634      *
635      * @param _ciType CIType to test for parent
636      * @return true if this type is a child, otherwise false
637      */
638     public boolean isCIType(final CIType _ciType)
639     {
640         return equals(_ciType.getType());
641     }
642 
643     /**
644      * Checks if the current type holds the property with the given name. If
645      * not, the value of the property of the parent type (see
646      * {@link #getParentType}) is returned (if a parent type exists).
647      *
648      * @param _name name of the property (key)
649      * @return value of the property with the given name / key.
650      * @see org.efaps.admin.AbstractAdminObject#getProperty
651      */
652     @Override
653     public String getProperty(final String _name)
654     {
655         String value = super.getProperty(_name);
656         if (value == null && getParentType() != null) {
657             value = getParentType().getProperty(_name);
658         }
659         return value;
660     }
661 
662 
663     /**
664      * Checks, if the current context user has all access defined in the list of
665      * access types for the given instance.
666      *
667      * @param _instance instance for which the access must be checked
668      * @param _accessType list of access types which must be checked
669      * @throws EFapsException on error
670      * @return true if user has access, else false
671      */
672     public boolean hasAccess(final Instance _instance,
673                              final AccessType _accessType)
674         throws EFapsException
675     {
676         return hasAccess(_instance, _accessType, null);
677     }
678 
679     /**
680      * Checks, if the current context user has all access defined in the list of
681      * access types for the given instance.
682      *
683      * @param _instance instance for which the access must be checked
684      * @param _accessType list of access types which must be checked
685      * @param _newValues objects that will be passed to esjp as <code>NEW_VALUES</code>
686      * @throws EFapsException on error
687      * @return true if user has access, else false
688      */
689     public boolean hasAccess(final Instance _instance,
690                              final AccessType _accessType,
691                              final Object _newValues)
692         throws EFapsException
693     {
694         boolean hasAccess = true;
695         final List<EventDefinition> events = super.getEvents(EventType.ACCESSCHECK);
696         if (events != null) {
697             final Parameter parameter = new Parameter();
698             parameter.put(ParameterValues.INSTANCE, _instance);
699             parameter.put(ParameterValues.ACCESSTYPE, _accessType);
700             parameter.put(ParameterValues.NEW_VALUES, _newValues);
701             parameter.put(ParameterValues.CLASS, this);
702 
703             for (final EventDefinition event : events) {
704                 final Return ret = event.execute(parameter);
705                 hasAccess = ret.get(ReturnValues.TRUE) != null;
706             }
707         }
708         return hasAccess;
709     }
710 
711     /**
712      * Method to check the access right for a list of instances.
713      *
714      * @param _instances list of instances
715      * @param _accessType access type
716      * @throws EFapsException on error
717      * @return Map of instances to boolean
718      */
719     @SuppressWarnings("unchecked")
720     public Map<Instance, Boolean> checkAccess(final List<Instance> _instances,
721                                               final AccessType _accessType)
722         throws EFapsException
723     {
724         Map<Instance, Boolean> ret = new HashMap<Instance, Boolean>();
725         if (_instances != null && !_instances.isEmpty() && _instances.size() == 1) {
726             final Instance instance = _instances.get(0);
727             ret.put(instance, hasAccess(instance, _accessType));
728         } else {
729             final List<EventDefinition> events = super.getEvents(EventType.ACCESSCHECK);
730             if (events != null) {
731                 final Parameter parameter = new Parameter();
732                 parameter.put(ParameterValues.OTHERS, _instances);
733                 parameter.put(ParameterValues.ACCESSTYPE, _accessType);
734                 parameter.put(ParameterValues.CLASS, this);
735                 for (final EventDefinition event : events) {
736                     final Return retrn = event.execute(parameter);
737                     ret = (Map<Instance, Boolean>) retrn.get(ReturnValues.VALUES);
738                 }
739             } else {
740                 for (final Instance instance : _instances) {
741                     ret.put(instance, true);
742                 }
743             }
744         }
745         return ret;
746     }
747 
748     /**
749      * @param _accessSet AccessSet to add to this Type
750      */
751     public void addAccessSet(final AccessSet _accessSet)
752     {
753         this.accessSets.add(_accessSet.getId());
754         setDirty();
755     }
756 
757     /**
758      * This is the getter method for instance variable {@link #accessSets}.
759      *
760      * @return value of instance variable {@link #accessSets}
761      * @see #accessSets
762      * @throws EFapsException on error
763      */
764     public Set<AccessSet> getAccessSets()
765         throws EFapsException
766     {
767         if (!this.checked4AccessSet) {
768             this.checked4AccessSet = true;
769             final QueryBuilder queryBldr = new QueryBuilder(CIAdminAccess.AccessSet2DataModelType);
770             queryBldr.addWhereAttrEqValue(CIAdminAccess.AccessSet2DataModelType.DataModelTypeLink, getId());
771             final MultiPrintQuery multi = queryBldr.getPrint();
772             multi.addAttribute(CIAdminAccess.AccessSet2DataModelType.AccessSetLink);
773             multi.executeWithoutAccessCheck();
774             while (multi.next()) {
775                 final Long accessSet = multi.<Long>getAttribute(CIAdminAccess.AccessSet2DataModelType.AccessSetLink);
776                 AccessSet.get(accessSet);
777                 this.accessSets.add(accessSet);
778             }
779             setDirty();
780         }
781         final Set<AccessSet> ret = new HashSet<AccessSet>();
782         for (final Long id : this.accessSets) {
783             ret.add(AccessSet.get(id));
784         }
785         return Collections.unmodifiableSet(ret);
786     }
787 
788     /**
789      * {@inheritDoc}
790      */
791     @Override
792     protected void setLinkProperty(final UUID _linkTypeUUID,
793                                    final long _toId,
794                                    final UUID _toTypeUUID,
795                                    final String _toName)
796         throws EFapsException
797     {
798         if (_linkTypeUUID.equals(CIAdminDataModel.Type2Store.uuid)) {
799             this.storeId = _toId;
800         } else if (_linkTypeUUID.equals(CIAdminDataModel.TypeEventIsAllowedFor.uuid)) {
801             this.allowedEventTypes.add(_toId);
802         }
803         super.setLinkProperty(_linkTypeUUID, _toId, _toTypeUUID, _toName);
804     }
805 
806     /**
807      * For the given type it is tested if a store is defined for the type.
808      *
809      * @return <i>true</i> if a store resource is defined for the type,
810      *         otherwise <i>false</i> is returned
811      */
812     public boolean hasStore()
813     {
814         return getStoreId() > 0 ? true : false;
815     }
816 
817     /**
818      * This is the getter method for instance variable {@link #parentType}.
819      *
820      * @return value of instance variable {@link #parentType}
821      * @see #parentType
822      * @see #setParentType
823      */
824     public Type getParentType()
825     {
826         Type ret = null;
827         if (this.parentTypeId != null && this.parentTypeId != 0) {
828             try {
829                 ret = Type.get(this.parentTypeId);
830             } catch (final CacheReloadException e) {
831                 Type.LOG.error("Could not read parentType for id: {}", this.parentTypeId);
832             }
833         }
834         return ret;
835     }
836 
837     /**
838      * Getter method for the instance variable {@link #parentTypeId}.
839      *
840      * @return value of instance variable {@link #parentTypeId}
841      */
842     protected Long getParentTypeId()
843     {
844         return this.parentTypeId;
845     }
846 
847     /**
848      * Setter method for instance variable {@link #parentType}.
849      *
850      * @param _parentTypeId parentid to set
851      */
852     protected void setParentTypeID(final long _parentTypeId)
853     {
854         this.parentTypeId = _parentTypeId;
855     }
856 
857     /**
858      * Add a root Classification to this type.
859      *
860      * @param _classification classifixation that classifies this type
861      */
862     protected void addClassifiedByType(final Classification _classification)
863     {
864         this.checked4classifiedBy = true;
865         this.classifiedByTypes.add(_classification.getId());
866         setDirty();
867     }
868 
869     /**
870      * Getter method for instance variable {@link #classifiedByTypes}.
871      * The method retrieves lazy the Classification Types.
872      * @return value of instance variable {@link #classifiedByTypes}
873      * @throws EFapsException on error
874      */
875     public Set<Classification> getClassifiedByTypes()
876         throws EFapsException
877     {
878         if (!this.checked4classifiedBy) {
879             final QueryBuilder attrQueryBldr = new QueryBuilder(CIAdminDataModel.TypeClassifies);
880             attrQueryBldr.addWhereAttrEqValue(CIAdminDataModel.TypeClassifies.To, getId());
881             final AttributeQuery attrQuery = attrQueryBldr.getAttributeQuery(CIAdminDataModel.TypeClassifies.From);
882             final QueryBuilder queryBldr = new QueryBuilder(CIAdminDataModel.Type);
883             queryBldr.addWhereAttrInQuery(CIAdminDataModel.Type.ID, attrQuery);
884             final InstanceQuery query = queryBldr.getQuery();
885             query.executeWithoutAccessCheck();
886             while (query.next()) {
887                 Type.get(query.getCurrentValue().getId());
888             }
889             this.checked4classifiedBy = true;
890             setDirty();
891         }
892         final Set<Classification> ret = new HashSet<Classification>();
893         if (getParentType() != null) {
894             ret.addAll(getParentType().getClassifiedByTypes());
895         }
896         for (final Long id : this.classifiedByTypes) {
897             ret.add((Classification) Type.get(id));
898         }
899         return Collections.unmodifiableSet(ret);
900     }
901 
902     /**
903      * This is the getter method for instance variable {@link #childTypes}.
904      *
905      * @return value of instance variable {@link #childTypes}
906      * @see #childTypes
907      * @throws CacheReloadException on error
908      */
909     public Set<Type> getChildTypes()
910         throws CacheReloadException
911     {
912         final Set<Type> ret = new HashSet<Type>();
913         for (final Long id : this.childTypes) {
914             final Type child = Type.get(id);
915             ret.add(child);
916             ret.addAll(child.getChildTypes());
917         }
918         return Collections.unmodifiableSet(ret);
919     }
920 
921     /**
922      * This is the getter method for instance variable {@link #attributes}.
923      *
924      * @return value of instance variable {@link #attributes}
925      * @see #attributes
926      */
927     public Map<String, Attribute> getAttributes()
928     {
929         return this.attributes;
930     }
931 
932     /**
933      * This is the getter method for instance variable {@link #tables}.
934      *
935      * @return value of instance variable {@link #tables}
936      * @see #tables
937      */
938     public Set<SQLTable> getTables()
939     {
940         return this.tables;
941     }
942 
943     /**
944      * This is the getter method for instance variable {@link #mainTable}.
945      *
946      * @return value of instance variable {@link #mainTable}
947      * @see #setMainTable
948      * @see #mainTable
949      */
950     public SQLTable getMainTable()
951     {
952         SQLTable ret = this.mainTable;
953         if (this.mainTable == null && getParentType() != null) {
954             ret = getParentType().getMainTable();
955         }
956         return ret;
957     }
958 
959     /**
960      * This is the setter method for instance variable {@link #mainTable}.
961      *
962      * @param _mainTable new value for instance variable {@link #mainTable}
963      * @see #getMainTable
964      * @see #mainTable
965      */
966     private void setMainTable(final SQLTable _mainTable)
967     {
968         SQLTable table = _mainTable;
969         while (table.getMainTable() != null) {
970             table = table.getMainTable();
971         }
972         this.mainTable = table;
973     }
974 
975     /**
976      * This is the getter method for instance variable
977      * {@link #allowedEventTypes}.
978      *
979      * @return value of instance variable {@link #allowedEventTypes}
980      * @see #allowedEventTypes
981      * @throws CacheReloadException on error
982      */
983     public Set<Type> getAllowedEventTypes()
984         throws CacheReloadException
985     {
986         final Set<Type> ret = new HashSet<Type>();
987         for (final Long id : this.allowedEventTypes) {
988             ret.add(Type.get(id));
989         }
990         return Collections.unmodifiableSet(ret);
991     }
992 
993     /**
994      * Getter method for instance variable {@link #storeId}.
995      *
996      * @return value of instance variable {@link #storeId}
997      */
998     public long getStoreId()
999     {
1000         final long ret;
1001         if (this.storeId == 0 && getParentType() != null) {
1002             ret = getParentType().getStoreId();
1003         } else {
1004             ret = this.storeId;
1005         }
1006         return ret;
1007     }
1008 
1009     /**
1010      * Method to get the key to the label.
1011      *
1012      * @return key to the label
1013      */
1014     public String getLabelKey()
1015     {
1016         final StringBuilder keyStr = new StringBuilder();
1017         return keyStr.append(getName()).append(".Label").toString();
1018     }
1019 
1020     /**
1021      * Method to get the translated label for this Status.
1022      *
1023      * @return translated Label
1024      */
1025     public String getLabel()
1026     {
1027         return DBProperties.getProperty(getLabelKey());
1028     }
1029 
1030     /**
1031      * @return the TypeMenu for this type
1032      * @throws EFapsException on errot
1033      */
1034     public Menu getTypeMenu()
1035         throws EFapsException
1036     {
1037         Menu ret = null;
1038         if (this.typeMenu == null) {
1039             final QueryBuilder queryBldr = new QueryBuilder(CIAdminUserInterface.LinkIsTypeTreeFor);
1040             queryBldr.addWhereAttrEqValue(CIAdminUserInterface.LinkIsTypeTreeFor.To, getId());
1041             final MultiPrintQuery multi = queryBldr.getPrint();
1042             multi.addAttribute(CIAdminUserInterface.LinkIsTypeTreeFor.From);
1043             multi.executeWithoutAccessCheck();
1044             if (multi.next()) {
1045                 final Long menuId = multi.<Long>getAttribute(CIAdminUserInterface.LinkIsTypeTreeFor.From);
1046                 ret = Menu.get(menuId);
1047                 if (ret != null) {
1048                     this.typeMenu = ret.getId();
1049                     ret.setTypeMenu(true);
1050                 } else {
1051                     this.typeMenu = Long.valueOf(0);
1052                 }
1053             } else {
1054                 this.typeMenu = Long.valueOf(0);
1055             }
1056             setDirty();
1057         }
1058         if (this.typeMenu == 0 && getParentType() != null) {
1059             ret = getParentType().getTypeMenu();
1060         } else {
1061             ret = Menu.get(this.typeMenu);
1062         }
1063         return ret;
1064     }
1065 
1066     /**
1067      * @return the TypeIcon for this type
1068      * @throws EFapsException on errot
1069      */
1070 
1071     public Image getTypeIcon()
1072         throws EFapsException
1073     {
1074         Image ret = null;
1075         if (this.typeIcon == null) {
1076             final QueryBuilder queryBldr = new QueryBuilder(CIAdminUserInterface.LinkIsTypeIconFor);
1077             queryBldr.addWhereAttrEqValue(CIAdminUserInterface.LinkIsTypeIconFor.To, getId());
1078             final MultiPrintQuery multi = queryBldr.getPrint();
1079             multi.addAttribute(CIAdminUserInterface.LinkIsTypeIconFor.From);
1080             multi.executeWithoutAccessCheck();
1081             if (multi.next()) {
1082                 final Long menuId = multi.<Long>getAttribute(CIAdminUserInterface.LinkIsTypeIconFor.From);
1083                 ret = Image.get(menuId);
1084                 if (ret != null) {
1085                     this.typeIcon = ret.getId();
1086                 } else {
1087                     this.typeIcon = Long.valueOf(0);
1088                 }
1089             } else {
1090                 this.typeIcon = Long.valueOf(0);
1091             }
1092             setDirty();
1093         }
1094         if (this.typeIcon == 0 && getParentType() != null) {
1095             ret = getParentType().getTypeIcon();
1096         } else {
1097             ret = Image.get(this.typeIcon);
1098         }
1099         return ret;
1100     }
1101 
1102     /**
1103      * @return the TypeFrom for this type
1104      * @throws EFapsException on errot
1105      */
1106     public Form getTypeForm()
1107         throws EFapsException
1108     {
1109         Form ret = null;
1110         if (this.typeForm == null) {
1111             final QueryBuilder queryBldr = new QueryBuilder(CIAdminUserInterface.LinkIsTypeFormFor);
1112             queryBldr.addWhereAttrEqValue(CIAdminUserInterface.LinkIsTypeFormFor.To, getId());
1113             final MultiPrintQuery multi = queryBldr.getPrint();
1114             multi.addAttribute(CIAdminUserInterface.LinkIsTypeFormFor.From);
1115             multi.executeWithoutAccessCheck();
1116             if (multi.next()) {
1117                 final Long formId = multi.<Long>getAttribute(CIAdminUserInterface.LinkIsTypeFormFor.From);
1118                 ret = Form.get(formId);
1119                 if (ret != null) {
1120                     this.typeForm = ret.getId();
1121                 } else {
1122                     this.typeForm = Long.valueOf(0);
1123                 }
1124             } else {
1125                 this.typeForm = Long.valueOf(0);
1126             }
1127             setDirty();
1128         }
1129         if (this.typeForm == 0 && getParentType() != null) {
1130              ret = getParentType().getTypeForm();
1131         } else {
1132             ret = Form.get(this.typeForm);
1133         }
1134         return ret;
1135     }
1136 
1137     /**
1138      * The method overrides the original method 'toString' and returns
1139      * information about this type instance.
1140      *
1141      * @return name of the user interface object
1142      */
1143     @Override
1144     public String toString()
1145     {
1146         return new ToStringBuilder(this).appendSuper(super.toString())
1147                         .append("parentTypeId", this.parentTypeId)
1148                         .append("attributes", this.attributes.size())
1149                         .append("children", this.childTypes.size())
1150                         .append("abstract", this.abstractBool)
1151                         .append("accessSets", this.accessSets.size())
1152                         .append("companyDependend", isCompanyDepended())
1153                         .append("groupDependend", isGroupDepended())
1154                         .append("statusDependend", isCheckStatus())
1155                         .append("checked4AccessSet", this.checked4AccessSet)
1156                         .append("checked4Children", this.checked4Children)
1157                         .append("checked4classifiedBy", this.checked4classifiedBy)
1158                         .append("dirty", isDirty())
1159                         .toString();
1160     }
1161 
1162     @Override
1163     public boolean equals(final Object _obj)
1164     {
1165         boolean ret;
1166         if (_obj instanceof Type) {
1167             ret = ((Type) _obj).getId() == getId();
1168         } else {
1169             ret = super.equals(_obj);
1170         }
1171         return ret;
1172     }
1173 
1174     @Override
1175     public int hashCode()
1176     {
1177         return Long.valueOf(getId()).intValue();
1178     }
1179 
1180     /**
1181      * Method to initialize the Cache of this CacheObjectInterface.
1182      *
1183      * @param _class class that called the method
1184      * @throws CacheReloadException on error
1185      */
1186     public static void initialize(final Class<?> _class)
1187         throws CacheReloadException
1188     {
1189         if (InfinispanCache.get().exists(Type.UUIDCACHE)) {
1190             InfinispanCache.get().<UUID, Type>getCache(Type.UUIDCACHE).clear();
1191         } else {
1192             InfinispanCache.get().<UUID, Type>getCache(Type.UUIDCACHE).addListener(new CacheLogListener(Type.LOG));
1193         }
1194         if (InfinispanCache.get().exists(Type.IDCACHE)) {
1195             InfinispanCache.get().<Long, Type>getCache(Type.IDCACHE).clear();
1196         } else {
1197             InfinispanCache.get().<Long, Type>getCache(Type.IDCACHE).addListener(new CacheLogListener(Type.LOG));
1198         }
1199         if (InfinispanCache.get().exists(Type.NAMECACHE)) {
1200             InfinispanCache.get().<String, Type>getCache(Type.NAMECACHE).clear();
1201         } else {
1202             InfinispanCache.get().<String, Type>getCache(Type.NAMECACHE).addListener(new CacheLogListener(Type.LOG));
1203         }
1204         if (InfinispanCache.get().exists(EnumType.CACHE)) {
1205             InfinispanCache.get().getCache(EnumType.CACHE).clear();
1206         }
1207         QueryCache.initialize();
1208     }
1209 
1210     /**
1211      * Method to initialize the Cache of this CacheObjectInterface.
1212      *
1213      * @throws CacheReloadException on error
1214      */
1215     public static void initialize()
1216         throws CacheReloadException
1217     {
1218         Type.initialize(Type.class);
1219     }
1220 
1221     /**
1222      * Returns for given parameter <i>_id</i> the instance of class {@link Type}
1223      * .
1224      *
1225      * @param _id id of the type to get
1226      * @return instance of class {@link Type}
1227      * @throws CacheReloadException on error
1228      */
1229     public static Type get(final long _id)
1230         throws CacheReloadException
1231     {
1232         final Cache<Long, Type> cache = InfinispanCache.get().<Long, Type>getCache(Type.IDCACHE);
1233         if (!cache.containsKey(_id)) {
1234             Type.getTypeFromDB(Type.SQL_ID, _id);
1235         }
1236         Type ret = cache.get(_id);
1237         if (ret != null && ret.isDirty()) {
1238             Type.LOG.debug("Recaching dirty Type for id: {}", ret);
1239             Type.cacheType(ret);
1240             ret = cache.get(_id);
1241         }
1242         return ret;
1243     }
1244 
1245     /**
1246      * Returns for given parameter <i>_name</i> the instance of class
1247      * {@link Type}.
1248      *
1249      * @param _name name of the type to get
1250      * @return instance of class {@link Type}
1251      * @throws CacheReloadException on error
1252      */
1253     public static Type get(final String _name)
1254         throws CacheReloadException
1255     {
1256         final Cache<String, Type> cache = InfinispanCache.get().<String, Type>getCache(Type.NAMECACHE);
1257         if (!cache.containsKey(_name)) {
1258             Type.getTypeFromDB(Type.SQL_NAME, _name);
1259         }
1260         Type ret = cache.get(_name);
1261         if (ret != null && ret.isDirty()) {
1262             Type.LOG.debug("Recaching dirty Type for name: {}", ret);
1263             Type.cacheType(ret);
1264             ret = cache.get(_name);
1265         }
1266         return ret;
1267     }
1268 
1269     /**
1270      * Returns for given parameter <i>_uuid</i> the instance of class
1271      * {@link Type}.
1272      *
1273      * @param _uuid uuid of the type to get
1274      * @return instance of class {@link Type}
1275      * @throws CacheReloadException on error
1276      */
1277     public static Type get(final UUID _uuid)
1278         throws CacheReloadException
1279     {
1280         final Cache<UUID, Type> cache = InfinispanCache.get().<UUID, Type>getCache(Type.UUIDCACHE);
1281         if (!cache.containsKey(_uuid)) {
1282             Type.getTypeFromDB(Type.SQL_UUID, _uuid.toString());
1283         }
1284         Type ret = cache.get(_uuid);
1285         if (ret != null && ret.isDirty()) {
1286             Type.LOG.debug("Recaching dirty Type for uuid: {}", ret);
1287             Type.cacheType(ret);
1288             ret = cache.get(_uuid);
1289         }
1290         return ret;
1291     }
1292 
1293     /**
1294      * @param _type type to be cached
1295      */
1296     protected static void cacheType(final Type _type)
1297     {
1298         _type.setUndirty();
1299         final Cache<UUID, Type> cache4UUID = InfinispanCache.get().<UUID, Type>getIgnReCache(Type.UUIDCACHE);
1300         cache4UUID.put(_type.getUUID(), _type);
1301 
1302         final Cache<String, Type> nameCache = InfinispanCache.get().<String, Type>getIgnReCache(Type.NAMECACHE);
1303         nameCache.put(_type.getName(), _type);
1304 
1305         final Cache<Long, Type> idCache = InfinispanCache.get().<Long, Type>getIgnReCache(Type.IDCACHE);
1306         idCache.put(_type.getId(), _type);
1307     }
1308 
1309     /**
1310      * In case of a cluster the types must be cached after the final loading
1311      * again to be sure that the last instance including all the changes like
1312      * attribute links etc are up to date.
1313      *
1314      * @param _type Type the Hierachy must be cached
1315      * @throws CacheReloadException on error
1316      */
1317     protected static void cacheTypesByHierachy(final Type _type)
1318         throws CacheReloadException
1319     {
1320         final Cache<UUID, Type> cache4UUID = InfinispanCache.get().<UUID, Type>getIgnReCache(Type.UUIDCACHE);
1321         if (cache4UUID.getCacheConfiguration().clustering() != null
1322                         && !cache4UUID.getCacheConfiguration().clustering().cacheMode().equals(CacheMode.LOCAL)) {
1323             Type type = _type;
1324             while (type.getParentTypeId() != null) {
1325                 final Cache<Long, Type> cache = InfinispanCache.get().<Long, Type>getIgnReCache(Type.IDCACHE);
1326                 if (cache.containsKey(type.getParentTypeId())) {
1327                     type = cache.get(type.getParentTypeId());
1328                 } else {
1329                     type = type.getParentType();
1330                 }
1331             }
1332             type.recacheChildren();
1333         }
1334     }
1335 
1336     /**
1337      * Recache the children in dropdown. Used for Caching in cluster.
1338      * @throws CacheReloadException on error
1339      */
1340     private void recacheChildren()
1341         throws CacheReloadException
1342     {
1343         if (isDirty()) {
1344             Type.cacheType(this);
1345         }
1346         for (final Type child : getChildTypes()) {
1347             child.recacheChildren();
1348         }
1349     }
1350 
1351     /**
1352      * @param _parentID id to be searched for
1353      * @param _statement statement to be executed
1354      * @return a list of object containing the id and the purpose
1355      * @throws CacheReloadException on error
1356      */
1357     private static List<Object[]> getChildTypeIDs(final long _parentID,
1358                                                   final String _statement)
1359         throws CacheReloadException
1360     {
1361         final List<Object[]> ret = new ArrayList<Object[]>();
1362         ConnectionResource con = null;
1363         try {
1364             con = Context.getThreadContext().getConnectionResource();
1365             PreparedStatement stmt = null;
1366             try {
1367                 stmt = con.getConnection().prepareStatement(_statement);
1368                 stmt.setObject(1, _parentID);
1369                 final ResultSet rs = stmt.executeQuery();
1370                 while (rs.next()) {
1371                     ret.add(new Object[] { rs.getLong(1), rs.getInt(2) });
1372                 }
1373                 rs.close();
1374             } finally {
1375                 if (stmt != null) {
1376                     stmt.close();
1377                 }
1378             }
1379             con.commit();
1380         } catch (final SQLException e) {
1381             throw new CacheReloadException("could not read child type ids", e);
1382         } catch (final EFapsException e) {
1383             throw new CacheReloadException("could not read child type ids", e);
1384         } finally {
1385             if (con != null && con.isOpened()) {
1386                 try {
1387                     con.abort();
1388                 } catch (final EFapsException e) {
1389                     throw new CacheReloadException("could not read child type ids", e);
1390                 }
1391             }
1392         }
1393         return ret;
1394     }
1395 
1396     /**
1397      * @param _sql SQLStatement to be executed
1398      * @param _criteria the filter criteria
1399      * @return Type instance
1400      * @throws CacheReloadException on error
1401      */
1402     private static Type getTypeFromDB(final String _sql,
1403                                       final Object _criteria)
1404         throws CacheReloadException
1405     {
1406         Type ret = null;
1407         ConnectionResource con = null;
1408         try {
1409             con = Context.getThreadContext().getConnectionResource();
1410             final PreparedStatement stmt = con.getConnection().prepareStatement(_sql);
1411             stmt.setObject(1, _criteria);
1412             final ResultSet rs = stmt.executeQuery();
1413             long parentTypeId = 0;
1414             long parentClassTypeId = 0;
1415             long id = 0;
1416 
1417             if (rs.next()) {
1418                 id = rs.getLong(1);
1419                 final String uuid = rs.getString(2).trim();
1420                 final String name = rs.getString(3).trim();
1421                 final int purpose = rs.getInt(4);
1422                 parentTypeId = rs.getLong(5);
1423                 parentClassTypeId = rs.getLong(6);
1424 
1425                 Type.LOG.debug("read type '{}' (id = {}) (purpose = {}) (parentTypeId = {}) (parentClassTypeId = {})",
1426                                 name, id, purpose, parentTypeId, parentClassTypeId);
1427 
1428                 if (BitEnumType.isSelected(purpose, Type.Purpose.CLASSIFICATION)) {
1429                     ret = new Classification(id, uuid, name);
1430                     if (parentClassTypeId != 0) {
1431                         ((Classification) ret).setParentClassification(parentClassTypeId);
1432                     }
1433                 } else {
1434                     ret = new Type(id, uuid, name);
1435                 }
1436                 if (parentTypeId != 0) {
1437                     ret.setParentTypeID(parentTypeId);
1438                 }
1439                 ret.setAbstract(BitEnumType.isSelected(purpose, Type.Purpose.ABSTRACT));
1440 
1441                 if (BitEnumType.isSelected(purpose, Type.Purpose.GENERALINSTANCE)) {
1442                     ret.setGeneralInstance(true);
1443                 }
1444                 if (BitEnumType.isSelected(purpose, Type.Purpose.NOGENERALINSTANCE)) {
1445                     ret.setGeneralInstance(false);
1446                 }
1447             }
1448             rs.close();
1449             stmt.close();
1450             con.commit();
1451             if (ret != null) {
1452                 if (parentTypeId != 0) {
1453                     Type.LOG.trace("get parent for id = {}",  parentTypeId);
1454                     final Type parent = Type.get(parentTypeId);
1455                     // TODO: test if loop
1456                     if (ret.getId() == parent.getId()) {
1457                         throw new CacheReloadException("child and parent type is equal!child is " + ret);
1458                     }
1459                 }
1460                 if (!ret.checked4Children) {
1461                     ret.checked4Children = true;
1462                     for (final Object[] childIDs : Type.getChildTypeIDs(ret.getId(), Type.SQL_CHILD)) {
1463                         Type.LOG.trace("reading Child Type with id: {} for type :{}", childIDs[0], ret.getName());
1464                         ret.childTypes.add((Long) childIDs[0]);
1465                     }
1466                     if (ret instanceof Classification) {
1467                         for (final Object[] childIDs : Type.getChildTypeIDs(ret.getId(), Type.SQL_CLASSCHILD)) {
1468                             Type.LOG.trace("reading Child class Type with id: {} for type :{}",
1469                                             childIDs[0], ret.getName());
1470                             ((Classification) ret).getChildren().add((Long) childIDs[0]);
1471                         }
1472                     }
1473                     ret.setDirty();
1474                 }
1475                 Attribute.add4Type(ret);
1476                 ret.readFromDB4Links();
1477                 ret.readFromDB4Properties();
1478                 ret.inheritAttributes();
1479                 // needed due to cluster serialization that does not update automatically
1480                 Type.cacheType(ret);
1481                 Type.LOG.trace("ended reading type '{}'", ret.getName());
1482             }
1483         } catch (final EFapsException e) {
1484             Type.LOG.error("initialiseCache()", e);
1485         } catch (final SQLException e) {
1486             Type.LOG.error("initialiseCache()", e);
1487         } finally {
1488             if (con != null && con.isOpened()) {
1489                 try {
1490                     con.abort();
1491                 } catch (final EFapsException e) {
1492                     throw new CacheReloadException("could not read child tyep ids", e);
1493                 }
1494             }
1495         }
1496         return ret;
1497     }
1498 
1499     /**
1500      * Compares a given id and uuid of a type to evaluate if they are from the
1501      * same Type. In case that they are not cached (during initialize) teh
1502      * database is requested.
1503      *
1504      * @param _typeId Id of the type to be checked
1505      * @param _typeUUID uuid of the type to be checked
1506      * @return true if the id and the uuid belong to the same type
1507      * @throws CacheReloadException on error
1508      */
1509     protected static boolean check4Type(final long _typeId,
1510                                         final UUID _typeUUID)
1511         throws CacheReloadException
1512     {
1513         boolean ret = false;
1514         final Cache<Long, Type> cache = InfinispanCache.get().<Long, Type>getCache(Type.IDCACHE);
1515         if (cache.containsKey(_typeId)) {
1516             ret = cache.get(_typeId).getUUID().equals(_typeUUID);
1517         } else {
1518             ConnectionResource con = null;
1519             String uuidTmp = "";
1520             try {
1521                 con = Context.getThreadContext().getConnectionResource();
1522                 PreparedStatement stmt = null;
1523                 try {
1524                     stmt = con.getConnection().prepareStatement(Type.SQL_ID);
1525                     stmt.setObject(1, _typeId);
1526                     final ResultSet rs = stmt.executeQuery();
1527                     while (rs.next()) {
1528                         uuidTmp = rs.getString(2).trim();
1529                     }
1530                     rs.close();
1531                 } finally {
1532                     if (stmt != null) {
1533                         stmt.close();
1534                     }
1535                 }
1536                 con.commit();
1537             } catch (final SQLException e) {
1538                 throw new CacheReloadException("could not read child type ids", e);
1539             } catch (final EFapsException e) {
1540                 throw new CacheReloadException("could not read child type ids", e);
1541             } finally {
1542                 if (con != null && con.isOpened()) {
1543                     try {
1544                         con.abort();
1545                     } catch (final EFapsException e) {
1546                         throw new CacheReloadException("could not read child type ids", e);
1547                     }
1548                 }
1549             }
1550             ret = UUID.fromString(uuidTmp).equals(_typeUUID);
1551         }
1552         return ret;
1553     }
1554 
1555     /**
1556      * During the initial caching of types, the mapping does not exists but is necessary.
1557      * @param _typeUUID UUID of the type the id is wanted for
1558      * @return id of the type
1559      * @throws CacheReloadException on error
1560      */
1561     protected static long getId4UUID(final UUID _typeUUID)
1562         throws CacheReloadException
1563     {
1564         long ret = 0;
1565         final Cache<UUID, Type> cache = InfinispanCache.get().<UUID, Type>getCache(Type.UUIDCACHE);
1566         if (cache.containsKey(_typeUUID)) {
1567             ret = cache.get(_typeUUID).getId();
1568         } else {
1569             ConnectionResource con = null;
1570             try {
1571                 con = Context.getThreadContext().getConnectionResource();
1572                 PreparedStatement stmt = null;
1573                 try {
1574                     stmt = con.getConnection().prepareStatement(Type.SQL_UUID);
1575                     stmt.setObject(1, _typeUUID.toString());
1576                     final ResultSet rs = stmt.executeQuery();
1577                     while (rs.next()) {
1578                         ret = rs.getLong(1);
1579                     }
1580                     rs.close();
1581                 } finally {
1582                     if (stmt != null) {
1583                         stmt.close();
1584                     }
1585                 }
1586                 con.commit();
1587             } catch (final SQLException e) {
1588                 throw new CacheReloadException("could not read child type ids", e);
1589             } catch (final EFapsException e) {
1590                 throw new CacheReloadException("could not read child type ids", e);
1591             } finally {
1592                 if (con != null && con.isOpened()) {
1593                     try {
1594                         con.abort();
1595                     } catch (final EFapsException e) {
1596                         throw new CacheReloadException("could not read child type ids", e);
1597                     }
1598                 }
1599             }
1600         }
1601         return ret;
1602     }
1603 
1604     /**
1605      * During the initial caching of types, the mapping does not exists but is necessary.
1606      * @param _typeId id of the type the UUID is wanted for
1607      * @return id of the type
1608      * @throws CacheReloadException on error
1609      */
1610     public static UUID getUUID4Id(final long _typeId)
1611         throws CacheReloadException
1612     {
1613         UUID ret = null;
1614         final Cache<Long, Type> cache = InfinispanCache.get().<Long, Type>getCache(Type.IDCACHE);
1615         if (cache.containsKey(_typeId)) {
1616             ret = cache.get(_typeId).getUUID();
1617         } else {
1618             ConnectionResource con = null;
1619             try {
1620                 con = Context.getThreadContext().getConnectionResource();
1621                 PreparedStatement stmt = null;
1622                 try {
1623                     stmt = con.getConnection().prepareStatement(Type.SQL_ID);
1624                     stmt.setObject(1, _typeId);
1625                     final ResultSet rs = stmt.executeQuery();
1626                     while (rs.next()) {
1627                         ret = UUID.fromString(rs.getString(2).trim());
1628                     }
1629                     rs.close();
1630                 } finally {
1631                     if (stmt != null) {
1632                         stmt.close();
1633                     }
1634                 }
1635                 con.commit();
1636             } catch (final SQLException e) {
1637                 throw new CacheReloadException("could not read child type ids", e);
1638             } catch (final EFapsException e) {
1639                 throw new CacheReloadException("could not read child type ids", e);
1640             } finally {
1641                 if (con != null && con.isOpened()) {
1642                     try {
1643                         con.abort();
1644                     } catch (final EFapsException e) {
1645                         throw new CacheReloadException("could not read child type ids", e);
1646                     }
1647                 }
1648             }
1649         }
1650         return ret;
1651     }
1652 
1653     /**
1654      * @return
1655      */
1656     public static boolean isInitialized()
1657     {
1658         final Cache<Long, Type> cache1 = InfinispanCache.get().<Long, Type>getCache(Type.IDCACHE);
1659         final Cache<String, Type> cache2 = InfinispanCache.get().<String, Type>getCache(Type.NAMECACHE);
1660         final Cache<UUID, Type> cache3 = InfinispanCache.get().<UUID, Type>getCache(Type.UUIDCACHE);
1661         return !cache1.isEmpty() || !cache2.isEmpty() || !cache3.isEmpty();
1662     }
1663 
1664 }