View Javadoc
1   /**
2    * Copyright 2014 Internet2
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  /**
17   * 
18   */
19  package edu.internet2.middleware.grouper.attr;
20  
21  import java.io.StringWriter;
22  import java.sql.Timestamp;
23  import java.util.LinkedHashSet;
24  import java.util.Set;
25  
26  import org.apache.commons.lang.ObjectUtils;
27  import org.apache.commons.lang.StringUtils;
28  import org.apache.commons.lang.builder.ToStringBuilder;
29  import org.apache.commons.logging.Log;
30  
31  import edu.internet2.middleware.grouper.GrouperAPI;
32  import edu.internet2.middleware.grouper.GrouperSession;
33  import edu.internet2.middleware.grouper.Member;
34  import edu.internet2.middleware.grouper.MemberFinder;
35  import edu.internet2.middleware.grouper.Stem;
36  import edu.internet2.middleware.grouper.StemFinder;
37  import edu.internet2.middleware.grouper.annotations.GrouperIgnoreClone;
38  import edu.internet2.middleware.grouper.annotations.GrouperIgnoreDbVersion;
39  import edu.internet2.middleware.grouper.annotations.GrouperIgnoreFieldConstant;
40  import edu.internet2.middleware.grouper.attr.assign.AttributeAssign;
41  import edu.internet2.middleware.grouper.attr.assign.AttributeAssignAttributeDefDelegate;
42  import edu.internet2.middleware.grouper.attr.assign.AttributeAssignType;
43  import edu.internet2.middleware.grouper.attr.assign.AttributeAssignable;
44  import edu.internet2.middleware.grouper.attr.assign.AttributeDefActionDelegate;
45  import edu.internet2.middleware.grouper.attr.finder.AttributeDefFinder;
46  import edu.internet2.middleware.grouper.attr.value.AttributeValueDelegate;
47  import edu.internet2.middleware.grouper.audit.AuditEntry;
48  import edu.internet2.middleware.grouper.audit.AuditTypeBuiltin;
49  import edu.internet2.middleware.grouper.cfg.GrouperConfig;
50  import edu.internet2.middleware.grouper.changeLog.ChangeLogEntry;
51  import edu.internet2.middleware.grouper.changeLog.ChangeLogLabels;
52  import edu.internet2.middleware.grouper.changeLog.ChangeLogTypeBuiltin;
53  import edu.internet2.middleware.grouper.ddl.GrouperDdlUtils;
54  import edu.internet2.middleware.grouper.exception.GrouperException;
55  import edu.internet2.middleware.grouper.exception.GrouperSessionException;
56  import edu.internet2.middleware.grouper.exception.GrouperValidationException;
57  import edu.internet2.middleware.grouper.exception.InsufficientPrivilegeException;
58  import edu.internet2.middleware.grouper.hibernate.AuditControl;
59  import edu.internet2.middleware.grouper.hibernate.GrouperTransactionType;
60  import edu.internet2.middleware.grouper.hibernate.HibernateHandler;
61  import edu.internet2.middleware.grouper.hibernate.HibernateHandlerBean;
62  import edu.internet2.middleware.grouper.hibernate.HibernateSession;
63  import edu.internet2.middleware.grouper.hooks.AttributeDefHooks;
64  import edu.internet2.middleware.grouper.hooks.beans.HooksAttributeDefBean;
65  import edu.internet2.middleware.grouper.hooks.logic.GrouperHookType;
66  import edu.internet2.middleware.grouper.hooks.logic.GrouperHooksUtils;
67  import edu.internet2.middleware.grouper.hooks.logic.VetoTypeGrouper;
68  import edu.internet2.middleware.grouper.internal.dao.GrouperDAOException;
69  import edu.internet2.middleware.grouper.internal.dao.QueryOptions;
70  import edu.internet2.middleware.grouper.internal.dao.hib3.Hib3AttributeDefDAO;
71  import edu.internet2.middleware.grouper.internal.dao.hib3.Hib3GrouperVersioned;
72  import edu.internet2.middleware.grouper.misc.GrouperDAOFactory;
73  import edu.internet2.middleware.grouper.misc.GrouperHasContext;
74  import edu.internet2.middleware.grouper.misc.GrouperObject;
75  import edu.internet2.middleware.grouper.misc.GrouperSessionHandler;
76  import edu.internet2.middleware.grouper.misc.GrouperVersion;
77  import edu.internet2.middleware.grouper.misc.Owner;
78  import edu.internet2.middleware.grouper.rules.RuleDefinition;
79  import edu.internet2.middleware.grouper.rules.RuleEngine;
80  import edu.internet2.middleware.grouper.rules.RuleUtils;
81  import edu.internet2.middleware.grouper.tableIndex.TableIndex;
82  import edu.internet2.middleware.grouper.tableIndex.TableIndexType;
83  import edu.internet2.middleware.grouper.util.GrouperUtil;
84  import edu.internet2.middleware.grouper.xml.export.XmlExportAttributeDef;
85  import edu.internet2.middleware.grouper.xml.export.XmlImportable;
86  import edu.internet2.middleware.subject.Subject;
87  
88  
89  /**
90   * definition of an attribute
91   * @author mchyzer
92   *
93   */
94  @SuppressWarnings("serial")
95  public class AttributeDef extends GrouperAPI implements GrouperObject, GrouperHasContext, 
96      Hib3GrouperVersioned, Owner, XmlImportable<AttributeDef>, AttributeAssignable, Comparable<GrouperObject> {
97  
98    /**
99     * get the name of the parent stem
100    * @return the name of the parent stem
101    */
102   public String getParentStemName() {
103     return GrouperUtil.parentStemNameFromName(this.getName(), false);
104   } 
105 
106   /**
107    * 
108    */
109   public static final String VALIDATION_NAME_OF_ATTRIBUTE_DEF_TOO_LONG_KEY = "nameOfAttributeDefTooLong";
110 
111   /**
112    * 
113    */
114   public static final String VALIDATION_EXTENSION_OF_ATTRIBUTE_DEF_TOO_LONG_KEY = "extensionOfAttributeDefTooLong";
115 
116   /**
117    * 
118    */
119   public static final String VALIDATION_DESCRIPTION_OF_ATTRIBUTE_DEF_TOO_LONG_KEY = "descriptionOfAttributeDefTooLong";
120 
121 
122   /**
123    * attribute defs dont have display extensions or name, so change them to extension and name
124    * @param sortField
125    * @return the new sort field
126    */
127   public static String massageSortField(String sortField) {
128     //there is no display extension in attributeDef
129     if (StringUtils.equalsIgnoreCase("displayExtension", sortField)) {
130       return "extension";
131     }
132     //there is no name in attributeDef
133     if (StringUtils.equalsIgnoreCase("displayName", sortField)) {
134       return "name";
135     }
136     return sortField;
137 
138   }
139   
140   /** default action */
141   public static final String ACTION_DEFAULT = "assign";
142 
143   /** logger */
144   private static final Log LOG = GrouperUtil.getLog(AttributeDef.class);
145 
146   /** name of the groups attribute def table in the db */
147   public static final String TABLE_GROUPER_ATTRIBUTE_DEF = "grouper_attribute_def";
148 
149   /** constant for column for: assign_to_attribute_def */
150   public static final String COLUMN_ASSIGN_TO_ATTRIBUTE_DEF  = "assign_to_attribute_def";
151   
152   /** constant for column for: assign_to_attribute_def_assn */
153   public static final String COLUMN_ASSIGN_TO_ATTRIBUTE_DEF_ASSN  = "assign_to_attribute_def_assn";
154   
155   /** constant for column for: assign_to_eff_membership */
156   public static final String COLUMN_ASSIGN_TO_EFF_MEMBERSHIP  = "assign_to_eff_membership";
157   
158   /** constant for column for: assign_to_eff_membership_assn */
159   public static final String COLUMN_ASSIGN_TO_EFF_MEMBERSHIP_ASSN  = "assign_to_eff_membership_assn";
160   
161   /** constant for column for: assign_to_group */
162   public static final String COLUMN_ASSIGN_TO_GROUP  = "assign_to_group";
163   
164   /** constant for column for: assign_to_group_assn */
165   public static final String COLUMN_ASSIGN_TO_GROUP_ASSN  = "assign_to_group_assn";
166   
167   /** constant for column for: assign_to_imm_membership */
168   public static final String COLUMN_ASSIGN_TO_IMM_MEMBERSHIP  = "assign_to_imm_membership";
169   
170   /** constant for column for: assign_to_imm_membership_assn */
171   public static final String COLUMN_ASSIGN_TO_IMM_MEMBERSHIP_ASSN  = "assign_to_imm_membership_assn";
172   
173   /** constant for column for: assign_to_member */
174   public static final String COLUMN_ASSIGN_TO_MEMBER  = "assign_to_member";
175   
176   /** constant for column for: assign_to_member_assn */
177   public static final String COLUMN_ASSIGN_TO_MEMBER_ASSN  = "assign_to_member_assn";
178   
179   /** constant for column for: assign_to_stem */
180   public static final String COLUMN_ASSIGN_TO_STEM  = "assign_to_stem";
181   
182   /** constant for column for: assign_to_stem_assn */
183   public static final String COLUMN_ASSIGN_TO_STEM_ASSN = "assign_to_stem_assn";
184 
185 
186   
187   /** if the attribute def is public */
188   public static final String COLUMN_ATTRIBUTE_DEF_PUBLIC = "attribute_def_public";
189 
190   /** column */
191   public static final String COLUMN_ATTRIBUTE_DEF_TYPE = "attribute_def_type";
192 
193   /** column */
194   public static final String COLUMN_CONTEXT_ID = "context_id";
195 
196   /** column */
197   public static final String COLUMN_CREATED_ON = "created_on";
198 
199   /** column */
200   public static final String COLUMN_CREATOR_ID = "creator_id";
201 
202   /** column */
203   public static final String COLUMN_LAST_UPDATED = "last_updated";
204 
205   /** column */
206   public static final String COLUMN_DESCRIPTION = "description";
207 
208   /** column */
209   public static final String COLUMN_EXTENSION = "extension";
210 
211   /** column */
212   public static final String COLUMN_NAME = "name";
213 
214   /** column */
215   public static final String COLUMN_MULTI_ASSIGNABLE = "multi_assignable";
216 
217   /** column */
218   public static final String COLUMN_MULTI_VALUED = "multi_valued";
219 
220   /** column */
221   public static final String COLUMN_STEM_ID = "stem_id";
222 
223   /** column */
224   public static final String COLUMN_VALUE_TYPE = "value_type";
225 
226   /** column */
227   public static final String COLUMN_ID = "id";
228 
229   /** unique number for this attribute def */
230   public static final String COLUMN_ID_INDEX = "id_index";
231   
232   //*****  START GENERATED WITH GenerateFieldConstants.java *****//
233 
234   /** constant for field name for: assignToAttributeDef */
235   public static final String FIELD_ASSIGN_TO_ATTRIBUTE_DEF = "assignToAttributeDef";
236 
237   /** constant for field name for: assignToAttributeDefAssn */
238   public static final String FIELD_ASSIGN_TO_ATTRIBUTE_DEF_ASSN = "assignToAttributeDefAssn";
239 
240   /** constant for field name for: assignToEffMembership */
241   public static final String FIELD_ASSIGN_TO_EFF_MEMBERSHIP = "assignToEffMembership";
242 
243   /** constant for field name for: assignToEffMembershipAssn */
244   public static final String FIELD_ASSIGN_TO_EFF_MEMBERSHIP_ASSN = "assignToEffMembershipAssn";
245 
246   /** constant for field name for: assignToGroup */
247   public static final String FIELD_ASSIGN_TO_GROUP = "assignToGroup";
248 
249   /** constant for field name for: assignToGroupAssn */
250   public static final String FIELD_ASSIGN_TO_GROUP_ASSN = "assignToGroupAssn";
251 
252   /** constant for field name for: assignToImmMembership */
253   public static final String FIELD_ASSIGN_TO_IMM_MEMBERSHIP = "assignToImmMembership";
254 
255   /** constant for field name for: assignToImmMembershipAssn */
256   public static final String FIELD_ASSIGN_TO_IMM_MEMBERSHIP_ASSN = "assignToImmMembershipAssn";
257 
258   /** constant for field name for: assignToMember */
259   public static final String FIELD_ASSIGN_TO_MEMBER = "assignToMember";
260 
261   /** constant for field name for: assignToMemberAssn */
262   public static final String FIELD_ASSIGN_TO_MEMBER_ASSN = "assignToMemberAssn";
263 
264   /** constant for field name for: assignToStem */
265   public static final String FIELD_ASSIGN_TO_STEM = "assignToStem";
266 
267   /** constant for field name for: assignToStemAssn */
268   public static final String FIELD_ASSIGN_TO_STEM_ASSN = "assignToStemAssn";
269 
270   /** constant for field name for: attributeDefPublic */
271   public static final String FIELD_ATTRIBUTE_DEF_PUBLIC = "attributeDefPublic";
272 
273   /** constant for field name for: attributeDefType */
274   public static final String FIELD_ATTRIBUTE_DEF_TYPE = "attributeDefType";
275 
276   /** constant for field name for: contextId */
277   public static final String FIELD_CONTEXT_ID = "contextId";
278 
279   /** constant for field name for: createdOnDb */
280   public static final String FIELD_CREATED_ON_DB = "createdOnDb";
281 
282   /** constant for field name for: creatorId */
283   public static final String FIELD_CREATOR_ID = "creatorId";
284 
285   /** constant for field name for: description */
286   public static final String FIELD_DESCRIPTION = "description";
287 
288   /** constant for field name for: extension */
289   public static final String FIELD_EXTENSION = "extension";
290 
291   /** constant for field name for: id */
292   public static final String FIELD_ID = "id";
293 
294   /** constant for field name for: idIndex */
295   public static final String FIELD_ID_INDEX = "idIndex";
296 
297   /** constant for field name for: lastUpdatedDb */
298   public static final String FIELD_LAST_UPDATED_DB = "lastUpdatedDb";
299 
300   /** constant for field name for: multiAssignable */
301   public static final String FIELD_MULTI_ASSIGNABLE = "multiAssignable";
302 
303   /** constant for field name for: multiValued */
304   public static final String FIELD_MULTI_VALUED = "multiValued";
305 
306   /** constant for field name for: name */
307   public static final String FIELD_NAME = "name";
308 
309   /** constant for field name for: stemId */
310   public static final String FIELD_STEM_ID = "stemId";
311 
312   /** constant for field name for: valueType */
313   public static final String FIELD_VALUE_TYPE = "valueType";
314 
315   /**
316    * fields which are included in db version
317    */
318   private static final Set<String> DB_VERSION_FIELDS = GrouperUtil.toSet(
319       FIELD_ASSIGN_TO_ATTRIBUTE_DEF, FIELD_ASSIGN_TO_ATTRIBUTE_DEF_ASSN, FIELD_ASSIGN_TO_EFF_MEMBERSHIP, FIELD_ASSIGN_TO_EFF_MEMBERSHIP_ASSN, 
320       FIELD_ASSIGN_TO_GROUP, FIELD_ASSIGN_TO_GROUP_ASSN, FIELD_ASSIGN_TO_IMM_MEMBERSHIP, FIELD_ASSIGN_TO_IMM_MEMBERSHIP_ASSN, 
321       FIELD_ASSIGN_TO_MEMBER, FIELD_ASSIGN_TO_MEMBER_ASSN, FIELD_ASSIGN_TO_STEM, FIELD_ASSIGN_TO_STEM_ASSN, 
322       FIELD_ATTRIBUTE_DEF_PUBLIC, FIELD_ATTRIBUTE_DEF_TYPE, FIELD_CONTEXT_ID, 
323       FIELD_CREATED_ON_DB, FIELD_CREATOR_ID, FIELD_DESCRIPTION, FIELD_EXTENSION, 
324       FIELD_ID, FIELD_ID_INDEX, FIELD_LAST_UPDATED_DB, FIELD_MULTI_ASSIGNABLE, FIELD_MULTI_VALUED, 
325       FIELD_NAME, FIELD_STEM_ID, FIELD_VALUE_TYPE);
326 
327   /**
328    * fields which are included in clone method
329    */
330   private static final Set<String> CLONE_FIELDS = GrouperUtil.toSet(
331       FIELD_ASSIGN_TO_ATTRIBUTE_DEF, FIELD_ASSIGN_TO_ATTRIBUTE_DEF_ASSN, FIELD_ASSIGN_TO_EFF_MEMBERSHIP, FIELD_ASSIGN_TO_EFF_MEMBERSHIP_ASSN, 
332       FIELD_ASSIGN_TO_GROUP, FIELD_ASSIGN_TO_GROUP_ASSN, FIELD_ASSIGN_TO_IMM_MEMBERSHIP, FIELD_ASSIGN_TO_IMM_MEMBERSHIP_ASSN, 
333       FIELD_ASSIGN_TO_MEMBER, FIELD_ASSIGN_TO_MEMBER_ASSN, FIELD_ASSIGN_TO_STEM, FIELD_ASSIGN_TO_STEM_ASSN, 
334       FIELD_ATTRIBUTE_DEF_PUBLIC, FIELD_ATTRIBUTE_DEF_TYPE, FIELD_CONTEXT_ID, 
335       FIELD_CREATED_ON_DB, FIELD_CREATOR_ID, FIELD_DESCRIPTION, FIELD_EXTENSION, 
336       FIELD_HIBERNATE_VERSION_NUMBER, FIELD_ID, FIELD_ID_INDEX, FIELD_LAST_UPDATED_DB, FIELD_MULTI_ASSIGNABLE, 
337       FIELD_MULTI_VALUED, FIELD_NAME, FIELD_STEM_ID, FIELD_VALUE_TYPE);
338 
339   //*****  END GENERATED WITH GenerateFieldConstants.java *****//
340 
341   /**
342    * deep clone the fields in this object
343    */
344   @Override
345   public AttributeDef clone() {
346     return GrouperUtil.clone(this, CLONE_FIELDS);
347   }
348 
349   /** */
350   @GrouperIgnoreClone @GrouperIgnoreDbVersion @GrouperIgnoreFieldConstant
351   private AttributeDefScopeDelegate attributeDefScopeDelegate;
352   
353   /**
354    * 
355    * @return the delegate
356    */
357   public AttributeDefScopeDelegate getAttributeDefScopeDelegate() {
358     if (this.attributeDefScopeDelegate == null) {
359       this.attributeDefScopeDelegate = new AttributeDefScopeDelegate(this);
360     }
361     return this.attributeDefScopeDelegate;
362   }
363 
364   /** */
365   @GrouperIgnoreClone @GrouperIgnoreDbVersion @GrouperIgnoreFieldConstant
366   private AttributeAssignAttributeDefDelegate attributeAssignAttributeDefDelegate;
367   
368   /**
369    * 
370    * @return the delegate
371    */
372   public AttributeAssignAttributeDefDelegate getAttributeDelegate() {
373     if (this.attributeAssignAttributeDefDelegate == null) {
374       this.attributeAssignAttributeDefDelegate = new AttributeAssignAttributeDefDelegate(this);
375     }
376     return this.attributeAssignAttributeDefDelegate;
377   }
378 
379   /** */
380   @GrouperIgnoreClone @GrouperIgnoreDbVersion @GrouperIgnoreFieldConstant
381   private AttributeValueDelegate attributeValueDelegate;
382   
383   /**
384    * this delegate works on attributes and values at the same time
385    * @return the delegate
386    */
387   public AttributeValueDelegate getAttributeValueDelegate() {
388     if (this.attributeValueDelegate == null) {
389       this.attributeValueDelegate = new AttributeValueDelegate(this.getAttributeDelegate());
390     }
391     return this.attributeValueDelegate;
392   }
393   
394   /** delegate */
395   @GrouperIgnoreClone @GrouperIgnoreDbVersion @GrouperIgnoreFieldConstant
396   private AttributeDefActionDelegate attributeDefActionDelegate;
397   
398   /**
399    * delegate the action list management to this class
400    * @return the delegate
401    */
402   public AttributeDefActionDelegate getAttributeDefActionDelegate() {
403     if (this.attributeDefActionDelegate == null) {
404       this.attributeDefActionDelegate = new AttributeDefActionDelegate(this);
405     }
406     return this.attributeDefActionDelegate;
407   }
408 
409   /** id of this attribute def */
410   private String id;
411 
412   /** context id of the transaction */
413   private String contextId;
414 
415   /** stem that this attribute is in */
416   private String stemId;
417 
418   /**
419    * time in millis when this attribute was last modified
420    */
421   private Long lastUpdatedDb;
422 
423   /**
424    * time in millis when this attribute was created
425    */
426   private Long createdOnDb;
427 
428   /**
429    * memberId of who created this
430    */
431   private String creatorId;
432   
433   
434   /**
435    * @return the creatorId
436    */
437   public String getCreatorId() {
438     return this.creatorId;
439   }
440 
441   /**
442    * get the subject that created this object or null if null or not found
443    * @return the subject or null
444    */
445   public Subject getCreateSubject() {
446     if (StringUtils.isBlank(this.getCreatorId())) {
447       return null;
448     }
449     Member member = MemberFinder.findByUuid(GrouperSession.staticGrouperSession(), this.getCreatorId(), false);
450     if (member != null) {
451       return member.getSubject();
452     }
453     return null;
454   }
455 
456   
457   /**
458    * @param creatorId1 the creatorId to set
459    */
460   public void setCreatorId(String creatorId1) {
461     this.creatorId = creatorId1;
462   }
463 
464   /**
465    * store this group (update) to database
466    */
467   public void store() {
468     
469     validate();
470     
471     //if a permission, can only be assigned to group or membership (not immediate)
472     if (this.attributeDefType == AttributeDefType.perm &&
473         (this.assignToAttributeDef || this.assignToAttributeDefAssn
474         || this.assignToStem || this.assignToStemAssn
475         || this.assignToGroupAssn
476         || this.assignToMember || this.assignToMemberAssn
477         || this.assignToEffMembershipAssn
478         || this.assignToImmMembership || this.assignToImmMembershipAssn )
479     ) {
480       throw new RuntimeException("An attribute definition of type permission can only be assignable to group/role or effective membership");
481     }
482 
483     //invalid entry: permission type attributes cannot be multi-assignable
484     if (this.attributeDefType == AttributeDefType.perm && this.multiAssignable) {
485       throw new RuntimeException("An attribute definition of type permission can not be multi-assignable");
486     }
487 
488     //Invalid entry: permission type attributes must have no-value value type
489     if (this.attributeDefType == AttributeDefType.perm && this.valueType != AttributeDefValueType.marker) {
490       throw new RuntimeException("An attribute definition of type permission can only have a marker value type.  In other words it cannot have values");
491     }
492 
493     //if a service, can only be assigned to group, stem, attributeDef
494     if (this.attributeDefType == AttributeDefType.service &&
495         (this.assignToAttributeDefAssn || this.assignToAttributeDef
496         || this.assignToStemAssn
497         || this.assignToGroupAssn || this.assignToGroup
498         || this.assignToMember || this.assignToMemberAssn
499         || this.assignToEffMembership || this.assignToEffMembershipAssn
500         || this.assignToImmMembership || this.assignToImmMembershipAssn )
501     ) {
502       throw new RuntimeException("An attribute definition of type service can only be assignable to folder");
503     }
504 
505     //invalid entry: permission type attributes cannot be multi-assignable
506     if (this.attributeDefType == AttributeDefType.service && this.multiAssignable) {
507       throw new RuntimeException("An attribute definition of type service can not be multi-assignable");
508     }
509 
510     //Invalid entry: permission type attributes must have no-value value type
511     if (this.attributeDefType == AttributeDefType.service && this.valueType != AttributeDefValueType.marker) {
512       throw new RuntimeException("An attribute definition of type service can only have a marker value type.  In other words it cannot have values");
513     }
514     
515     if (this.multiValued && this.valueType == AttributeDefValueType.marker) {
516       throw new RuntimeException("An attribute definition of value type marker cannot be multi-valued");
517     }
518     
519     HibernateSession.callbackHibernateSession(
520         GrouperTransactionType.READ_WRITE_OR_USE_EXISTING, AuditControl.WILL_AUDIT,
521         new HibernateHandler() {
522 
523           public Object callback(HibernateHandlerBean hibernateHandlerBean)
524               throws GrouperDAOException {
525 
526             hibernateHandlerBean.getHibernateSession().setCachingEnabled(false);
527 
528             //make sure subject is allowed to do this
529             Subject subject = GrouperSession.staticGrouperSession().getSubject();
530             if (!AttributeDef.this.getPrivilegeDelegate().canAttrAdmin(subject)) {
531               throw new InsufficientPrivilegeException(GrouperUtil
532                   .subjectToString(subject)
533                   + " is not attrAdmin on attributeDef: " + AttributeDef.this.getName());
534             }
535             
536             String differences = GrouperUtil.dbVersionDescribeDifferences(AttributeDef.this.dbVersion(), 
537                 AttributeDef.this, AttributeDef.this.dbVersion() != null ? AttributeDef.this.dbVersionDifferentFields() : AttributeDef.CLONE_FIELDS);
538 
539             GrouperDAOFactory.getFactory().getAttributeDef().saveOrUpdate(AttributeDef.this);
540             
541             if (!hibernateHandlerBean.isCallerWillCreateAudit()) {
542               AuditEntryaudit/AuditEntry.html#AuditEntry">AuditEntry auditEntry = new AuditEntry(AuditTypeBuiltin.ATTRIBUTE_DEF_UPDATE, "id", 
543                   AttributeDef.this.getUuid(), "name", AttributeDef.this.getName(), "parentStemId", AttributeDef.this.getStemId(), 
544                   "description", AttributeDef.this.getDescription());
545               
546               auditEntry.setDescription("Updated attributeDef: " + AttributeDef.this.getName() + ", " + differences);
547               auditEntry.saveOrUpdate(true);
548             }
549             return null;
550           }
551         });
552   }
553   
554   /**
555    * 
556    */
557   public void validate() {
558     //validate the attribute definition
559 
560     //lets validate
561     boolean sqlServer = GrouperDdlUtils.isSQLServer();
562     int maxNameLength = sqlServer ? 900 : 1024;
563     maxNameLength = GrouperConfig.retrieveConfig().propertyValueInt("grouper.nameOfAttributeDef.maxSize", maxNameLength);
564 
565     //    GrouperDdlUtils.ddlutilsFindOrCreateColumn(attributeDefTable,
566     //        AttributeDef.COLUMN_EXTENSION, Types.VARCHAR, "255", false, true);
567     if (GrouperUtil.lengthAscii(this.getExtension()) > 255) {
568       throw new GrouperValidationException("Extension of attributeDef too long: " + GrouperUtil.lengthAscii(this.getExtension()), 
569           VALIDATION_EXTENSION_OF_ATTRIBUTE_DEF_TOO_LONG_KEY, 255, GrouperUtil.lengthAscii(this.getExtension()));
570     }
571 
572     
573     //    GrouperDdlUtils.ddlutilsFindOrCreateColumn(attributeDefTable,
574     //        AttributeDef.COLUMN_NAME, Types.VARCHAR, ddlVersionBean.isSqlServer() ? "900" : "1024", false, true);
575     if (GrouperUtil.lengthAscii(this.getName()) > maxNameLength) {
576       throw new GrouperValidationException("Name of attributeDef too long: " + GrouperUtil.lengthAscii(this.getName()), 
577           VALIDATION_NAME_OF_ATTRIBUTE_DEF_TOO_LONG_KEY, maxNameLength, GrouperUtil.lengthAscii(this.getName()));
578     }
579 
580     //    GrouperDdlUtils.ddlutilsFindOrCreateColumn(attributeDefTable,
581     //        AttributeDef.COLUMN_DESCRIPTION, Types.VARCHAR, "1024", false, false);
582     if (GrouperUtil.lengthAscii(this.getDescription()) > 1024) {
583       throw new GrouperValidationException("Description of attributeDef too long: " + GrouperUtil.lengthAscii(this.getDescription()), 
584           VALIDATION_DESCRIPTION_OF_ATTRIBUTE_DEF_TOO_LONG_KEY, 1024, GrouperUtil.lengthAscii(this.getDescription()));
585     }
586   }
587   
588   /** delegate privilege calls to another class to separate logic */
589   @GrouperIgnoreClone @GrouperIgnoreDbVersion @GrouperIgnoreFieldConstant
590   private AttributeDefPrivilegeDelegate attributeDefPrivilegeDelegate = null;
591 
592   /**
593    * privilege delegate to handle security on this attribute def
594    * @return the delegate
595    */
596   public AttributeDefPrivilegeDelegate getPrivilegeDelegate() {
597     if (this.attributeDefPrivilegeDelegate == null) {
598       this.attributeDefPrivilegeDelegate = new AttributeDefPrivilegeDelegate(this);
599     }
600     return this.attributeDefPrivilegeDelegate;
601   }
602   
603   /**
604    * description of attribute, friendly description, e.g. in sentence form, 
605    * about what the attribute is about 
606    */
607   private String description;
608 
609   /**
610    * extension of attribute
611    */
612   private String extension;
613 
614   /**
615    * name of attribute
616    */
617   private String name;
618 
619   /**
620    * if the attribute def is public, otherwise you just see it in this stem and substem
621    */
622   private boolean attributeDefPublic = false;
623   
624   /**
625    * type of this attribute (e.g. attribute or privilege)
626    */
627   private AttributeDefType attributeDefType;
628   
629   /** if can assign to group/role */
630   private boolean assignToGroup;
631   
632   /** if can assign to stem */
633   private boolean assignToStem;
634   
635   /** if can assign to member */
636   private boolean assignToMember;
637   
638   /** if can assign to immediate membership */
639   private boolean assignToImmMembership;
640   
641   /** if can assign to effective membership */
642   private boolean assignToEffMembership;
643 
644   /** if can assign to attribute def */
645   private boolean assignToAttributeDef;
646 
647   /** if can assign to assignment of group/role */
648   private boolean assignToGroupAssn;
649   
650   /** if can assign to assignment of stem */
651   private boolean assignToStemAssn;
652   
653   /** if can assign to assignment of member */
654   private boolean assignToMemberAssn;
655   
656   /** if can assign to assignment of immediate membership */
657   private boolean assignToImmMembershipAssn;
658   
659   /** if can assign to assignment of effective membership */
660   private boolean assignToEffMembershipAssn;
661 
662   /** if can assign to assignment of attribute def */
663   private boolean assignToAttributeDefAssn;
664 
665   /**
666    * if can assign to group/role
667    * @return the assignToGroup
668    */
669   public boolean isAssignToGroup() {
670     return this.assignToGroup;
671   }
672   
673   /**
674    * if can assign to group/role
675    * @param assignToGroup the assignToGroup to set
676    */
677   public void setAssignToGroup(boolean assignToGroup) {
678     this.assignToGroup = assignToGroup;
679   }
680 
681   /**
682    * if can assign to stem
683    * @return the assignToStem
684    */
685   public boolean isAssignToStem() {
686     return this.assignToStem;
687   }
688   
689   /**
690    * if can assign to stem
691    * @param assignToStem the assignToStem to set
692    */
693   public void setAssignToStem(boolean assignToStem) {
694     this.assignToStem = assignToStem;
695   }
696 
697   /**
698    * if can assign to member
699    * @return the assignToMember
700    */
701   public boolean isAssignToMember() {
702     return this.assignToMember;
703   }
704   
705   /**
706    * if can assign to member
707    * @param assignToMember the assignToMember to set
708    */
709   public void setAssignToMember(boolean assignToMember) {
710     this.assignToMember = assignToMember;
711   }
712 
713   /**
714    * if can assign to immediate membership
715    * @return the assignToImmMembership
716    */
717   public boolean isAssignToImmMembership() {
718     return this.assignToImmMembership;
719   }
720 
721   /**
722    * if can assign to immediate membership
723    * @param assignToImmMembership the assignToImmMembership to set
724    */
725   public void setAssignToImmMembership(boolean assignToImmMembership) {
726     this.assignToImmMembership = assignToImmMembership;
727   }
728 
729   /**
730    * if can assign to effective membership
731    * @return the assignToEffMembership
732    */
733   public boolean isAssignToEffMembership() {
734     return this.assignToEffMembership;
735   }
736 
737   /**
738    * if can assign to effective membership
739    * @param assignToEffMembership the assignToEffMembership to set
740    */
741   public void setAssignToEffMembership(boolean assignToEffMembership) {
742     this.assignToEffMembership = assignToEffMembership;
743   }
744 
745   /**
746    * if can assign to attribute def
747    * @return the assignToAttributeDef
748    */
749   public boolean isAssignToAttributeDef() {
750     return this.assignToAttributeDef;
751   }
752 
753   /**
754    * if can assign to attribute def
755    * @param assignToAttributeDef the assignToAttributeDef to set
756    */
757   public void setAssignToAttributeDef(boolean assignToAttributeDef) {
758     this.assignToAttributeDef = assignToAttributeDef;
759   }
760 
761   /**
762    * if can assign to assignment of group/role
763    * @return the assignToGroupAssn
764    */
765   public boolean isAssignToGroupAssn() {
766     return this.assignToGroupAssn;
767   }
768   
769   /**
770    * if can assign to assignment of group/role
771    * @param assignToGroupAssn the assignToGroupAssn to set
772    */
773   public void setAssignToGroupAssn(boolean assignToGroupAssn) {
774     this.assignToGroupAssn = assignToGroupAssn;
775   }
776 
777 
778   
779   /**
780    * allowed to assign to a stem assignment
781    * @return the assignToStemAssn
782    */
783   public boolean isAssignToStemAssn() {
784     return this.assignToStemAssn;
785   }
786 
787 
788   
789   /**
790    * allowed to assign to a stem assignment
791    * @param assignToStemAssn the assignToStemAssn to set
792    */
793   public void setAssignToStemAssn(boolean assignToStemAssn) {
794     this.assignToStemAssn = assignToStemAssn;
795   }
796 
797 
798   
799   /**
800    * allowed to assign to a member assignment
801    * @return the assignToMemberAssn
802    */
803   public boolean isAssignToMemberAssn() {
804     return this.assignToMemberAssn;
805   }
806 
807 
808   
809   /**
810    * allowed to assign to a member assignment
811    * @param assignToMemberAssn the assignToMemberAssn to set
812    */
813   public void setAssignToMemberAssn(boolean assignToMemberAssn) {
814     this.assignToMemberAssn = assignToMemberAssn;
815   }
816 
817 
818   
819   /**
820    * allowed to assign to an immediate membership assignment
821    * @return the assignToImmMembershipAssn
822    */
823   public boolean isAssignToImmMembershipAssn() {
824     return this.assignToImmMembershipAssn;
825   }
826 
827 
828   
829   /**
830    * allowed to assign to an immediate membership assignment
831    * @param assignToImmMembershipAssn the assignToImmMembershipAssn to set
832    */
833   public void setAssignToImmMembershipAssn(boolean assignToImmMembershipAssn) {
834     this.assignToImmMembershipAssn = assignToImmMembershipAssn;
835   }
836 
837 
838   
839   /**
840    * allowed to assign to an effective membership assignment
841    * @return the assignToEffMembershipAssn
842    */
843   public boolean isAssignToEffMembershipAssn() {
844     return this.assignToEffMembershipAssn;
845   }
846 
847 
848   
849   /**
850    * allowed to assign to an effective membership assignment
851    * @param assignToEffMembershipAssn the assignToEffMembershipAssn to set
852    */
853   public void setAssignToEffMembershipAssn(boolean assignToEffMembershipAssn) {
854     this.assignToEffMembershipAssn = assignToEffMembershipAssn;
855   }
856 
857 
858   
859   /**
860    * allowed to assign to an attribute definition assignment
861    * @return the assignToAttributeDefAssn
862    */
863   public boolean isAssignToAttributeDefAssn() {
864     return this.assignToAttributeDefAssn;
865   }
866 
867 
868   
869   /**
870    * allowed to assign to an attribute definition assignment
871    * @param assignToAttributeDefAssn the assignToAttributeDefAssn to set
872    */
873   public void setAssignToAttributeDefAssn(boolean assignToAttributeDefAssn) {
874     this.assignToAttributeDefAssn = assignToAttributeDefAssn;
875   }
876 
877   /**
878    * if can assign to group/role
879    * @return the assignToGroup
880    */
881   public String getAssignToGroupDb() {
882     return this.assignToGroup ? "T" : "F";
883   }
884   
885   /**
886    * if can assign to group/role
887    * @param assignToGroup1 the assignToGroup to set
888    */
889   public void setAssignToGroupDb(String assignToGroup1) {
890     this.assignToGroup = GrouperUtil.booleanValue(assignToGroup1);
891   }
892 
893   /**
894    * if can assign to stem
895    * @return the assignToStem
896    */
897   public String getAssignToStemDb() {
898     return this.assignToStem ? "T" : "F";
899   }
900   
901   /**
902    * if can assign to stem
903    * @param assignToStem1 the assignToStem to set
904    */
905   public void setAssignToStemDb(String assignToStem1) {
906     this.assignToStem = GrouperUtil.booleanValue(assignToStem1);
907   }
908 
909   /**
910    * if can assign to member
911    * @return the assignToMember
912    */
913   public String getAssignToMemberDb() {
914     return this.assignToMember ? "T" : "F";
915   }
916   
917   /**
918    * if can assign to member
919    * @param assignToMember1 the assignToMember to set
920    */
921   public void setAssignToMemberDb(String assignToMember1) {
922     this.assignToMember = GrouperUtil.booleanValue(assignToMember1);
923   }
924 
925   /**
926    * if can assign to immediate membership
927    * @return the assignToImmMembership
928    */
929   public String getAssignToImmMembershipDb() {
930     return this.assignToImmMembership ? "T" : "F";
931   }
932 
933   /**
934    * if can assign to immediate membership
935    * @param assignToImmMembership1 the assignToImmMembership to set
936    */
937   public void setAssignToImmMembershipDb(String assignToImmMembership1) {
938     this.assignToImmMembership = GrouperUtil.booleanValue(assignToImmMembership1);
939   }
940 
941   /**
942    * if can assign to effective membership
943    * @return the assignToEffMembership
944    */
945   public String getAssignToEffMembershipDb() {
946     return this.assignToEffMembership ? "T" : "F";
947   }
948 
949   /**
950    * if can assign to effective membership
951    * @param assignToEffMembership1 the assignToEffMembership to set
952    */
953   public void setAssignToEffMembershipDb(String assignToEffMembership1) {
954     this.assignToEffMembership = GrouperUtil.booleanValue(assignToEffMembership1);
955   }
956 
957   /**
958    * if can assign to attribute def
959    * @return the assignToAttributeDef
960    */
961   public String getAssignToAttributeDefDb() {
962     return this.assignToAttributeDef ? "T" : "F";
963   }
964 
965   /**
966    * if can assign to attribute def
967    * @param assignToAttributeDef1 the assignToAttributeDef to set
968    */
969   public void setAssignToAttributeDefDb(String assignToAttributeDef1) {
970     this.assignToAttributeDef = GrouperUtil.booleanValue(assignToAttributeDef1);
971   }
972 
973   /**
974    * if can assign to assignment of group/role
975    * @return the assignToGroupAssn
976    */
977   public String getAssignToGroupAssnDb() {
978     return this.assignToGroupAssn ? "T" : "F";
979   }
980   
981   /**
982    * if can assign to assignment of group/role
983    * @param assignToGroupAssn1 the assignToGroupAssn to set
984    */
985   public void setAssignToGroupAssnDb(String assignToGroupAssn1) {
986     this.assignToGroupAssn = GrouperUtil.booleanValue(assignToGroupAssn1);
987   }
988 
989 
990   
991   /**
992    * allowed to assign to a stem assignment
993    * @return the assignToStemAssn
994    */
995   public String getAssignToStemAssnDb() {
996     return this.assignToStemAssn ? "T" : "F";
997   }
998 
999 
1000   
1001   /**
1002    * allowed to assign to a stem assignment
1003    * @param assignToStemAssn1 the assignToStemAssn to set
1004    */
1005   public void setAssignToStemAssnDb(String assignToStemAssn1) {
1006     this.assignToStemAssn = GrouperUtil.booleanValue(assignToStemAssn1);
1007   }
1008 
1009 
1010   
1011   /**
1012    * allowed to assign to a member assignment
1013    * @return the assignToMemberAssn
1014    */
1015   public String getAssignToMemberAssnDb() {
1016     return this.assignToMemberAssn ? "T" : "F";
1017   }
1018 
1019 
1020   
1021   /**
1022    * allowed to assign to a member assignment
1023    * @param assignToMemberAssn1 the assignToMemberAssn to set
1024    */
1025   public void setAssignToMemberAssnDb(String assignToMemberAssn1) {
1026     this.assignToMemberAssn = GrouperUtil.booleanValue(assignToMemberAssn1);
1027   }
1028 
1029 
1030   
1031   /**
1032    * allowed to assign to an immediate membership assignment
1033    * @return the assignToImmMembershipAssn
1034    */
1035   public String getAssignToImmMembershipAssnDb() {
1036     return this.assignToImmMembershipAssn ? "T" : "F";
1037   }
1038 
1039 
1040   
1041   /**
1042    * allowed to assign to an immediate membership assignment
1043    * @param assignToImmMembershipAssn1 the assignToImmMembershipAssn to set
1044    */
1045   public void setAssignToImmMembershipAssnDb(String assignToImmMembershipAssn1) {
1046     this.assignToImmMembershipAssn = GrouperUtil.booleanValue(assignToImmMembershipAssn1);
1047   }
1048 
1049 
1050   
1051   /**
1052    * allowed to assign to an effective membership assignment
1053    * @return the assignToEffMembershipAssn
1054    */
1055   public String getAssignToEffMembershipAssnDb() {
1056     return this.assignToEffMembershipAssn ? "T" : "F";
1057   }
1058 
1059 
1060   
1061   /**
1062    * allowed to assign to an effective membership assignment
1063    * @param assignToEffMembershipAssnDb1 the assignToEffMembershipAssn to set
1064    */
1065   public void setAssignToEffMembershipAssnDb(String assignToEffMembershipAssnDb1) {
1066     this.assignToEffMembershipAssn = GrouperUtil.booleanValue(assignToEffMembershipAssnDb1);
1067   }
1068 
1069 
1070   
1071   /**
1072    * allowed to assign to an attribute definition assignment
1073    * @return the assignToAttributeDefAssn
1074    */
1075   public String getAssignToAttributeDefAssnDb() {
1076     return this.assignToAttributeDefAssn ? "T" : "F";
1077   }
1078 
1079 
1080   
1081   /**
1082    * allowed to assign to an attribute definition assignment
1083    * @param assignToAttributeDefAssnDb the assignToAttributeDefAssn to set
1084    */
1085   public void setAssignToAttributeDefAssnDb(String assignToAttributeDefAssnDb) {
1086     this.assignToAttributeDefAssn = GrouperUtil.booleanValue(assignToAttributeDefAssnDb);
1087   }
1088 
1089 
1090   /**
1091    * if the attribute def is public, otherwise you just see it in this stem and substem
1092    * @return if public
1093    */
1094   public boolean isAttributeDefPublic() {
1095     return this.attributeDefPublic;
1096   }
1097 
1098   /**
1099    * hibernate mapped method for if this attribute def is public
1100    * @return true if public, false if not (default false)
1101    */
1102   public String getAttributeDefPublicDb() {
1103     return this.attributeDefPublic ? "T" : "F";
1104   }
1105 
1106   /**
1107    * if the attribute def is public, otherwise you just see it in this stem and substem
1108    * @param theAttributeDefPublicDb
1109    */
1110   public void setAttributeDefPublicDb(String theAttributeDefPublicDb) {
1111     this.attributeDefPublic = GrouperUtil.booleanValue(theAttributeDefPublicDb, false);
1112   }
1113   
1114   /**
1115    * if the attribute def is public, otherwise you just see it in this stem and substem
1116    * @param attributeDefPublic1
1117    */
1118   public void setAttributeDefPublic(boolean attributeDefPublic1) {
1119     this.attributeDefPublic = attributeDefPublic1;
1120   }
1121 
1122   /**
1123    * type of this attribute (e.g. attribute or privilege)
1124    * @return attribute def type
1125    */
1126   public AttributeDefType getAttributeDefType() {
1127     return this.attributeDefType;
1128   }
1129 
1130   /**
1131    * type of this attribute (e.g. attribute or privilege)
1132    * @param attributeDefType
1133    */
1134   public void setAttributeDefType(AttributeDefType attributeDefType) {
1135     this.attributeDefType = attributeDefType;
1136   }
1137 
1138   /**
1139    * type of this attribute (e.g. attribute or privilege)
1140    * @return the attribute def type
1141    */
1142   public String getAttributeDefTypeDb() {
1143     return this.attributeDefType == null ? null : this.attributeDefType.name();
1144   }
1145 
1146   /**
1147    * type of this attribute (e.g. attr or priv or limit)
1148    * @param theAttributeDefType
1149    */
1150   public void setAttributeDefTypeDb(String theAttributeDefType) {
1151     this.attributeDefType = AttributeDefType.valueOfIgnoreCase(theAttributeDefType, false);
1152   }
1153 
1154   /**
1155    * this method makes this class more compatible with Group and Stem
1156    * @return the parent stem id
1157    */
1158   public String getParentUuid() {
1159     return this.stemId;
1160   }
1161   
1162   /**
1163    * stem that this attribute is in
1164    * @return the stem id
1165    */
1166   public String getStemId() {
1167     return this.stemId;
1168   }
1169 
1170   /**
1171    * stem that this attribute is in
1172    * @return the stem id
1173    */
1174   public Stem getStem() {
1175     return this.stemId == null ? null : StemFinder.findByUuid(GrouperSession.staticGrouperSession(), this.stemId, true);
1176   }
1177 
1178   /**
1179    * stem that this attribute is in
1180    * @param stemId1
1181    */
1182   public void setStemId(String stemId1) {
1183     this.stemId = stemId1;
1184   }
1185 
1186   /**
1187    * if this attribute can be assigned to the same action to the same object more than once
1188    */
1189   private boolean multiAssignable;
1190   
1191   /**
1192    * if more than one value (same type) can be assigned to the attribute assignment
1193    */
1194   private boolean multiValued;
1195 
1196   /**
1197    * type of the value,  int, double, string, marker
1198    */
1199   private AttributeDefValueType valueType = AttributeDefValueType.marker;
1200 
1201   /** id of the group as a unique integer */
1202   private Long idIndex;
1203   
1204   /**
1205    * type of the value,  int, double, string, marker
1206    * @return the type
1207    */
1208   public AttributeDefValueType getValueType() {
1209     return valueType;
1210   }
1211 
1212   /**
1213    * type of the value,  int, double, string, marker
1214    * @param valueType1
1215    */
1216   public void setValueType(AttributeDefValueType valueType1) {
1217     this.valueType = valueType1;
1218   }
1219 
1220   /**
1221    * type of the value,  int, double, string, marker
1222    * @return the type
1223    */
1224   public String getValueTypeDb() {
1225     return this.valueType == null ? null : this.valueType.toString();
1226   }
1227 
1228   /**
1229    * type of the value,  int, double, string, marker
1230    * @param valueType1
1231    */
1232   public void setValueTypeDb(String valueType1) {
1233     this.valueType = AttributeDefValueType.valueOfIgnoreCase(valueType1, false);
1234   }
1235 
1236   /**
1237    * if this attribute can be assigned to the same action to the same object more than once
1238    * @return if multiassignable
1239    */
1240   public boolean isMultiAssignable() {
1241     return multiAssignable;
1242   }
1243   
1244   /**
1245    * if this attribute can be assigned to the same action to the same object more than once
1246    * convert to string for hibernate
1247    * @return the string value
1248    */
1249   public String getMultiAssignableDb() {
1250     return this.multiAssignable ? "T" : "F";
1251   }
1252 
1253   /**
1254    * if this attribute can be assigned to the same action to the same object more than once
1255    * convert to string for hibernate
1256    * @param multiAssignableDb
1257    */
1258   public void setMultiAssignableDb(String multiAssignableDb) {
1259     this.multiAssignable = GrouperUtil.booleanValue(multiAssignableDb, false);
1260   }
1261   
1262   /**
1263    * if this attribute can be assigned to the same action to the same object more than once
1264    * @param multiAssignable1
1265    */
1266   public void setMultiAssignable(boolean multiAssignable1) {
1267     this.multiAssignable = multiAssignable1;
1268   }
1269 
1270   /**
1271    * if more than one value (same type) can be assigned to the attribute assignment
1272    * @return boolean
1273    */
1274   public boolean isMultiValued() {
1275     return multiValued;
1276   }
1277 
1278   /**
1279    * if more than one value (same type) can be assigned to the attribute assignment
1280    * convert to String for hibernate
1281    * @return if multivalued
1282    */
1283   public String getMultiValuedDb() {
1284     return this.multiValued ? "T" : "F";
1285   }
1286 
1287   /**
1288    * if more than one value (same type) can be assigned to the attribute assignment
1289    * convert to String for hibernate
1290    * @param multiValuedDb
1291    */
1292   public void setMultiValuedDb(String multiValuedDb) {
1293     this.multiValued = GrouperUtil.booleanValue(multiValuedDb, false);
1294   }
1295   
1296   /**
1297    * if more than one value (same type) can be assigned to the attribute assignment
1298    * @param multiValued1
1299    */
1300   public void setMultiValued(boolean multiValued1) {
1301     this.multiValued = multiValued1;
1302   }
1303 
1304   /**
1305    * context id of the transaction
1306    * @return context id
1307    */
1308   public String getContextId() {
1309     return this.contextId;
1310   }
1311 
1312   /**
1313    * context id of the transaction
1314    * @param contextId1
1315    */
1316   public void setContextId(String contextId1) {
1317     this.contextId = contextId1;
1318   }
1319 
1320   /**
1321    * id of this attribute def
1322    * @return id
1323    */
1324   public String getId() {
1325     return id;
1326   }
1327 
1328   /**
1329    * id of this attribute def
1330    * @param id1
1331    */
1332   public void setId(String id1) {
1333     this.id = id1;
1334   }
1335 
1336   
1337   /**
1338    * when last updated
1339    * @return timestamp
1340    */
1341   public Timestamp getLastUpdated() {
1342     return this.lastUpdatedDb == null ? null : new Timestamp(this.lastUpdatedDb);
1343   }
1344 
1345   /**
1346    * when last updated
1347    * @return timestamp
1348    */
1349   public Long getLastUpdatedDb() {
1350     return this.lastUpdatedDb;
1351   }
1352   
1353   /**
1354    * when last updated
1355    * @param lastUpdated1
1356    */
1357   public void setLastUpdated(Timestamp lastUpdated1) {
1358     this.lastUpdatedDb = lastUpdated1 == null ? null : lastUpdated1.getTime();
1359   }
1360 
1361   /**
1362    * when last updated
1363    * @param lastUpdated1
1364    */
1365   public void setLastUpdatedDb(Long lastUpdated1) {
1366     this.lastUpdatedDb = lastUpdated1;
1367   }
1368   
1369   /**
1370    * when created
1371    * @return timestamp
1372    */
1373   public Timestamp getCreatedOn() {
1374     return this.createdOnDb == null ? null : new Timestamp(this.createdOnDb);
1375   }
1376 
1377   /**
1378    * when created
1379    * @return timestamp
1380    */
1381   public Long getCreatedOnDb() {
1382     return this.createdOnDb;
1383   }
1384 
1385   /**
1386    * when created
1387    * @param createdOn1
1388    */
1389   public void setCreatedOn(Timestamp createdOn1) {
1390     this.createdOnDb = createdOn1 == null ? null : createdOn1.getTime();
1391   }
1392 
1393   /**
1394    * when created
1395    * @param createdOn1
1396    */
1397   public void setCreatedOnDb(Long createdOn1) {
1398     this.createdOnDb = createdOn1;
1399   }
1400 
1401   /**
1402    * description of attribute, friendly description, e.g. in sentence form, 
1403    * about what the attribute is about 
1404    * @return the description
1405    */
1406   public String getDescription() {
1407     return description;
1408   }
1409 
1410   /**
1411    * description of attribute, friendly description, e.g. in sentence form, 
1412    * about what the attribute is about 
1413    * @param description1
1414    */
1415   public void setDescription(String description1) {
1416     this.description = description1;
1417   }
1418 
1419   /**
1420    * extension of attribute expireTime
1421    * @return extension
1422    */
1423   public String getExtension() {
1424     return extension;
1425   }
1426 
1427   /**
1428    * extension of attribute expireTime
1429    * @return extension
1430    */
1431   public String getExtensionDb() {
1432     return extension;
1433   }
1434 
1435   /**
1436    * extension of attribute expireTime
1437    * @param extension1
1438    */
1439   public void setExtension(String extension1) {
1440     this.extension = extension1;
1441     this.name = GrouperUtil.parentStemNameFromName(this.name) + ":" + this.extension;
1442   }
1443 
1444   /**
1445    * extension of attribute expireTime
1446    * @param extension1
1447    */
1448   public void setExtensionDb(String extension1) {
1449     this.extension = extension1;
1450   }
1451 
1452   /**
1453    * 
1454    * @return the name for hibernate
1455    */
1456   public String getNameDb() {
1457     return name;
1458   }
1459 
1460   /**
1461    * 
1462    * @param name1
1463    */
1464   public void setNameDb(String name1) {
1465     this.name = name1;
1466   }
1467   
1468 
1469   /**
1470    * Get group name.
1471    * @return  Group name.
1472    * @throws  GrouperException
1473    */
1474   public String getName() throws GrouperException  {
1475 
1476     if (StringUtils.isBlank(this.name)) {
1477       LOG.error( "attributeDef is blank");
1478       throw new GrouperException("attributeDef is blank");
1479     }
1480     return this.name;
1481   } // public String getName()
1482 
1483   /**
1484    * Set attributeDef <i>name</i>.  This should not be called
1485    * @param   value   Set <i>extension</i> to this value.
1486    */
1487   public void setName(String value) {
1488     throw new InsufficientPrivilegeException("group name is system maintained: " + this.name + ", " + value);
1489   }
1490 
1491   /**
1492    * @see java.lang.Object#equals(java.lang.Object)
1493    */
1494   @Override
1495   public boolean equals(Object obj) {
1496     if (!(obj instanceof AttributeDef)) {
1497       return false;
1498     }
1499     return StringUtils.equals(this.id, ((AttributeDef)obj).id);
1500   }
1501 
1502   /**
1503    * @see java.lang.Object#hashCode()
1504    */
1505   @Override
1506   public int hashCode() {
1507     return StringUtils.defaultString(this.id).hashCode();
1508   }
1509 
1510 
1511   /**
1512    * @see edu.internet2.middleware.grouper.misc.Owner#getUuid()
1513    */
1514   public String getUuid() {
1515     return this.getId();
1516   }
1517 
1518   /**
1519    * @see java.lang.Object#toString()
1520    */
1521   @Override
1522   public String toString() {
1523     // Bypass privilege checks.  If the group is loaded it is viewable.
1524     return new ToStringBuilder(this)
1525       .append( "name", this.name)
1526       .append( "uuid", this.getId() )
1527       .toString();
1528   }
1529 
1530   /**
1531    * keep track of if we are in a delete so hooks can 
1532    */
1533   private static ThreadLocal<Boolean> threadLocalInAttributeDefDelete = new InheritableThreadLocal<Boolean>();
1534   
1535   /**
1536    * see if we are in the middle of a delete (e.g. for hook)
1537    * @return true if delete is occurring
1538    */
1539   public static boolean deleteOccuring() {
1540     Boolean deleteOccuring = threadLocalInAttributeDefDelete.get();
1541     if (deleteOccuring != null) {
1542       return deleteOccuring;
1543     }
1544     return false;
1545   }
1546 
1547   /**
1548    * delete this record (and security and actions etc, but not attribute def names yet)
1549    */
1550   public void delete() {
1551 
1552               
1553 
1554     HibernateSession.callbackHibernateSession(GrouperTransactionType.READ_WRITE_OR_USE_EXISTING, AuditControl.WILL_AUDIT, new HibernateHandler() {
1555       
1556       public Object callback(HibernateHandlerBean hibernateHandlerBean)
1557           throws GrouperDAOException {
1558 
1559         try {
1560           threadLocalInAttributeDefDelete.set(true);
1561 
1562           GrouperSession.internal_callbackRootGrouperSession(new GrouperSessionHandler() {
1563             
1564             public Object callback(GrouperSession grouperSession) throws GrouperSessionException {
1565               //delete any attributes on this def as root
1566               Set<AttributeAssign> attributeAssigns = GrouperDAOFactory.getFactory().getAttributeAssign().findByOwnerAttributeDefId(AttributeDef.this.getId());
1567               
1568               for (AttributeAssign attributeAssign : attributeAssigns) {
1569                 attributeAssign.delete();
1570               }
1571               return null;
1572             }
1573           });
1574 
1575           //find the names that use this def
1576           Set<AttributeDefName> attributeDefNames = GrouperDAOFactory.getFactory().getAttributeDefName().findByAttributeDef(AttributeDef.this.getId());
1577           
1578           for (AttributeDefName attributeDefName : attributeDefNames) {
1579             attributeDefName.delete();
1580           }
1581           
1582           Set<AttributeDefScope> attributeDefScopes = GrouperDAOFactory.getFactory().getAttributeDefScope().findByAttributeDefId(AttributeDef.this.getId(), new QueryOptions().secondLevelCache(false));
1583           
1584           for (AttributeDefScope attributeDefScope : attributeDefScopes) {
1585             attributeDefScope.delete();
1586           }
1587           
1588           
1589           GrouperDAOFactory.getFactory().getAttributeDef().delete(AttributeDef.this);
1590   
1591           if (!hibernateHandlerBean.isCallerWillCreateAudit()) {
1592             AuditEntryaudit/AuditEntry.html#AuditEntry">AuditEntry auditEntry = new AuditEntry(AuditTypeBuiltin.ATTRIBUTE_DEF_DELETE, "id", 
1593                 AttributeDef.this.getUuid(), "name", AttributeDef.this.getName(), "parentStemId", AttributeDef.this.getStemId(), 
1594                 "description", AttributeDef.this.getDescription());
1595             auditEntry.setDescription("Deleted attributeDef: " + AttributeDef.this.getName());
1596             auditEntry.saveOrUpdate(true);
1597           }
1598         } finally {
1599           threadLocalInAttributeDefDelete.remove();
1600         }
1601         return null;
1602       }
1603     });
1604     
1605   }
1606 
1607   /**
1608    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlCopyBusinessPropertiesToExisting(java.lang.Object)
1609    */
1610   public void xmlCopyBusinessPropertiesToExisting(AttributeDef existingRecord) {
1611     existingRecord.setAssignToAttributeDef(this.assignToAttributeDef);
1612     existingRecord.setAssignToAttributeDefAssn(this.assignToAttributeDefAssn);
1613     existingRecord.setAssignToEffMembership(this.assignToEffMembership);
1614     existingRecord.setAssignToEffMembershipAssn(this.assignToEffMembershipAssn);
1615     existingRecord.setAssignToGroup(this.assignToGroup);
1616     existingRecord.setAssignToGroupAssn(this.assignToGroupAssn);
1617     existingRecord.setAssignToImmMembership(this.assignToImmMembership);
1618     existingRecord.setAssignToImmMembershipAssn(this.assignToImmMembershipAssn);
1619     existingRecord.setAssignToMember(this.assignToMember);
1620     existingRecord.setAssignToMemberAssn(this.assignToMemberAssn);
1621     existingRecord.setAssignToStem(this.assignToStem);
1622     existingRecord.setAssignToStemAssn(this.assignToStemAssn);
1623     existingRecord.setAttributeDefPublic(this.attributeDefPublic);
1624     existingRecord.setAttributeDefType(this.attributeDefType);
1625     
1626     existingRecord.setDescription(this.getDescription());
1627     existingRecord.setExtensionDb(this.getExtensionDb());
1628     existingRecord.setId(this.getId());
1629     existingRecord.setMultiAssignable(this.multiAssignable);
1630     existingRecord.setMultiValued(this.multiValued);
1631     existingRecord.setNameDb(this.getNameDb());
1632     existingRecord.setStemId(this.stemId);
1633     existingRecord.setValueType(this.valueType);
1634   }
1635 
1636   /**
1637    * Get parent stem.
1638    * <pre class="eg">
1639    * Stem parent = g.getParentStem();
1640    * </pre>
1641    * @return  Parent {@link Stem}.
1642    * @throws IllegalStateException 
1643    */
1644   public Stem getParentStem() {
1645     String uuid = this.getStemId();
1646     if (uuid == null) {
1647       throw new IllegalStateException("attributeDef has no parent stem");
1648     }
1649     Stem parent = GrouperDAOFactory.getFactory().getStem().findByUuid(uuid, true) ;
1650     return parent;
1651   }
1652 
1653 
1654   /**
1655    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlDifferentBusinessProperties(java.lang.Object)
1656    */
1657   public boolean xmlDifferentBusinessProperties(AttributeDef other) {
1658     if (this.assignToAttributeDef != other.assignToAttributeDef) {
1659       return true;
1660     }
1661     if (this.assignToAttributeDefAssn != other.assignToAttributeDefAssn) {
1662       return true;
1663     }
1664     if (this.assignToEffMembership != other.assignToEffMembership) {
1665       return true;
1666     }
1667     if (this.assignToEffMembershipAssn != other.assignToEffMembershipAssn) {
1668       return true;
1669     }
1670     if (this.assignToGroup != other.assignToGroup) {
1671       return true;
1672     }
1673     if (this.assignToGroupAssn != other.assignToGroupAssn) {
1674       return true;
1675     }
1676     if (this.assignToImmMembership != other.assignToImmMembership) {
1677       return true;
1678     }
1679     if (this.assignToImmMembershipAssn != other.assignToImmMembershipAssn) {
1680       return true;
1681     }
1682     if (this.assignToMember != other.assignToMember) {
1683       return true;
1684     }
1685     if (this.assignToMemberAssn != other.assignToMemberAssn) {
1686       return true;
1687     }
1688     if (this.assignToStem != other.assignToStem) {
1689       return true;
1690     }
1691     if (this.assignToStemAssn != other.assignToStemAssn) {
1692       return true;
1693     }
1694     if (this.attributeDefPublic != other.attributeDefPublic) {
1695       return true;
1696     }
1697     if (this.attributeDefType != other.attributeDefType) {
1698       return true;
1699     }
1700     if (!StringUtils.equals(StringUtils.trimToNull(this.description), StringUtils.trimToNull(other.description))) {
1701       return true;
1702     }
1703     if (!StringUtils.equals(this.extension, other.extension)) {
1704       return true;
1705     }
1706     if (!StringUtils.equals(this.id, other.id)) {
1707       return true;
1708     }
1709     if (this.multiAssignable != other.multiAssignable) {
1710       return true;
1711     }
1712     if (this.multiValued != other.multiValued) {
1713       return true;
1714     }
1715     if (!StringUtils.equals(this.name, other.name)) {
1716       return true;
1717     }
1718     if (!StringUtils.equals(this.stemId, other.stemId)) {
1719       return true;
1720     }
1721     if (this.valueType != other.valueType) {
1722       return true;
1723     }
1724     return false;
1725   }
1726 
1727 
1728   /**
1729    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlDifferentUpdateProperties(java.lang.Object)
1730    */
1731   public boolean xmlDifferentUpdateProperties(AttributeDef other) {
1732     if (!StringUtils.equals(this.contextId, other.contextId)) {
1733       return true;
1734     }
1735     if (!ObjectUtils.equals(this.createdOnDb, other.createdOnDb)) {
1736       return true;
1737     }
1738     if (!StringUtils.equals(this.creatorId, other.creatorId)) {
1739       return true;
1740     }
1741     if (!GrouperUtil.equals(this.getHibernateVersionNumber(), other.getHibernateVersionNumber())) {
1742       return true;
1743     }
1744     return false;
1745   }
1746 
1747 
1748   /**
1749    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlRetrieveByIdOrKey()
1750    */
1751   public AttributeDef xmlRetrieveByIdOrKey() {
1752     return GrouperDAOFactory.getFactory().getAttributeDef().findByUuidOrName(this.id, this.name, false, new QueryOptions().secondLevelCache(false));
1753   }
1754 
1755 
1756   /**
1757    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlSaveBusinessProperties(java.lang.Object)
1758    */
1759   public AttributeDefernet2/middleware/grouper/attr/AttributeDef.html#AttributeDef">AttributeDef xmlSaveBusinessProperties(AttributeDef existingRecord) {
1760     //if its an insert, call the business method
1761     if (existingRecord == null) {
1762       Stem parent = StemFinder.findByUuid(GrouperSession.staticGrouperSession(), this.stemId, true);
1763       existingRecord = parent.internal_addChildAttributeDef(GrouperSession.staticGrouperSession(), 
1764           this.extension, this.id, this.attributeDefType, this.description);
1765       if (this.idIndex != null) {
1766         existingRecord.assignIdIndex(this.idIndex);
1767       }
1768     }
1769     this.xmlCopyBusinessPropertiesToExisting(existingRecord);
1770     //if its an insert or update, then do the rest of the fields
1771     existingRecord.store();
1772     return existingRecord;
1773   }
1774 
1775 
1776   /**
1777    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlSaveUpdateProperties()
1778    */
1779   public void xmlSaveUpdateProperties() {
1780     GrouperDAOFactory.getFactory().getAttributeDef().saveUpdateProperties(this);
1781   }
1782 
1783 
1784   /**
1785    * convert to xml bean for export
1786    * @param grouperVersion
1787    * @return xml bean
1788    */
1789   public XmlExportAttributeDef xmlToExportAttributeDef(GrouperVersion grouperVersion) {
1790     if (grouperVersion == null) {
1791       throw new RuntimeException();
1792     }
1793         
1794     XmlExportAttributeDeftributeDef.html#XmlExportAttributeDef">XmlExportAttributeDef xmlExportAttributeDef = new XmlExportAttributeDef();
1795     
1796     xmlExportAttributeDef.setAssignToAttributeDef(this.getAssignToAttributeDefDb());
1797     xmlExportAttributeDef.setAssignToAttributeDefAssn(this.getAssignToAttributeDefAssnDb());
1798     xmlExportAttributeDef.setAssignToEffMembership(this.getAssignToEffMembershipDb());
1799     xmlExportAttributeDef.setAssignToEffMembershipAssn(this.getAssignToEffMembershipAssnDb());
1800     xmlExportAttributeDef.setAssignToGroup(this.getAssignToGroupDb());
1801     xmlExportAttributeDef.setAssignToGroupAssn(this.getAssignToGroupAssnDb());
1802     xmlExportAttributeDef.setAssignToImmMembership(this.getAssignToImmMembershipDb());
1803     xmlExportAttributeDef.setAssignToImmMembershipAssn(this.getAssignToImmMembershipAssnDb());
1804     xmlExportAttributeDef.setAssignToMember(this.getAssignToMemberDb());
1805     xmlExportAttributeDef.setAssignToMemberAssn(this.getAssignToMemberAssnDb());
1806     xmlExportAttributeDef.setAssignToStem(this.getAssignToStemDb());
1807     xmlExportAttributeDef.setAssignToStemAssn(this.getAssignToStemAssnDb());
1808     xmlExportAttributeDef.setAttributeDefPublic(this.getAttributeDefPublicDb());
1809     xmlExportAttributeDef.setAttributeDefType(this.getAttributeDefTypeDb());
1810     xmlExportAttributeDef.setContextId(this.getContextId());
1811     xmlExportAttributeDef.setCreateTime(GrouperUtil.dateStringValue(this.getCreatedOnDb()));
1812     xmlExportAttributeDef.setCreatorId(this.getCreatorId());
1813     xmlExportAttributeDef.setDescription(this.getDescription());
1814     xmlExportAttributeDef.setExtension(this.getExtension());
1815     xmlExportAttributeDef.setHibernateVersionNumber(this.getHibernateVersionNumber());
1816     xmlExportAttributeDef.setIdIndex(this.getIdIndex());
1817     xmlExportAttributeDef.setModifierTime(GrouperUtil.dateStringValue(this.getLastUpdatedDb()));
1818     xmlExportAttributeDef.setMultiAssignable(this.getMultiAssignableDb());
1819     xmlExportAttributeDef.setMultiValued(this.getMultiValuedDb());
1820     xmlExportAttributeDef.setName(this.getName());
1821     xmlExportAttributeDef.setParentStem(this.getStemId());
1822     xmlExportAttributeDef.setUuid(this.getUuid());
1823     xmlExportAttributeDef.setValueType(this.getValueTypeDb());
1824     return xmlExportAttributeDef;
1825   }
1826 
1827   /**
1828    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlGetId()
1829    */
1830   public String xmlGetId() {
1831     return this.getId();
1832   }
1833 
1834   /**
1835    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlSetId(java.lang.String)
1836    */
1837   public void xmlSetId(String theId) {
1838     this.setId(theId);
1839   }
1840   
1841   /**
1842    * @see edu.internet2.middleware.grouper.xml.export.XmlImportableBase#xmlToString()
1843    */
1844   public String xmlToString() {
1845     StringWriter stringWriter = new StringWriter();
1846     
1847     stringWriter.write("AttributeDef: " + this.getId() + ", " + this.getName());
1848 
1849 //    XmlExportUtils.toStringAttributeDef(null, stringWriter, this, false);
1850     
1851     return stringWriter.toString();
1852     
1853   }
1854   
1855   /**
1856    * save the state when retrieving from DB
1857    * @return the dbVersion
1858    */
1859   @Override
1860   public AttributeDef dbVersion() {
1861     return (AttributeDef)this.dbVersion;
1862   }
1863   
1864   /**
1865    * take a snapshot of the data since this is what is in the db
1866    */
1867   @Override
1868   public void dbVersionReset() {
1869     //lets get the state from the db so we know what has changed
1870     this.dbVersion = GrouperUtil.clone(this, DB_VERSION_FIELDS);
1871   }
1872 
1873 
1874   /**
1875    * @see edu.internet2.middleware.grouper.GrouperAPI#dbVersionDifferentFields()
1876    */
1877   @Override
1878   public Set<String> dbVersionDifferentFields() {
1879     if (this.dbVersion == null) {
1880       throw new RuntimeException("State was never stored from db");
1881     }
1882     //easier to unit test if everything is ordered
1883     Set<String> result = GrouperUtil.compareObjectFields(this, this.dbVersion,
1884         DB_VERSION_FIELDS, null);
1885     return result;
1886   }
1887 
1888   /**
1889    * 
1890    * @return the set of types
1891    */
1892   public Set<AttributeAssignType> getAttributeAssignTypes() {
1893     
1894     Set<AttributeAssignType> attributeAssignTypes = new LinkedHashSet<AttributeAssignType>();
1895     
1896     if (this.isAssignToAttributeDef()) {
1897       attributeAssignTypes.add(AttributeAssignType.attr_def);
1898     }
1899     if (this.isAssignToAttributeDefAssn()) {
1900       attributeAssignTypes.add(AttributeAssignType.attr_def_asgn);
1901     }
1902     if (this.isAssignToEffMembership()) {
1903       attributeAssignTypes.add(AttributeAssignType.any_mem);
1904     }
1905     if (this.isAssignToEffMembershipAssn()) {
1906       attributeAssignTypes.add(AttributeAssignType.any_mem_asgn);
1907     }
1908     if (this.isAssignToGroup()) {
1909       attributeAssignTypes.add(AttributeAssignType.group);
1910     }
1911     if (this.isAssignToGroupAssn()) {
1912       attributeAssignTypes.add(AttributeAssignType.group_asgn);
1913     }
1914     if (this.isAssignToImmMembership()) {
1915       attributeAssignTypes.add(AttributeAssignType.imm_mem);
1916     }
1917     if (this.isAssignToImmMembershipAssn()) {
1918       attributeAssignTypes.add(AttributeAssignType.imm_mem_asgn);
1919     }
1920     if (this.isAssignToMember()) {
1921       attributeAssignTypes.add(AttributeAssignType.member);
1922     }
1923     if (this.isAssignToMemberAssn()) {
1924       attributeAssignTypes.add(AttributeAssignType.mem_asgn);
1925     }
1926     if (this.isAssignToStem()) {
1927       attributeAssignTypes.add(AttributeAssignType.stem);
1928     }
1929     if (this.isAssignToStemAssn()) {
1930       attributeAssignTypes.add(AttributeAssignType.stem_asgn);
1931     }
1932     return attributeAssignTypes;
1933   }
1934   
1935   /**
1936    * @see edu.internet2.middleware.grouper.GrouperAPI#onPostDelete(edu.internet2.middleware.grouper.hibernate.HibernateSession)
1937    */
1938   @Override
1939   public void onPostDelete(HibernateSession hibernateSession) {
1940     super.onPostDelete(hibernateSession);
1941   
1942     this.dbVersionClear();
1943 
1944     GrouperHooksUtils.schedulePostCommitHooksIfRegistered(GrouperHookType.ATTRIBUTE_DEF, 
1945         AttributeDefHooks.METHOD_ATTRIBUTE_DEF_POST_COMMIT_DELETE, HooksAttributeDefBean.class, 
1946         this, AttributeDef.class);
1947   
1948     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF, 
1949         AttributeDefHooks.METHOD_ATTRIBUTE_DEF_POST_DELETE, HooksAttributeDefBean.class, 
1950         this, AttributeDef.class, VetoTypeGrouper.ATTRIBUTE_DEF_POST_DELETE, false, true);
1951   
1952   }
1953 
1954   /**
1955    * @see edu.internet2.middleware.grouper.hibernate.HibGrouperLifecycle#onPostSave(edu.internet2.middleware.grouper.hibernate.HibernateSession)
1956    */
1957   @Override
1958   public void onPostSave(HibernateSession hibernateSession) {
1959   
1960     super.onPostSave(hibernateSession);
1961     
1962     this.dbVersionClear();
1963 
1964     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF, 
1965         AttributeDefHooks.METHOD_ATTRIBUTE_DEF_POST_INSERT, HooksAttributeDefBean.class, 
1966         this, AttributeDef.class, VetoTypeGrouper.ATTRIBUTE_DEF_POST_INSERT, true, false);
1967   
1968     //do these second so the right object version is set, and dbVersion is ok
1969     GrouperHooksUtils.schedulePostCommitHooksIfRegistered(GrouperHookType.ATTRIBUTE_DEF, 
1970         AttributeDefHooks.METHOD_ATTRIBUTE_DEF_POST_COMMIT_INSERT, HooksAttributeDefBean.class, 
1971         this, AttributeDef.class);
1972   
1973   
1974   }
1975 
1976   /**
1977    * @see edu.internet2.middleware.grouper.hibernate.HibGrouperLifecycle#onPostUpdate(HibernateSession)
1978    */
1979   public void onPostUpdate(HibernateSession hibernateSession) {
1980     
1981     if (this.dbVersionDifferentFields().contains(FIELD_NAME)) {
1982       GrouperSession.callbackGrouperSession(GrouperSession.staticGrouperSession().internal_getRootSession(), new GrouperSessionHandler() {
1983   
1984         /**
1985          * @see edu.internet2.middleware.grouper.misc.GrouperSessionHandler#callback(edu.internet2.middleware.grouper.GrouperSession)
1986          */
1987         public Object callback(GrouperSession rootSession) throws GrouperSessionException {
1988 
1989           // need to potentially update attribute def name in rules
1990           Set<RuleDefinition> definitions = RuleEngine.ruleEngine().getRuleDefinitions();
1991           for (RuleDefinition definition : definitions) {
1992             if (definition.getCheck() != null && definition.getCheck().checkTypeEnum() != null && 
1993                 definition.getCheck().checkTypeEnum().isCheckOwnerTypeAttributeDef(definition) && AttributeDef.this.dbVersion().getName().equals(definition.getCheck().getCheckOwnerName())) {
1994               definition.getAttributeAssignType().getAttributeValueDelegate().assignValue(RuleUtils.ruleCheckOwnerNameName(), AttributeDef.this.getName());
1995             }
1996             
1997             if (definition.getIfCondition() != null && definition.getIfCondition().ifConditionEnum() != null &&
1998                 definition.getIfCondition().ifConditionEnum().isIfOwnerTypeAttributeDef(definition) && AttributeDef.this.dbVersion().getName().equals(definition.getIfCondition().getIfOwnerName())) {
1999               definition.getAttributeAssignType().getAttributeValueDelegate().assignValue(RuleUtils.ruleIfOwnerNameName(), AttributeDef.this.getName());
2000             }
2001           }
2002           
2003           return null;
2004         }
2005       });
2006     }
2007     
2008     super.onPostUpdate(hibernateSession);
2009     
2010     this.dbVersionClear();
2011 
2012     GrouperHooksUtils.schedulePostCommitHooksIfRegistered(GrouperHookType.ATTRIBUTE_DEF, 
2013         AttributeDefHooks.METHOD_ATTRIBUTE_DEF_POST_COMMIT_UPDATE, HooksAttributeDefBean.class, 
2014         this, AttributeDef.class);
2015   
2016     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF, 
2017         AttributeDefHooks.METHOD_ATTRIBUTE_DEF_POST_UPDATE, HooksAttributeDefBean.class, 
2018         this, AttributeDef.class, VetoTypeGrouper.ATTRIBUTE_DEF_POST_UPDATE, true, false);
2019   
2020   
2021   }
2022 
2023   /**
2024    * @see edu.internet2.middleware.grouper.GrouperAPI#onPreDelete(edu.internet2.middleware.grouper.hibernate.HibernateSession)
2025    */
2026   @Override
2027   public void onPreDelete(HibernateSession hibernateSession) {
2028     super.onPreDelete(hibernateSession);
2029   
2030     //change log into temp table
2031     new ChangeLogEntry(true, ChangeLogTypeBuiltin.ATTRIBUTE_DEF_DELETE, 
2032         ChangeLogLabels.ATTRIBUTE_DEF_DELETE.id.name(), this.getUuid(), 
2033         ChangeLogLabels.ATTRIBUTE_DEF_DELETE.name.name(), this.getName(), 
2034         ChangeLogLabels.ATTRIBUTE_DEF_DELETE.stemId.name(), this.getStemId(),
2035         ChangeLogLabels.ATTRIBUTE_DEF_DELETE.description.name(), this.getDescription(),
2036         ChangeLogLabels.ATTRIBUTE_DEF_DELETE.attributeDefType.name(), this.getAttributeDefTypeDb()).save();
2037 
2038     Hib3AttributeDefDAO.attributeDefCacheRemove(this);
2039 
2040     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF, 
2041         AttributeDefHooks.METHOD_ATTRIBUTE_DEF_PRE_DELETE, HooksAttributeDefBean.class, 
2042         this, AttributeDef.class, VetoTypeGrouper.ATTRIBUTE_DEF_PRE_DELETE, false, false);
2043   }
2044 
2045   /**
2046    * 
2047    * @see edu.internet2.middleware.grouper.GrouperAPI#onPreSave(edu.internet2.middleware.grouper.hibernate.HibernateSession)
2048    */
2049   @Override
2050   public void onPreSave(HibernateSession hibernateSession) {
2051     super.onPreSave(hibernateSession);
2052     
2053     if (this.creatorId == null) {
2054       this.creatorId = GrouperSession.staticGrouperSession(true).getMemberUuid();
2055     }
2056     if (this.createdOnDb == null) {
2057       this.createdOnDb = System.currentTimeMillis();
2058     }
2059     
2060     if (this.idIndex == null) {
2061       this.idIndex = TableIndex.reserveId(TableIndexType.attributeDef);
2062     }
2063     
2064     //change log into temp table
2065     new ChangeLogEntry(true, ChangeLogTypeBuiltin.ATTRIBUTE_DEF_ADD, 
2066         ChangeLogLabels.ATTRIBUTE_DEF_ADD.id.name(), this.getUuid(), 
2067         ChangeLogLabels.ATTRIBUTE_DEF_ADD.name.name(), this.getName(), 
2068         ChangeLogLabels.ATTRIBUTE_DEF_ADD.stemId.name(), this.getStemId(),
2069         ChangeLogLabels.ATTRIBUTE_DEF_ADD.description.name(), this.getDescription(),
2070         ChangeLogLabels.ATTRIBUTE_DEF_ADD.attributeDefType.name(), this.getAttributeDefTypeDb()).save();
2071 
2072     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF, 
2073         AttributeDefHooks.METHOD_ATTRIBUTE_DEF_PRE_INSERT, HooksAttributeDefBean.class, 
2074         this, AttributeDef.class, VetoTypeGrouper.ATTRIBUTE_DEF_PRE_INSERT, false, false);
2075     
2076   }
2077 
2078   /**
2079    * @see edu.internet2.middleware.grouper.GrouperAPI#onPreUpdate(edu.internet2.middleware.grouper.hibernate.HibernateSession)
2080    */
2081   @Override
2082   public void onPreUpdate(HibernateSession hibernateSession) {
2083     super.onPreUpdate(hibernateSession);
2084     this.lastUpdatedDb = System.currentTimeMillis();
2085     
2086     if (this.dbVersionDifferentFields().contains(FIELD_STEM_ID)) {
2087       throw new RuntimeException("cannot update stemId");
2088     }
2089     
2090     if (this.dbVersionDifferentFields().contains(FIELD_ATTRIBUTE_DEF_TYPE)) {
2091       throw new RuntimeException("cannot update attributeDefType");
2092     }
2093     
2094     if (this.dbVersionDifferentFields().contains(FIELD_NAME) || this.dbVersionDifferentFields().contains(FIELD_EXTENSION)) {
2095       // don't allow renames for legacy attributes
2096       String stemName = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.baseStem");
2097       String groupTypeDefPrefix = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.groupTypeDef.prefix");
2098       String attributeDefPrefix = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.attributeDef.prefix");
2099       String customListDefPrefix = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.customListDef.prefix");
2100       
2101       String oldName = this.dbVersion().getNameDb();
2102       if (oldName.startsWith(stemName + ":" + groupTypeDefPrefix) ||
2103           oldName.startsWith(stemName + ":" + attributeDefPrefix) ||
2104           oldName.startsWith(stemName + ":" + customListDefPrefix)) {
2105         throw new RuntimeException("cannot update name for legacy attributes");
2106       }
2107     }
2108     
2109     Hib3AttributeDefDAO.attributeDefCacheRemove(this);
2110 
2111     //change log into temp table
2112     ChangeLogEntry.saveTempUpdates(ChangeLogTypeBuiltin.ATTRIBUTE_DEF_UPDATE, 
2113         this, this.dbVersion(),
2114         GrouperUtil.toList(
2115             ChangeLogLabels.ATTRIBUTE_DEF_UPDATE.id.name(),this.getUuid(), 
2116             ChangeLogLabels.ATTRIBUTE_DEF_UPDATE.name.name(), this.getName(),
2117             ChangeLogLabels.ATTRIBUTE_DEF_UPDATE.stemId.name(), this.getStemId(),
2118             ChangeLogLabels.ATTRIBUTE_DEF_UPDATE.description.name(), this.getDescription(),
2119             ChangeLogLabels.ATTRIBUTE_DEF_UPDATE.attributeDefType.name(), this.getAttributeDefTypeDb()),
2120         GrouperUtil.toList(FIELD_NAME, FIELD_DESCRIPTION),
2121         GrouperUtil.toList(
2122             ChangeLogLabels.ATTRIBUTE_DEF_UPDATE.name.name(),
2123             ChangeLogLabels.ATTRIBUTE_DEF_UPDATE.description.name()));   
2124 
2125     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF, 
2126         AttributeDefHooks.METHOD_ATTRIBUTE_DEF_PRE_UPDATE, HooksAttributeDefBean.class, 
2127         this, AttributeDef.class, VetoTypeGrouper.ATTRIBUTE_DEF_PRE_UPDATE, false, false);
2128   
2129   }
2130 
2131 
2132   /**
2133    * @see Comparable#compareTo(Object)
2134    */
2135   public int compareTo(GrouperObject that) {
2136     if (that==null) {
2137       return 1;
2138     }
2139     String thisName = StringUtils.defaultString(this.getName());
2140     String thatName = StringUtils.defaultString(that.getName());
2141     return thisName.compareTo(thatName);
2142   }
2143 
2144 
2145   /**
2146    * id of the group as a unique integer
2147    * @return id
2148    */
2149   public Long getIdIndex() {
2150     return this.idIndex;
2151   }
2152 
2153 
2154   /**
2155    * id of the group as a unique integer
2156    * @param idIndex1
2157    */
2158   public void setIdIndex(Long idIndex1) {
2159     this.idIndex = idIndex1;
2160   }
2161 
2162 
2163   /**
2164    * assign different id index
2165    * @param theIdIndex
2166    * @return if it was changed
2167    */
2168   public boolean assignIdIndex(final long theIdIndex) {
2169     
2170     TableIndex.assertCanAssignIdIndex();
2171 
2172     boolean needsSave = false;
2173     
2174     synchronized (TableIndexType.attributeDef) {
2175 
2176       //ok, if the index is not in use (not, it could be reserved... hmmm)
2177       AttributeDef tempAttributeDef = GrouperDAOFactory.getFactory().getAttributeDef().findByIdIndex(theIdIndex, false, null);
2178       if (tempAttributeDef == null) {
2179         
2180         this.setIdIndex(theIdIndex);
2181         TableIndex.clearReservedId(TableIndexType.attributeDef, theIdIndex);
2182         needsSave = true;
2183         
2184         //do a new session so we don hold on too long
2185         HibernateSession.callbackHibernateSession(GrouperTransactionType.READ_WRITE_NEW, AuditControl.WILL_NOT_AUDIT, new HibernateHandler() {
2186           
2187           @Override
2188           public Object callback(HibernateHandlerBean hibernateHandlerBean)
2189               throws GrouperDAOException {
2190             //now we might need to increment the index
2191             TableIndex tableIndex = GrouperDAOFactory.getFactory().getTableIndex().findByType(TableIndexType.attributeDef);
2192             if (tableIndex != null && tableIndex.getLastIndexReserved() < theIdIndex) {
2193               tableIndex.setLastIndexReserved(theIdIndex);
2194               tableIndex.saveOrUpdate();
2195             }
2196             return null;
2197           }
2198         });
2199       }      
2200     }
2201     return needsSave;
2202   }
2203 
2204   /**
2205    * @see GrouperObject#getDisplayName()
2206    */
2207   @Override
2208   public String getDisplayName() {
2209     return this.getParentStem().getDisplayName() + ":" + this.extension; 
2210   }
2211 
2212   /**
2213    * @see GrouperObject#matchesLowerSearchStrings(Set)
2214    */
2215   @Override
2216   public boolean matchesLowerSearchStrings(Set<String> filterStrings) {
2217 
2218     if (GrouperUtil.length(filterStrings) == 0) {
2219       return true;
2220     }
2221 
2222     String lowerId = this.getId().toLowerCase();
2223     String lowerName = StringUtils.defaultString(this.getName()).toLowerCase();
2224     String lowerDisplayName = StringUtils.defaultString(this.getDisplayName()).toLowerCase();
2225     String lowerDescription = StringUtils.defaultString(this.getDescription()).toLowerCase();
2226     
2227     for (String filterString : GrouperUtil.nonNull(filterStrings)) {
2228       
2229       //if all dont match, return false
2230       if (!lowerId.contains(filterString)
2231           && !lowerName.contains(filterString)
2232           && !lowerDisplayName.contains(filterString)
2233           && !lowerDescription.contains(filterString)) {
2234         return false;
2235       }
2236       
2237     }
2238     return true;
2239   }
2240 
2241   
2242 }