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.ArrayList;
24  import java.util.Collections;
25  import java.util.Comparator;
26  import java.util.List;
27  import java.util.Set;
28  
29  import edu.internet2.middleware.grouperClient.collections.MultiKey;
30  import org.apache.commons.lang.StringUtils;
31  import org.apache.commons.lang.builder.HashCodeBuilder;
32  import org.apache.commons.lang.builder.ToStringBuilder;
33  import org.apache.commons.logging.Log;
34  
35  import edu.internet2.middleware.grouper.GroupType;
36  import edu.internet2.middleware.grouper.GrouperAPI;
37  import edu.internet2.middleware.grouper.GrouperSession;
38  import edu.internet2.middleware.grouper.Stem;
39  import edu.internet2.middleware.grouper.StemFinder;
40  import edu.internet2.middleware.grouper.annotations.GrouperIgnoreClone;
41  import edu.internet2.middleware.grouper.annotations.GrouperIgnoreDbVersion;
42  import edu.internet2.middleware.grouper.annotations.GrouperIgnoreFieldConstant;
43  import edu.internet2.middleware.grouper.attr.assign.AttributeAssign;
44  import edu.internet2.middleware.grouper.attr.finder.AttributeDefFinder;
45  import edu.internet2.middleware.grouper.audit.AuditEntry;
46  import edu.internet2.middleware.grouper.audit.AuditTypeBuiltin;
47  import edu.internet2.middleware.grouper.cache.GrouperCache;
48  import edu.internet2.middleware.grouper.cfg.GrouperConfig;
49  import edu.internet2.middleware.grouper.changeLog.ChangeLogEntry;
50  import edu.internet2.middleware.grouper.changeLog.ChangeLogLabels;
51  import edu.internet2.middleware.grouper.changeLog.ChangeLogTypeBuiltin;
52  import edu.internet2.middleware.grouper.ddl.GrouperDdlUtils;
53  import edu.internet2.middleware.grouper.exception.GrouperSessionException;
54  import edu.internet2.middleware.grouper.exception.GrouperValidationException;
55  import edu.internet2.middleware.grouper.exception.InsufficientPrivilegeException;
56  import edu.internet2.middleware.grouper.grouperSet.GrouperSetElement;
57  import edu.internet2.middleware.grouper.hibernate.AuditControl;
58  import edu.internet2.middleware.grouper.hibernate.GrouperTransactionType;
59  import edu.internet2.middleware.grouper.hibernate.HibernateHandler;
60  import edu.internet2.middleware.grouper.hibernate.HibernateHandlerBean;
61  import edu.internet2.middleware.grouper.hibernate.HibernateSession;
62  import edu.internet2.middleware.grouper.hooks.AttributeDefNameHooks;
63  import edu.internet2.middleware.grouper.hooks.GroupTypeHooks;
64  import edu.internet2.middleware.grouper.hooks.beans.HooksAttributeDefNameBean;
65  import edu.internet2.middleware.grouper.hooks.beans.HooksGroupTypeBean;
66  import edu.internet2.middleware.grouper.hooks.logic.GrouperHookType;
67  import edu.internet2.middleware.grouper.hooks.logic.GrouperHooksUtils;
68  import edu.internet2.middleware.grouper.hooks.logic.VetoTypeGrouper;
69  import edu.internet2.middleware.grouper.internal.dao.GrouperDAOException;
70  import edu.internet2.middleware.grouper.internal.dao.QueryOptions;
71  import edu.internet2.middleware.grouper.internal.dao.hib3.Hib3AttributeDefNameDAO;
72  import edu.internet2.middleware.grouper.internal.dao.hib3.Hib3GrouperVersioned;
73  import edu.internet2.middleware.grouper.misc.GrouperDAOFactory;
74  import edu.internet2.middleware.grouper.misc.GrouperHasContext;
75  import edu.internet2.middleware.grouper.misc.GrouperObject;
76  import edu.internet2.middleware.grouper.misc.GrouperSessionHandler;
77  import edu.internet2.middleware.grouper.misc.GrouperVersion;
78  import edu.internet2.middleware.grouper.tableIndex.TableIndex;
79  import edu.internet2.middleware.grouper.tableIndex.TableIndexType;
80  import edu.internet2.middleware.grouper.util.GrouperUtil;
81  import edu.internet2.middleware.grouper.xml.export.XmlExportAttributeDefName;
82  import edu.internet2.middleware.grouper.xml.export.XmlImportable;
83  import edu.internet2.middleware.subject.Subject;
84  
85  
86  /**
87   * definition of an attribute name (is linked with an attribute def)
88   * @author mchyzer
89   */
90  @SuppressWarnings("serial")
91  public class AttributeDefName extends GrouperAPI 
92      implements GrouperHasContext, Hib3GrouperVersioned, GrouperSetElement, 
93      XmlImportable<AttributeDefName>, Comparable<GrouperObject>, GrouperObject {
94  
95    /**
96     * 
97     */
98    public static final String VALIDATION_NAME_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY = "nameOfAttributeDefNameTooLong";
99  
100   /**
101    * 
102    */
103   public static final String VALIDATION_DISPLAY_NAME_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY = "displayNameOfAttributeDefNameTooLong";
104 
105   /**
106    * 
107    */
108   public static final String VALIDATION_DECRIPTION_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY = "decriptionOfAttributeDefNameTooLong";
109 
110   /**
111    * 
112    */
113   public static final String VALIDATION_EXTENSION_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY = "extensionOfAttributeDefNameTooLong";
114 
115   /**
116    * 
117    */
118   public static final String VALIDATION_DISPLAY_EXTENSION_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY = "displayExtensionOfAttributeDefNameTooLong";
119 
120   /** name of the groups attribute def name table in the db */
121   public static final String TABLE_GROUPER_ATTRIBUTE_DEF_NAME = "grouper_attribute_def_name";
122 
123   /** column */
124   public static final String COLUMN_ATTRIBUTE_DEF_ID = "attribute_def_id";
125 
126   /** column */
127   public static final String COLUMN_CONTEXT_ID = "context_id";
128 
129   /** column */
130   public static final String COLUMN_CREATED_ON = "created_on";
131 
132   /** column */
133   public static final String COLUMN_LAST_UPDATED = "last_updated";
134 
135   /** column */
136   public static final String COLUMN_DESCRIPTION = "description";
137 
138   /** column */
139   public static final String COLUMN_EXTENSION = "extension";
140 
141   /** column */
142   public static final String COLUMN_NAME = "name";
143 
144   /** column */
145   public static final String COLUMN_DISPLAY_EXTENSION = "display_extension";
146 
147   /** column */
148   public static final String COLUMN_DISPLAY_NAME = "display_name";
149 
150   /** column */
151   public static final String COLUMN_STEM_ID = "stem_id";
152 
153   /** column */
154   public static final String COLUMN_ID = "id";
155 
156   /** unique number for this attributeDefName */
157   public static final String COLUMN_ID_INDEX = "id_index";
158 
159   //*****  START GENERATED WITH GenerateFieldConstants.java *****//
160 
161   /** constant for field name for: attributeDefId */
162   public static final String FIELD_ATTRIBUTE_DEF_ID = "attributeDefId";
163 
164   /** constant for field name for: contextId */
165   public static final String FIELD_CONTEXT_ID = "contextId";
166 
167   /** constant for field name for: createdOnDb */
168   public static final String FIELD_CREATED_ON_DB = "createdOnDb";
169 
170   /** constant for field name for: description */
171   public static final String FIELD_DESCRIPTION = "description";
172 
173   /** constant for field name for: displayExtension */
174   public static final String FIELD_DISPLAY_EXTENSION = "displayExtension";
175 
176   /** constant for field name for: displayName */
177   public static final String FIELD_DISPLAY_NAME = "displayName";
178 
179   /** constant for field name for: extension */
180   public static final String FIELD_EXTENSION = "extension";
181 
182   /** constant for field name for: id */
183   public static final String FIELD_ID = "id";
184 
185   /** constant for field name for: idIndex */
186   public static final String FIELD_ID_INDEX = "idIndex";
187 
188   /** constant for field name for: lastUpdatedDb */
189   public static final String FIELD_LAST_UPDATED_DB = "lastUpdatedDb";
190 
191   /** constant for field name for: name */
192   public static final String FIELD_NAME = "name";
193 
194   /** constant for field name for: stemId */
195   public static final String FIELD_STEM_ID = "stemId";
196 
197   /**
198    * fields which are included in db version
199    */
200   private static final Set<String> DB_VERSION_FIELDS = GrouperUtil.toSet(
201       FIELD_ATTRIBUTE_DEF_ID, FIELD_CONTEXT_ID, FIELD_CREATED_ON_DB, FIELD_DESCRIPTION, 
202       FIELD_DISPLAY_EXTENSION, FIELD_DISPLAY_NAME, FIELD_EXTENSION, FIELD_ID, FIELD_ID_INDEX, 
203       FIELD_LAST_UPDATED_DB, FIELD_NAME, FIELD_STEM_ID);
204 
205   /**
206    * fields which are included in clone method
207    */
208   private static final Set<String> CLONE_FIELDS = GrouperUtil.toSet(
209       FIELD_ATTRIBUTE_DEF_ID, FIELD_CONTEXT_ID, FIELD_CREATED_ON_DB, FIELD_DB_VERSION, 
210       FIELD_DESCRIPTION, FIELD_DISPLAY_EXTENSION, FIELD_DISPLAY_NAME, FIELD_EXTENSION, 
211       FIELD_HIBERNATE_VERSION_NUMBER, FIELD_ID, FIELD_ID_INDEX, FIELD_LAST_UPDATED_DB, FIELD_NAME, 
212       FIELD_STEM_ID);
213 
214   //*****  END GENERATED WITH GenerateFieldConstants.java *****//
215 
216   /**
217    * cache of multikey (attributeDefId, sourceId, subjectId) to true or false if allowed to admin attributeDefId
218    */
219   static GrouperCache<MultiKey, Boolean> canAdminAttributeDef = null;
220   
221   /**
222    * 
223    * @return
224    */
225   static GrouperCache<MultiKey, Boolean> canAdminAttributeDef() {
226     if (canAdminAttributeDef == null) {
227       canAdminAttributeDef = new GrouperCache<MultiKey, Boolean>(
228           AttributeDefName.class.getName() + ".CanAdminAttributeDef", 5000, false, 5, 5, false);
229     }
230     return canAdminAttributeDef;
231   }
232 
233   /**
234    * make sure this attribute def can admin from grouper session
235    */
236   public void assertCanAdminAttributeDefStatic() {
237     
238     Subject subject = GrouperSession.staticGrouperSession().getSubject();
239     MultiKey cacheKey = new MultiKey(this.attributeDefId, subject.getSourceId(), subject.getId());
240     Boolean result = canAdminAttributeDef().get(cacheKey);
241     AttributeDef attributeDef = null;
242     
243     //if not in cache, calculate
244     if (result == null) {
245       attributeDef = this.getAttributeDef();
246       result = attributeDef.getPrivilegeDelegate().canAttrAdmin(subject);
247       
248       //add back to cache since wasnt cached
249       canAdminAttributeDef().put(cacheKey, result);
250     }
251     
252     //false means cant admin
253     if (!result) {
254       
255       attributeDef = attributeDef == null ? this.getAttributeDef() : attributeDef;
256       
257       throw new InsufficientPrivilegeException(GrouperUtil
258           .subjectToString(subject)
259           + " is not attrAdmin on attributeDef: " + attributeDef.getName() 
260           + ", concerning attributeDefName: " + this.getName());
261     }
262     
263   }
264 
265 
266 
267   /**
268    * deep clone the fields in this object
269    */
270   @Override
271   public AttributeDefName clone() {
272     return GrouperUtil.clone(this, CLONE_FIELDS);
273   }
274 
275 
276   /** id of this attribute def name */
277   private String id;
278 
279   /** cache the attributeDef */
280   @GrouperIgnoreClone @GrouperIgnoreDbVersion @GrouperIgnoreFieldConstant
281   private transient AttributeDef attributeDef;
282 
283   /**
284    * get the attribute def
285    * @return the attribute def
286    */
287   public AttributeDef getAttributeDef() {
288     if (this.attributeDef == null) {
289       this.attributeDef = AttributeDefFinder.findById(this.attributeDefId, true);
290     }
291     return this.attributeDef;
292   }
293   
294   /** id of this attribute def  */
295   private String attributeDefId;
296 
297   /** context id of the transaction */
298   private String contextId;
299 
300   /** stem that this attribute is in */
301   private String stemId;
302 
303   /**
304    * stem that this attribute is in
305    * @return the stem id
306    */
307   public Stem getStem() {
308     return this.stemId == null ? null : StemFinder.findByUuid(GrouperSession.staticGrouperSession(), this.stemId, true);
309   }
310 
311   /**
312    * name of attribute, e.g. school:community:students:expireDate 
313    */
314   private String name;
315 
316   /**
317    * description of attribute, friendly description, e.g. in sentence form, 
318    * about what the attribute is about 
319    */
320   private String description;
321 
322   /**
323    * displayExtension of attribute, e.g. Expire Date
324    */
325   private String displayExtension;
326 
327   /**
328    * displayName of attribute, e.g. My School:Community Groups:Expire Date 
329    */
330   private String displayName;
331 
332   /**
333    * extension of attribute expireTime
334    */
335   private String extension;
336 
337   /**
338    * time in millis when this attribute was created
339    */
340   private Long createdOnDb;
341 
342   /**
343    * time in millis when this attribute was last modified
344    */
345   private Long lastUpdatedDb;
346 
347   /**
348    * this method makes this class more compatible with Group and Stem
349    * @return the parent stem id
350    */
351   public String getParentUuid() {
352     return this.stemId;
353   }
354 
355   /**
356    * stem that this attribute is in
357    * @return the stem id
358    */
359   public String getStemId() {
360     return this.stemId;
361   }
362 
363   /**
364    * stem that this attribute is in
365    * @param stemId1
366    */
367   public void setStemId(String stemId1) {
368     this.stemId = stemId1;
369   }
370 
371   /**
372    * context id of the transaction
373    * @return context id
374    */
375   public String getContextId() {
376     return this.contextId;
377   }
378 
379   /**
380    * context id of the transaction
381    * @param contextId1
382    */
383   public void setContextId(String contextId1) {
384     this.contextId = contextId1;
385   }
386 
387   /**
388    * id of this attribute def name
389    * @return id
390    */
391   public String getId() {
392     return this.id;
393   }
394 
395   /**
396    * id of this attribute def name
397    * @return id
398    */
399   public String getUuid() {
400     return this.id;
401   }
402 
403   /**
404    * id of this attribute def name
405    * @param id1
406    */
407   public void setId(String id1) {
408     this.id = id1;
409   }
410 
411   
412   /**
413    * 
414    * @return the name
415    */
416   public String getName() {
417     return this.name;
418   }
419 
420   /**
421    * 
422    * @param name1
423    */
424   public void setName(@SuppressWarnings("unused") String name1) {
425     throw new RuntimeException("Dont call this method");
426   }
427 
428   /**
429    * 
430    * @return the name
431    */
432   public String getNameDb() {
433     return this.name;
434   }
435 
436   /**
437    * 
438    * @param name1
439    */
440   public void setNameDb(String name1) {
441     this.name = name1;
442   }
443 
444   /**
445    * description of attribute, friendly description, e.g. in sentence form, 
446    * about what the attribute is about 
447    * @return the description
448    */
449   public String getDescription() {
450     return this.description;
451   }
452 
453   /**
454    * description of attribute, friendly description, e.g. in sentence form, 
455    * about what the attribute is about 
456    * @param description1
457    */
458   public void setDescription(String description1) {
459     this.description = description1;
460   }
461 
462   /**
463    * displayExtension of attribute, e.g. Expire Date
464    * @return display extension
465    */
466   public String getDisplayExtension() {
467     return this.displayExtension;
468   }
469 
470   /**
471    * displayExtension of attribute, e.g. Expire Date
472    * @param displayExtension1
473    */
474   public void setDisplayExtension(@SuppressWarnings("unused") String displayExtension1) {
475     throw new RuntimeException("Dont call this method");
476   }
477 
478   /**
479    * displayName of attribute, e.g. My School:Community Groups:Expire Date 
480    * @return display name
481    */
482   public String getDisplayName() {
483     return this.displayName;
484   }
485 
486   /**
487    * displayName of attribute, e.g. My School:Community Groups:Expire Date 
488    * @param displayName1
489    */
490   public void setDisplayName(@SuppressWarnings("unused") String displayName1) {
491     throw new RuntimeException("Dont call this method");
492   }
493 
494   /**
495    * extension of attribute expireTime
496    * @return extension
497    */
498   public String getExtension() {
499     return this.extension;
500   }
501 
502   /**
503    * extension of attribute expireTime
504    * @param extension1
505    */
506   public void setExtension(@SuppressWarnings("unused") String extension1) {
507     throw new RuntimeException("Dont call this method");
508   }
509 
510   /**
511    * extension of attribute expireTime
512    * @return extension
513    */
514   public String getExtensionDb() {
515     return this.extension;
516   }
517 
518   /**
519    * extension of attribute expireTime
520    * @param extension1
521    */
522   public void setExtensionDb(String extension1) {
523     this.extension = extension1;
524   }
525 
526   /**
527    * when last updated
528    * @return timestamp
529    */
530   public Timestamp getLastUpdated() {
531     return this.lastUpdatedDb == null ? null : new Timestamp(this.lastUpdatedDb);
532   }
533 
534   /**
535    * when last updated
536    * @return timestamp
537    */
538   public Long getLastUpdatedDb() {
539     return this.lastUpdatedDb;
540   }
541 
542   /**
543    * when created
544    * @return timestamp
545    */
546   public Timestamp getCreatedOn() {
547     return this.createdOnDb == null ? null : new Timestamp(this.createdOnDb);
548   }
549 
550   /**
551    * when created
552    * @return timestamp
553    */
554   public Long getCreatedOnDb() {
555     return this.createdOnDb;
556   }
557 
558   /**
559    * when last updated
560    * @param lastUpdated1
561    */
562   public void setLastUpdated(Timestamp lastUpdated1) {
563     this.lastUpdatedDb = lastUpdated1 == null ? null : lastUpdated1.getTime();
564   }
565 
566   /**
567    * when last updated
568    * @param lastUpdated1
569    */
570   public void setLastUpdatedDb(Long lastUpdated1) {
571     this.lastUpdatedDb = lastUpdated1;
572   }
573 
574   /**
575    * when created
576    * @param createdOn1
577    */
578   public void setCreatedOn(Timestamp createdOn1) {
579     this.createdOnDb = createdOn1 == null ? null : createdOn1.getTime();
580   }
581 
582   /**
583    * when created
584    * @param createdOn1
585    */
586   public void setCreatedOnDb(Long createdOn1) {
587     this.createdOnDb = createdOn1;
588   }
589 
590   /**
591    * displayExtension of attribute, e.g. Expire Date
592    * @return display extension
593    */
594   public String getDisplayExtensionDb() {
595     return this.displayExtension;
596   }
597 
598   /**
599    * displayExtension of attribute, e.g. Expire Date
600    * @param displayExtension1
601    */
602   public void setDisplayExtensionDb(String displayExtension1) {
603     this.displayExtension = displayExtension1;
604   }
605 
606   /**
607    * displayName of attribute, e.g. My School:Community Groups:Expire Date 
608    * @return display name
609    */
610   public String getDisplayNameDb() {
611     return this.displayName;
612   }
613 
614   /**
615    * displayName of attribute, e.g. My School:Community Groups:Expire Date 
616    * @param displayName1
617    */
618   public void setDisplayNameDb(String displayName1) {
619     this.displayName = displayName1;
620   }
621 
622   /**
623    * attribute definition that this is related to
624    * @return the attribute def id
625    */
626   public String getAttributeDefId() {
627     return this.attributeDefId;
628   }
629 
630   /**
631    * attribute def id that this is related to
632    * @param attributeDefId1
633    */
634   public void setAttributeDefId(String attributeDefId1) {
635     this.attributeDefId = attributeDefId1;
636     this.attributeDef = null;
637   }
638   
639   /** logger */
640   @SuppressWarnings("unused")
641   private static final Log LOG = GrouperUtil.getLog(AttributeDefName.class);
642 
643   /**
644    * @see edu.internet2.middleware.grouper.grouperSet.GrouperSetElement#__getId()
645    */
646   public String __getId() {
647     return this.getId();
648   }
649 
650   /**
651    * @see edu.internet2.middleware.grouper.grouperSet.GrouperSetElement#__getName()
652    */
653   public String __getName() {
654     return this.getName();
655   }
656   
657   /**
658    * save or update this object
659    */
660   public void delete() {
661     
662     HibernateSession.callbackHibernateSession(GrouperTransactionType.READ_WRITE_OR_USE_EXISTING, AuditControl.WILL_AUDIT, new HibernateHandler() {
663       
664       public Object callback(HibernateHandlerBean hibernateHandlerBean)
665           throws GrouperDAOException {
666 
667         HibernateSession hibernateSession = hibernateHandlerBean.getHibernateSession();
668 
669         hibernateSession.setCachingEnabled(false);
670         
671         //make sure subject is allowed to do this
672         Subject subject = GrouperSession.staticGrouperSession().getSubject();
673         AttributeDef attributeDef2 = AttributeDefName.this.getAttributeDef();
674         if (!attributeDef2.getPrivilegeDelegate().canAttrAdmin(subject)) {
675           throw new InsufficientPrivilegeException(GrouperUtil
676               .subjectToString(subject)
677               + " is not attrAdmin on attributeDef: " + attributeDef2.getName());
678         }
679         
680         //we need to find all sets related to this node, and delete them (in reverse order since
681         //parents might point back)
682         Set<AttributeDefNameSet> attributeDefNameSets = GrouperDAOFactory.getFactory()
683           .getAttributeDefNameSet()
684           .findByIfThenHasAttributeDefNameId(AttributeDefName.this.id, 
685               AttributeDefName.this.id);
686 
687         List<AttributeDefNameSet> attributeDefNameSetsList = 
688           new ArrayList<AttributeDefNameSet>(attributeDefNameSets);
689         
690         //sort in reverse depth
691         Collections.sort(attributeDefNameSetsList, new Comparator<AttributeDefNameSet>() {
692           
693           /**
694            * compare two items
695            * @param first first item
696            * @param second item
697            * @return -1, 0, 1
698            */
699           public int compare(AttributeDefNameSet./../edu/internet2/middleware/grouper/attr/AttributeDefNameSet.html#AttributeDefNameSet">AttributeDefNameSet first, AttributeDefNameSet second) {
700             if (first == second) {
701               return 0;
702             }
703             if (first == null) {
704               return -1;
705             }
706             if (second == null) {
707               return 1;
708             }
709             return ((Integer)first.getDepth()).compareTo(second.getDepth());
710           }
711         });
712         
713         Collections.reverse(attributeDefNameSetsList);
714         
715         for(AttributeDefNameSet attributeDefNameSet : attributeDefNameSetsList) {
716           //I believe mysql has problems deleting self referential foreign keys
717           attributeDefNameSet.setParentAttrDefNameSetId(null);
718           attributeDefNameSet.saveOrUpdate();
719           attributeDefNameSet.delete();
720         }
721 
722         //delete any attributes on this stem, this is done as root
723         GrouperSession.internal_callbackRootGrouperSession(new GrouperSessionHandler() {
724           
725           public Object callback(GrouperSession grouperSession) throws GrouperSessionException {
726 
727             Set<AttributeAssign> attributeAssigns = GrouperDAOFactory.getFactory().getAttributeAssign().findByAttributeDefNameId(AttributeDefName.this.getId());
728             
729             //delete all assignments
730             for(AttributeAssign attributeAssign : attributeAssigns) {
731               attributeAssign.delete();
732             }
733             
734             return null;
735           }
736         });
737 
738         GrouperDAOFactory.getFactory().getAttributeDefName().delete(AttributeDefName.this);
739         
740         if (!hibernateHandlerBean.isCallerWillCreateAudit()) {
741           AuditEntryaudit/AuditEntry.html#AuditEntry">AuditEntry auditEntry = new AuditEntry(AuditTypeBuiltin.ATTRIBUTE_DEF_NAME_DELETE, "id", 
742               AttributeDefName.this.getId(), "name", AttributeDefName.this.getName(), 
743               "displayName", AttributeDefName.this.getDisplayName(),
744               "description", AttributeDefName.this.getDescription(),
745               "parentStemId", AttributeDefName.this.getStemId(), 
746               "parentAttributeDefId", attributeDef2.getId(),
747               "parentAttributeDefName", attributeDef2.getName());
748           
749           auditEntry.setDescription("Deleted attributeDefName: " + AttributeDefName.this.getName());
750           auditEntry.saveOrUpdate(true);
751         }
752 
753         
754         return null;
755       }
756     });
757     
758   }
759 
760   /**
761    * delegate logic about attribute def name sets to this object
762    */
763   @GrouperIgnoreClone @GrouperIgnoreDbVersion @GrouperIgnoreFieldConstant
764   private AttributeDefNameSetDelegate attributeDefNameSetDelegate;
765 
766   /** id of the group as a unique integer */
767   private Long idIndex;
768   
769   /**
770    * delegate logic about attribute def name sets to this object 
771    * @return the delegate
772    */
773   public AttributeDefNameSetDelegate getAttributeDefNameSetDelegate() {
774     if (this.attributeDefNameSetDelegate == null) {
775       this.attributeDefNameSetDelegate = new AttributeDefNameSetDelegate(this);
776     }
777     return this.attributeDefNameSetDelegate;
778   }
779   
780   /**
781    * @see java.lang.Object#toString()
782    */
783   @Override
784   public String toString() {
785     // Bypass privilege checks.  If the attributedef name is loaded it is viewable.
786     return new ToStringBuilder(this)
787       .append( "name", this.name)
788       .append( "uuid", this.getId() )
789       .toString();
790   }
791 
792   /**
793    * 
794    * @see java.lang.Object#equals(java.lang.Object)
795    */
796   @Override
797   public boolean equals(Object other) {
798     if (this == other) {
799       return true;
800     }
801     if (!(other instanceof AttributeDefName)) {
802       return false;
803     }
804     return StringUtils.equals(this.getName(), ( (AttributeDefName) other ).getName() );
805   } // public boolean equals(other)
806 
807   /**
808    * @return hashcode
809    * @since   1.2.0
810    */
811   @Override
812   public int hashCode() {
813     return new HashCodeBuilder()
814       .append( this.getName() )
815       .toHashCode();
816   } // public int hashCode()
817 
818   /**
819    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlCopyBusinessPropertiesToExisting(java.lang.Object)
820    */
821   public void xmlCopyBusinessPropertiesToExisting(AttributeDefName existingRecord) {
822     existingRecord.setAttributeDefId(this.getAttributeDefId());
823     existingRecord.setDescription(this.getDescription());
824     existingRecord.setDisplayExtensionDb(this.getDisplayExtensionDb());
825     existingRecord.setDisplayNameDb(this.getDisplayNameDb());
826     existingRecord.setExtensionDb(this.getExtensionDb());
827     existingRecord.setId(this.getId());
828     existingRecord.setNameDb(this.getNameDb());
829     existingRecord.setStemId(this.getStemId());
830   }
831 
832   /**
833    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlDifferentBusinessProperties(java.lang.Object)
834    */
835   public boolean xmlDifferentBusinessProperties(AttributeDefName other) {
836     if (!StringUtils.equals(this.attributeDefId, other.attributeDefId)) {
837       return true;
838     }
839     if (!StringUtils.equals(StringUtils.trimToNull(this.description), StringUtils.trimToNull(other.description))) {
840       return true;
841     }
842     if (!StringUtils.equals(this.displayExtension, other.displayExtension)) {
843       return true;
844     }
845     if (!StringUtils.equals(this.displayName, other.displayName)) {
846       return true;
847     }
848     if (!StringUtils.equals(this.extension, other.extension)) {
849       return true;
850     }
851     if (!StringUtils.equals(this.id, other.id)) {
852       return true;
853     }
854     if (!StringUtils.equals(this.name, other.name)) {
855       return true;
856     }
857     if (!StringUtils.equals(this.stemId, other.stemId)) {
858       return true;
859     }
860 
861     return false;
862   }
863 
864   /**
865    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlDifferentUpdateProperties(java.lang.Object)
866    */
867   public boolean xmlDifferentUpdateProperties(AttributeDefName other) {
868     if (!StringUtils.equals(this.contextId, other.contextId)) {
869       return true;
870     }
871     if (!GrouperUtil.equals(this.createdOnDb, other.createdOnDb)) {
872       return true;
873     }
874     if (!GrouperUtil.equals(this.getHibernateVersionNumber(), other.getHibernateVersionNumber())) {
875       return true;
876     }
877     if (!GrouperUtil.equals(this.lastUpdatedDb, other.lastUpdatedDb)) {
878       return true;
879     }
880     return false;
881   }
882 
883   /**
884    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlRetrieveByIdOrKey()
885    */
886   public AttributeDefName xmlRetrieveByIdOrKey() {
887     return GrouperDAOFactory.getFactory().getAttributeDefName().findByUuidOrName(this.id, this.name, false,
888         new QueryOptions().secondLevelCache(false));
889   }
890 
891   /**
892    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlSaveBusinessProperties(java.lang.Object)
893    */
894   public AttributeDefNamet2/middleware/grouper/attr/AttributeDefName.html#AttributeDefName">AttributeDefName xmlSaveBusinessProperties(AttributeDefName existingRecord) {
895     //if its an insert, call the business method
896     if (existingRecord == null) {
897       Stem parent = StemFinder.findByUuid(GrouperSession.staticGrouperSession(), this.stemId, true);
898       existingRecord = parent.internal_addChildAttributeDefName(GrouperSession.staticGrouperSession(), 
899           this.getAttributeDef(), this.extension, this.displayExtension, this.id, this.description);
900       if (this.idIndex != null) {
901         existingRecord.assignIdIndex(this.idIndex);
902       }
903     }
904     this.xmlCopyBusinessPropertiesToExisting(existingRecord);
905     //if its an insert or update, then do the rest of the fields
906     GrouperDAOFactory.getFactory().getAttributeDefName().saveOrUpdate(existingRecord);
907     return existingRecord;
908   }
909 
910   /**
911    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlSaveUpdateProperties()
912    */
913   public void xmlSaveUpdateProperties() {
914     GrouperDAOFactory.getFactory().getAttributeDefName().saveUpdateProperties(this);
915   }
916 
917   /**
918    * convert to xml bean for export
919    * @param grouperVersion
920    * @return xml bean
921    */
922   public XmlExportAttributeDefName xmlToExportAttributeDefName(GrouperVersion grouperVersion) {
923     if (grouperVersion == null) {
924       throw new RuntimeException();
925     }
926     XmlExportAttributeDefNamefName.html#XmlExportAttributeDefName">XmlExportAttributeDefName xmlExportAttributeDefName  = new XmlExportAttributeDefName();
927     
928     xmlExportAttributeDefName.setAttributeDefId(this.getAttributeDefId());
929     xmlExportAttributeDefName.setContextId(this.getContextId());
930     xmlExportAttributeDefName.setCreateTime(GrouperUtil.dateStringValue(this.getCreatedOnDb()));
931     xmlExportAttributeDefName.setDescription(this.getDescription());
932     xmlExportAttributeDefName.setDisplayExtension(this.getDisplayExtension());
933     xmlExportAttributeDefName.setDisplayName(this.getDisplayName());
934     xmlExportAttributeDefName.setExtension(this.getExtension());
935     xmlExportAttributeDefName.setHibernateVersionNumber(this.getHibernateVersionNumber());
936     xmlExportAttributeDefName.setIdIndex(this.getIdIndex());
937     xmlExportAttributeDefName.setModifierTime(GrouperUtil.dateStringValue(this.getLastUpdatedDb()));
938     xmlExportAttributeDefName.setName(this.getName());
939     xmlExportAttributeDefName.setParentStem(this.getStemId());
940     xmlExportAttributeDefName.setUuid(this.getId());
941 
942     return xmlExportAttributeDefName;
943   }
944 
945   /**
946    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlGetId()
947    */
948   public String xmlGetId() {
949     return this.getId();
950   }
951 
952   /**
953    * @see edu.internet2.middleware.grouper.xml.export.XmlImportable#xmlSetId(java.lang.String)
954    */
955   public void xmlSetId(String theId) {
956     this.setId(theId);
957   }
958   
959   /**
960    * @see edu.internet2.middleware.grouper.xml.export.XmlImportableBase#xmlToString()
961    */
962   public String xmlToString() {
963     StringWriter stringWriter = new StringWriter();
964     
965     stringWriter.write("AttributeDefName: " + this.getId() + ", " + this.getName());
966 
967 //    XmlExportUtils.toStringAttributeDefName(null, stringWriter, this, false);
968     
969     return stringWriter.toString();
970     
971   }
972 
973   /**
974    * store this group (update) to database
975    */
976   public void store() {
977     
978     validate();
979 
980     
981     HibernateSession.callbackHibernateSession(
982         GrouperTransactionType.READ_WRITE_OR_USE_EXISTING, AuditControl.WILL_AUDIT,
983         new HibernateHandler() {
984 
985           public Object callback(HibernateHandlerBean hibernateHandlerBean)
986               throws GrouperDAOException {
987 
988             hibernateHandlerBean.getHibernateSession().setCachingEnabled(false);
989 
990             //make sure subject is allowed to do this
991             Subject subject = GrouperSession.staticGrouperSession().getSubject();
992             AttributeDef attributeDef2 = AttributeDefName.this.getAttributeDef();
993             if (!attributeDef2.getPrivilegeDelegate().canAttrAdmin(subject)) {
994               throw new InsufficientPrivilegeException(GrouperUtil
995                   .subjectToString(subject)
996                   + " is not attrAdmin on attributeDef: " + attributeDef2.getName());
997             }
998             
999             String differences = GrouperUtil.dbVersionDescribeDifferences(AttributeDefName.this.dbVersion(), 
1000                 AttributeDefName.this, AttributeDefName.this.dbVersion() != null ? AttributeDefName.this.dbVersionDifferentFields() : AttributeDefName.CLONE_FIELDS);
1001 
1002             GrouperDAOFactory.getFactory().getAttributeDefName().saveOrUpdate(AttributeDefName.this);
1003             
1004             if (!hibernateHandlerBean.isCallerWillCreateAudit()) {
1005               AuditEntryaudit/AuditEntry.html#AuditEntry">AuditEntry auditEntry = new AuditEntry(AuditTypeBuiltin.ATTRIBUTE_DEF_NAME_UPDATE, "id", 
1006                   AttributeDefName.this.getId(), "name", AttributeDefName.this.getName(), 
1007                   "displayName", AttributeDefName.this.getDisplayName(),
1008                   "description", AttributeDefName.this.getDescription(),
1009                   "parentStemId", AttributeDefName.this.getStemId(), 
1010                   "parentAttributeDefId", attributeDef2.getId(),
1011                   "parentAttributeDefName", attributeDef2.getName());
1012               
1013               auditEntry.setDescription("Updated attributeDefName: " + AttributeDefName.this.getName() + ", " + differences);
1014               auditEntry.saveOrUpdate(true);
1015             }
1016             return null;
1017           }
1018         });
1019   }
1020 
1021 
1022 
1023   /**
1024    * 
1025    */
1026   public void validate() {
1027     //lets validate
1028     //    GrouperDdlUtils.ddlutilsFindOrCreateColumn(attributeDefNameTable,
1029     //        AttributeDefName.COLUMN_NAME, Types.VARCHAR, ddlVersionBean.isSqlServer() ? "900" : "1024", false, true);
1030     boolean sqlServer = GrouperDdlUtils.isSQLServer();
1031     int maxNameLength = sqlServer ? 900 : 1024;
1032     maxNameLength = GrouperConfig.retrieveConfig().propertyValueInt("grouper.nameOfAttributeDefName.maxSize", maxNameLength);
1033 
1034     //    GrouperDdlUtils.ddlutilsFindOrCreateColumn(attributeDefNameTable,
1035     //        AttributeDefName.COLUMN_EXTENSION, Types.VARCHAR, "255", false, true);
1036     if (GrouperUtil.lengthAscii(this.getExtension()) > 255) {
1037       throw new GrouperValidationException("Extension of attributeDefName too long: " + GrouperUtil.lengthAscii(this.getExtension()), 
1038           VALIDATION_EXTENSION_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY, 255, GrouperUtil.lengthAscii(this.getExtension()));
1039     }
1040 
1041     //    GrouperDdlUtils.ddlutilsFindOrCreateColumn(attributeDefNameTable,
1042     //        AttributeDefName.COLUMN_DISPLAY_EXTENSION, Types.VARCHAR, "128", false, true);
1043     if (GrouperUtil.lengthAscii(this.getDisplayExtension()) > 128) {
1044       throw new GrouperValidationException("Display extension of attributeDefName too long: " + GrouperUtil.lengthAscii(this.getDisplayExtension()), 
1045           VALIDATION_DISPLAY_EXTENSION_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY, 128, GrouperUtil.lengthAscii(this.getDisplayExtension()));
1046     }
1047     
1048     if (GrouperUtil.lengthAscii(this.getName()) > maxNameLength) {
1049       throw new GrouperValidationException("Name of attributeDefName too long: " + GrouperUtil.lengthAscii(this.getName()), 
1050           VALIDATION_NAME_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY, maxNameLength, GrouperUtil.lengthAscii(this.getName()));
1051     }
1052 
1053     //    GrouperDdlUtils.ddlutilsFindOrCreateColumn(attributeDefNameTable,
1054     //        AttributeDefName.COLUMN_DISPLAY_NAME, Types.VARCHAR, ddlVersionBean.isSqlServer() ? "900" : "1024", false, true);
1055     if (GrouperUtil.lengthAscii(this.getDisplayName()) > maxNameLength) {
1056       throw new GrouperValidationException("Display name of attributeDefName too long: " + GrouperUtil.lengthAscii(this.getDisplayName()), 
1057           VALIDATION_DISPLAY_NAME_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY, maxNameLength, GrouperUtil.lengthAscii(this.getDisplayName()));
1058     }
1059 
1060     //    GrouperDdlUtils.ddlutilsFindOrCreateColumn(attributeDefNameTable,
1061     //        AttributeDefName.COLUMN_DESCRIPTION, Types.VARCHAR, "1024", false, false);
1062     if (GrouperUtil.lengthAscii(this.getDescription()) > 1024) {
1063       throw new GrouperValidationException("Description of attributeDefName too long: " + GrouperUtil.lengthAscii(this.getDescription()), 
1064           VALIDATION_DECRIPTION_OF_ATTRIBUTE_DEF_NAME_TOO_LONG_KEY, 1024, GrouperUtil.lengthAscii(this.getDescription()));
1065     }
1066   }
1067 
1068   /**
1069    * @see edu.internet2.middleware.grouper.GrouperAPI#onPostDelete(edu.internet2.middleware.grouper.hibernate.HibernateSession)
1070    */
1071   @Override
1072   public void onPostDelete(HibernateSession hibernateSession) {
1073     super.onPostDelete(hibernateSession);
1074   
1075     GrouperHooksUtils.schedulePostCommitHooksIfRegistered(GrouperHookType.ATTRIBUTE_DEF_NAME, 
1076         AttributeDefNameHooks.METHOD_ATTRIBUTE_DEF_NAME_POST_COMMIT_DELETE, HooksAttributeDefNameBean.class, 
1077         this, AttributeDefName.class);
1078   
1079     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF_NAME, 
1080         AttributeDefNameHooks.METHOD_ATTRIBUTE_DEF_NAME_POST_DELETE, HooksAttributeDefNameBean.class, 
1081         this, AttributeDefName.class, VetoTypeGrouper.ATTRIBUTE_DEF_NAME_POST_DELETE, false, true);
1082   
1083     GroupType groupType = GroupType.internal_getGroupType(this, false);
1084     if (groupType != null) {
1085       // this is a legacy group type
1086       
1087       GrouperHooksUtils.schedulePostCommitHooksIfRegistered(GrouperHookType.GROUP_TYPE,
1088           GroupTypeHooks.METHOD_GROUP_TYPE_POST_COMMIT_DELETE, HooksGroupTypeBean.class,
1089           groupType, GroupType.class);
1090 
1091       GrouperHooksUtils.callHooksIfRegistered(groupType, GrouperHookType.GROUP_TYPE,
1092           GroupTypeHooks.METHOD_GROUP_TYPE_POST_DELETE, HooksGroupTypeBean.class,
1093           groupType, GroupType.class, VetoTypeGrouper.GROUP_TYPE_POST_DELETE, false, true);
1094     }
1095   }
1096 
1097   /**
1098    * @see edu.internet2.middleware.grouper.hibernate.HibGrouperLifecycle#onPostSave(edu.internet2.middleware.grouper.hibernate.HibernateSession)
1099    */
1100   @Override
1101   public void onPostSave(HibernateSession hibernateSession) {
1102   
1103     super.onPostSave(hibernateSession);
1104     
1105     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF_NAME, 
1106         AttributeDefNameHooks.METHOD_ATTRIBUTE_DEF_NAME_POST_INSERT, HooksAttributeDefNameBean.class, 
1107         this, AttributeDefName.class, VetoTypeGrouper.ATTRIBUTE_DEF_NAME_POST_INSERT, true, false);
1108   
1109     //do these second so the right object version is set, and dbVersion is ok
1110     GrouperHooksUtils.schedulePostCommitHooksIfRegistered(GrouperHookType.ATTRIBUTE_DEF_NAME, 
1111         AttributeDefNameHooks.METHOD_ATTRIBUTE_DEF_NAME_POST_COMMIT_INSERT, HooksAttributeDefNameBean.class, 
1112         this, AttributeDefName.class);
1113   
1114     GroupType groupType = GroupType.internal_getGroupType(this, false);
1115     if (groupType != null) {
1116       // this is a legacy group type
1117 
1118       GrouperHooksUtils.callHooksIfRegistered(groupType, GrouperHookType.GROUP_TYPE,
1119           GroupTypeHooks.METHOD_GROUP_TYPE_POST_INSERT, HooksGroupTypeBean.class,
1120           groupType, GroupType.class, VetoTypeGrouper.GROUP_TYPE_POST_INSERT, true, false);
1121 
1122       GrouperHooksUtils.schedulePostCommitHooksIfRegistered(GrouperHookType.GROUP_TYPE,
1123           GroupTypeHooks.METHOD_GROUP_TYPE_POST_COMMIT_INSERT, HooksGroupTypeBean.class,
1124           groupType, GroupType.class);
1125     }
1126   }
1127 
1128   /**
1129    * @see edu.internet2.middleware.grouper.hibernate.HibGrouperLifecycle#onPostUpdate(HibernateSession)
1130    */
1131   public void onPostUpdate(HibernateSession hibernateSession) {
1132     
1133     super.onPostUpdate(hibernateSession);
1134     
1135     GrouperHooksUtils.schedulePostCommitHooksIfRegistered(GrouperHookType.ATTRIBUTE_DEF_NAME, 
1136         AttributeDefNameHooks.METHOD_ATTRIBUTE_DEF_NAME_POST_COMMIT_UPDATE, HooksAttributeDefNameBean.class, 
1137         this, AttributeDefName.class);
1138   
1139     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF_NAME, 
1140         AttributeDefNameHooks.METHOD_ATTRIBUTE_DEF_NAME_POST_UPDATE, HooksAttributeDefNameBean.class, 
1141         this, AttributeDefName.class, VetoTypeGrouper.ATTRIBUTE_DEF_NAME_POST_UPDATE, true, false);
1142   
1143   
1144     GroupType groupType = GroupType.internal_getGroupType(this, false);
1145     if (groupType != null) {
1146       // this is a legacy group type
1147       
1148       GrouperHooksUtils.schedulePostCommitHooksIfRegistered(GrouperHookType.GROUP_TYPE,
1149           GroupTypeHooks.METHOD_GROUP_TYPE_POST_COMMIT_UPDATE, HooksGroupTypeBean.class,
1150           groupType, GroupType.class);
1151 
1152       GrouperHooksUtils.callHooksIfRegistered(groupType, GrouperHookType.GROUP_TYPE,
1153           GroupTypeHooks.METHOD_GROUP_TYPE_POST_UPDATE, HooksGroupTypeBean.class,
1154           groupType, GroupType.class, VetoTypeGrouper.GROUP_TYPE_POST_UPDATE, true, false);
1155     }
1156   }
1157 
1158   /**
1159    * @see edu.internet2.middleware.grouper.GrouperAPI#onPreDelete(edu.internet2.middleware.grouper.hibernate.HibernateSession)
1160    */
1161   @Override
1162   public void onPreDelete(HibernateSession hibernateSession) {
1163     super.onPreDelete(hibernateSession);
1164   
1165     GroupType groupType = GroupType.internal_getGroupType(this, false);
1166     if (groupType != null) {
1167       // this is a legacy group type
1168       
1169       GrouperHooksUtils.callHooksIfRegistered(groupType, GrouperHookType.GROUP_TYPE,
1170           GroupTypeHooks.METHOD_GROUP_TYPE_PRE_DELETE, HooksGroupTypeBean.class,
1171           groupType, GroupType.class, VetoTypeGrouper.GROUP_TYPE_PRE_DELETE, false, false);
1172     }
1173     
1174     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF_NAME, 
1175         AttributeDefNameHooks.METHOD_ATTRIBUTE_DEF_NAME_PRE_DELETE, HooksAttributeDefNameBean.class, 
1176         this, AttributeDefName.class, VetoTypeGrouper.ATTRIBUTE_DEF_NAME_PRE_DELETE, false, false);
1177     
1178     //change log into temp table
1179     new ChangeLogEntry(true, ChangeLogTypeBuiltin.ATTRIBUTE_DEF_NAME_DELETE, 
1180         ChangeLogLabels.ATTRIBUTE_DEF_NAME_DELETE.id.name(), this.getId(), 
1181         ChangeLogLabels.ATTRIBUTE_DEF_NAME_DELETE.name.name(), this.getName(), 
1182         ChangeLogLabels.ATTRIBUTE_DEF_NAME_DELETE.stemId.name(), this.getStemId(), 
1183         ChangeLogLabels.ATTRIBUTE_DEF_NAME_DELETE.description.name(), this.getDescription(), 
1184         ChangeLogLabels.ATTRIBUTE_DEF_NAME_DELETE.attributeDefId.name(), this.getAttributeDefId()).save();
1185     
1186     Hib3AttributeDefNameDAO.attributeDefNameCacheRemove(this);
1187 
1188   }
1189 
1190   /**
1191    * 
1192    * @see edu.internet2.middleware.grouper.GrouperAPI#onPreSave(edu.internet2.middleware.grouper.hibernate.HibernateSession)
1193    */
1194   @Override
1195   public void onPreSave(HibernateSession hibernateSession) {
1196     super.onPreSave(hibernateSession);
1197     
1198     this.lastUpdatedDb = System.currentTimeMillis();
1199     if (this.createdOnDb == null) {
1200       this.createdOnDb = System.currentTimeMillis();
1201     }
1202 
1203     if (this.idIndex == null) {
1204       this.idIndex = TableIndex.reserveId(TableIndexType.attributeDefName);
1205     }
1206 
1207     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF_NAME, 
1208         AttributeDefNameHooks.METHOD_ATTRIBUTE_DEF_NAME_PRE_INSERT, HooksAttributeDefNameBean.class, 
1209         this, AttributeDefName.class, VetoTypeGrouper.ATTRIBUTE_DEF_NAME_PRE_INSERT, false, false);
1210     
1211     GroupType groupType = GroupType.internal_getGroupType(this, false);
1212     if (groupType != null) {
1213       // this is a legacy group type
1214     
1215       GrouperHooksUtils.callHooksIfRegistered(groupType, GrouperHookType.GROUP_TYPE,
1216           GroupTypeHooks.METHOD_GROUP_TYPE_PRE_INSERT, HooksGroupTypeBean.class,
1217           groupType, GroupType.class, VetoTypeGrouper.GROUP_TYPE_PRE_INSERT, false, false);
1218     }
1219     
1220     //change log into temp table
1221     new ChangeLogEntry(true, ChangeLogTypeBuiltin.ATTRIBUTE_DEF_NAME_ADD, 
1222         ChangeLogLabels.ATTRIBUTE_DEF_NAME_ADD.id.name(), this.getId(), 
1223         ChangeLogLabels.ATTRIBUTE_DEF_NAME_ADD.name.name(), this.getName(), 
1224         ChangeLogLabels.ATTRIBUTE_DEF_NAME_ADD.stemId.name(), this.getStemId(), 
1225         ChangeLogLabels.ATTRIBUTE_DEF_NAME_ADD.description.name(), this.getDescription(), 
1226         ChangeLogLabels.ATTRIBUTE_DEF_NAME_ADD.attributeDefId.name(), this.getAttributeDefId()).save();
1227     
1228   }
1229 
1230   /**
1231    * @see edu.internet2.middleware.grouper.GrouperAPI#onPreUpdate(edu.internet2.middleware.grouper.hibernate.HibernateSession)
1232    */
1233   @Override
1234   public void onPreUpdate(HibernateSession hibernateSession) {
1235     super.onPreUpdate(hibernateSession);
1236     this.lastUpdatedDb = System.currentTimeMillis();
1237     
1238     if (this.dbVersionDifferentFields().contains(FIELD_ATTRIBUTE_DEF_ID)) {
1239       throw new RuntimeException("cannot update attributeDefId");
1240     }
1241     
1242     if (this.dbVersionDifferentFields().contains(FIELD_STEM_ID)) {
1243       throw new RuntimeException("cannot update stemId");
1244     }
1245     
1246     if (this.dbVersionDifferentFields().contains(FIELD_NAME) || this.dbVersionDifferentFields().contains(FIELD_EXTENSION)) {
1247       // don't allow renames for legacy attributes
1248       String stemName = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.baseStem");
1249       String groupTypePrefix = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.groupType.prefix");
1250       String attributePrefix = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.attribute.prefix");
1251       String customListPrefix = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.customList.prefix");
1252       
1253       String oldName = this.dbVersion().getNameDb();
1254       if (oldName.startsWith(stemName + ":" + groupTypePrefix) ||
1255           oldName.startsWith(stemName + ":" + attributePrefix) ||
1256           oldName.startsWith(stemName + ":" + customListPrefix)) {
1257         throw new RuntimeException("cannot update name for legacy attributes");
1258       }
1259     }
1260     
1261     GrouperHooksUtils.callHooksIfRegistered(this, GrouperHookType.ATTRIBUTE_DEF_NAME, 
1262         AttributeDefNameHooks.METHOD_ATTRIBUTE_DEF_NAME_PRE_UPDATE, HooksAttributeDefNameBean.class, 
1263         this, AttributeDefName.class, VetoTypeGrouper.ATTRIBUTE_DEF_NAME_PRE_UPDATE, false, false);
1264   
1265     
1266     GroupType groupType = GroupType.internal_getGroupType(this, false);
1267     if (groupType != null) {
1268       // this is a legacy group type
1269       
1270       GrouperHooksUtils.callHooksIfRegistered(groupType, GrouperHookType.GROUP_TYPE,
1271           GroupTypeHooks.METHOD_GROUP_TYPE_PRE_UPDATE, HooksGroupTypeBean.class,
1272           groupType, GroupType.class, VetoTypeGrouper.GROUP_TYPE_PRE_UPDATE, false, false);
1273     }
1274     
1275     //change log into temp table
1276     ChangeLogEntry.saveTempUpdates(ChangeLogTypeBuiltin.ATTRIBUTE_DEF_NAME_UPDATE, 
1277         this, this.dbVersion(),
1278         GrouperUtil.toList(
1279             ChangeLogLabels.ATTRIBUTE_DEF_NAME_UPDATE.id.name(), this.getId(), 
1280             ChangeLogLabels.ATTRIBUTE_DEF_NAME_UPDATE.name.name(), this.getName(), 
1281             ChangeLogLabels.ATTRIBUTE_DEF_NAME_UPDATE.stemId.name(), this.getStemId(), 
1282             ChangeLogLabels.ATTRIBUTE_DEF_NAME_UPDATE.description.name(), this.getDescription(), 
1283             ChangeLogLabels.ATTRIBUTE_DEF_NAME_UPDATE.attributeDefId.name(), this.getAttributeDefId()),
1284         GrouperUtil.toList("name", "description"),
1285         GrouperUtil.toList(
1286             ChangeLogLabels.ATTRIBUTE_DEF_NAME_UPDATE.name.name(),
1287             ChangeLogLabels.ATTRIBUTE_DEF_NAME_UPDATE.description.name())); 
1288     
1289     Hib3AttributeDefNameDAO.attributeDefNameCacheRemove(this);
1290 
1291   }
1292 
1293   /**
1294    * save the state when retrieving from DB
1295    * @return the dbVersion
1296    */
1297   @Override
1298   public AttributeDefName dbVersion() {
1299     return (AttributeDefName)this.dbVersion;
1300   }
1301   
1302   /**
1303    * take a snapshot of the data since this is what is in the db
1304    */
1305   @Override
1306   public void dbVersionReset() {
1307     //lets get the state from the db so we know what has changed
1308     this.dbVersion = GrouperUtil.clone(this, DB_VERSION_FIELDS);
1309   }
1310 
1311 
1312   /**
1313    * @see edu.internet2.middleware.grouper.GrouperAPI#dbVersionDifferentFields()
1314    */
1315   @Override
1316   public Set<String> dbVersionDifferentFields() {
1317     if (this.dbVersion == null) {
1318       throw new RuntimeException("State was never stored from db");
1319     }
1320     //easier to unit test if everything is ordered
1321     Set<String> result = GrouperUtil.compareObjectFields(this, this.dbVersion,
1322         DB_VERSION_FIELDS, null);
1323     return result;
1324   }
1325 
1326   /**
1327    * @see Comparable#compareTo(Object)
1328    */
1329   public int compareTo(GrouperObject that) {
1330     if (that==null) {
1331       return 1;
1332     }
1333     String thisName = StringUtils.defaultString(this.getName());
1334     String thatName = StringUtils.defaultString(that.getName());
1335     return thisName.compareTo(thatName);
1336   }
1337 
1338 
1339 
1340   /**
1341    * id of the group as a unique integer
1342    * @return id
1343    */
1344   public Long getIdIndex() {
1345     return this.idIndex;
1346   }
1347 
1348 
1349 
1350   /**
1351    * id of the group as a unique integer
1352    * @param idIndex1
1353    */
1354   public void setIdIndex(Long idIndex1) {
1355     this.idIndex = idIndex1;
1356   }
1357   
1358   /**
1359    * assign different id index
1360    * @param theIdIndex
1361    * @return if it was changed
1362    */
1363   public boolean assignIdIndex(final long theIdIndex) {
1364 
1365     TableIndex.assertCanAssignIdIndex();
1366 
1367     boolean needsSave = false;
1368     synchronized (TableIndexType.attributeDefName) {
1369 
1370       //ok, if the index is not in use (not, it could be reserved... hmmm)
1371       AttributeDefName tempAttributeDefName = GrouperDAOFactory.getFactory().getAttributeDefName().findByIdIndex(theIdIndex, false, null);
1372       if (tempAttributeDefName == null) {
1373         
1374         this.setIdIndex(theIdIndex);
1375         TableIndex.clearReservedId(TableIndexType.attributeDefName, theIdIndex);
1376         needsSave = true;
1377         
1378         //do a new session so we don hold on too long
1379         HibernateSession.callbackHibernateSession(GrouperTransactionType.READ_WRITE_NEW, AuditControl.WILL_NOT_AUDIT, new HibernateHandler() {
1380           
1381           @Override
1382           public Object callback(HibernateHandlerBean hibernateHandlerBean)
1383               throws GrouperDAOException {
1384             //now we might need to increment the index
1385             TableIndex tableIndex = GrouperDAOFactory.getFactory().getTableIndex().findByType(TableIndexType.attributeDefName);
1386             if (tableIndex != null && tableIndex.getLastIndexReserved() < theIdIndex) {
1387               tableIndex.setLastIndexReserved(theIdIndex);
1388               tableIndex.saveOrUpdate();
1389             }
1390             return null;
1391           }
1392         });
1393       }      
1394     }
1395     return needsSave;
1396   }
1397 
1398   /**
1399    * set this for caching
1400    * @param attributeDef1
1401    */
1402   public void internalSetAttributeDef(AttributeDef attributeDef1) {
1403     
1404     if (attributeDef1 != null) {
1405       if (!StringUtils.equals(this.attributeDefId, attributeDef1.getId())) {
1406         throw new RuntimeException("Why does the attributeDef id " 
1407             + this.attributeDefId + " not equal the param id: " + attributeDef1.getId());
1408       }
1409     }
1410     
1411     this.attributeDef = attributeDef1;
1412   }
1413   
1414   /**
1415    * @param exceptionIfNotLegacyAttribute
1416    * @return legacy attribute name
1417    */
1418   public String getLegacyAttributeName(boolean exceptionIfNotLegacyAttribute) {
1419     String stemName = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.baseStem");
1420     String attributePrefix = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.attribute.prefix");
1421     
1422     String prefix = stemName + ":" + attributePrefix;
1423     if (this.name.startsWith(prefix)) {
1424       return this.name.substring(prefix.length());
1425     } 
1426 
1427     if (exceptionIfNotLegacyAttribute) {
1428       throw new RuntimeException("Not legacy attribute");
1429     }
1430       
1431     return null;
1432   }
1433   
1434   /**
1435    * @param exceptionIfNotLegacyGroupType
1436    * @return legacy attribute name
1437    */
1438   public String getLegacyGroupTypeName(boolean exceptionIfNotLegacyGroupType) {
1439     String stemName = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.baseStem");
1440     String groupTypePrefix = GrouperConfig.retrieveConfig().propertyValueStringRequired("legacyAttribute.groupType.prefix");
1441     
1442     String prefix = stemName + ":" + groupTypePrefix;
1443     if (this.name.startsWith(prefix)) {
1444       return this.name.substring(prefix.length());
1445     } 
1446 
1447     if (exceptionIfNotLegacyGroupType) {
1448       throw new RuntimeException("Not legacy group type");
1449     }
1450       
1451     return null;
1452   }
1453   
1454   /**
1455    * @see GrouperObject#matchesLowerSearchStrings(Set)
1456    */
1457   @Override
1458   public boolean matchesLowerSearchStrings(Set<String> filterStrings) {
1459 
1460     if (GrouperUtil.length(filterStrings) == 0) {
1461       return true;
1462     }
1463 
1464     String lowerId = this.getId().toLowerCase();
1465     String lowerName = StringUtils.defaultString(this.getName()).toLowerCase();
1466     String lowerDisplayName = StringUtils.defaultString(this.getDisplayName()).toLowerCase();
1467     String lowerDescription = StringUtils.defaultString(this.getDescription()).toLowerCase();
1468     
1469     for (String filterString : GrouperUtil.nonNull(filterStrings)) {
1470       
1471       //if all dont match, return false
1472       if (!lowerId.contains(filterString)
1473           && !lowerName.contains(filterString)
1474           && !lowerDisplayName.contains(filterString)
1475           && !lowerDescription.contains(filterString)) {
1476         return false;
1477       }
1478       
1479     }
1480     return true;
1481   }
1482 
1483 
1484 
1485   /**
1486    * @see edu.internet2.middleware.grouper.misc.GrouperObject#getParentStem()
1487    */
1488   public Stem getParentStem() {
1489     return this.getStem();
1490   }
1491 
1492 }