/// <summary> /// Check objectClass. /// </summary> /// <param name="obj">ModelObject.</param> public static void CheckObjectClass(ModelObject obj) { string dn = (string)obj[StandardNames.shortName]; Value objectClass = obj[StandardNames.objectClass]; if (objectClass == null) { Checks.Fail("'{0}' must have object class", dn); return; } // Check for resolution and last/first element compliance int count = 0; List <string> classes = obj.GetAllClassIds().ToList(); bool resolveOk = true; foreach (string classId in classes) { ModelObject classObject; //The object must be present in Schema NC. if (!obj.dc.TryGetClass(classId, out classObject)) { Checks.Fail("'{0}' has undefined object class '{1}'", dn, classId); resolveOk = false; continue; } //Checking for the first class is Top if (count == 0 && classId != StandardNames.top) { Checks.Fail("'{0}' first object class must be top", dn); resolveOk = false; } //Checking for the last class is Structural class. if (count == objectClass.UnderlyingValues.Count - 1) { ObjectClassCategory category = (ObjectClassCategory)(int)classObject[StandardNames.objectClassCategory]; if (category != ObjectClassCategory.StructuralClass) { Checks.Fail("'{0}' last object class must be structural"); resolveOk = false; } } count++; } if (!resolveOk) { return; } // Check for superclass chaining // Checks that if the value of object class is [top,ac_1,...,ac_n,sc_1,...,sc_n], // then sc_n is the most specific structural class, sc_1...scn_(n-1) is the super class chain of sc_n (excluding top), // and ac_n is the next auxilary class before that, where ac_1...acn(n-1) is that classes chain excluding classes // which have been seen already before (where there can be a number of ac anchors here). List <string> includedClasses = new List <string>(); int i = classes.Count - 1; while (i > 0) { string classId = classes[i--]; if (includedClasses.Contains(classId)) { Checks.Fail("'{0}' object class contains repeated entries", dn); break; } includedClasses.Add(classId); ObjectClassCategory category = (ObjectClassCategory)(int)obj.dc.GetClass(classId)[StandardNames.objectClassCategory]; if (i == classes.Count - 2) { // Most specific class must be structural if (category != ObjectClassCategory.StructuralClass) { Checks.Fail("'{0}' object class most specific class must be structural", dn); } } //If the server is Pre Windows 2003. foreach (string clId in GetSuperClassChain(obj.dc, classId)) { if (includedClasses.Contains(clId)) { // Already included in a previous chain continue; } includedClasses.Add(clId); if (i <= 0) { Checks.Fail( "'{0}' object class does not contain chain of super classes of '{1}' (classes missing)", dn, classId); break; } if (classes[i--] != clId) { Checks.Fail( "'{0}' object class does not contain chain of super classes '{1}' (found unexpected '{2}')", dn, classId, classes[i + 1]); break; } } } }
public void ValidateObjectClassRequirements(DirectoryEntries childrens, bool isADDS) { bool isObjectClassMultiValued = false; bool isObjectClassAppeared = false; bool isObjectClassTop = false; bool isObjectClassStructural = false; foreach (DirectoryEntry child in childrens) { //Get objectClass value. PropertyValueCollection propValColln = child.Properties[StandardNames.objectClass]; //If it is not existing Requirement 130 will fail. if (propValColln != null) { isObjectClassAppeared = true; } //It is multivalued. so it should be more than one value. if (propValColln.Count >= 1) { isObjectClassMultiValued = true; } //Get objectClassValue in array. string[] objectClassElements = new string[propValColln.Count]; int loopVariable = 0; foreach (string propVal in (IEnumerable <object>)propValColln.Value) { objectClassElements[loopVariable++] = propVal; } //The first element is always top. if (objectClassElements[0].ToLower().Equals("top")) { isObjectClassTop = true; } //Get last element. string structuralClassName = (string)child.Properties["objectCategory"].Value; DirectoryEntry lastClassObject; if (isADDS) { if (!adAdapter.GetObjectByDN(structuralClassName, out lastClassObject)) { DataSchemaSite.Assume.IsTrue(false, structuralClassName + " Object is not found in server"); } } else { if (!adAdapter.GetLdsObjectByDN(structuralClassName, out lastClassObject)) { DataSchemaSite.Assume.IsTrue(false, structuralClassName + " Object is not found in server"); } } ObjectClassCategory lastClassCategory = (ObjectClassCategory)(int)lastClassObject. Properties[StandardNames.objectClassCategory.ToLower()][0]; //The last element should be structural class. if (lastClassCategory == ObjectClassCategory.StructuralClass) { isObjectClassStructural = true; } if (isObjectClassAppeared && isObjectClassMultiValued && isObjectClassStructural && isObjectClassTop) { continue; } else { break; } } //MS-ADTS-Schema_R143. DataSchemaSite.CaptureRequirementIfIsTrue( isObjectClassMultiValued && isObjectClassAppeared, 143, "Attribute objectClass is a multivalued attribute that appears on all the objects in the directory."); //MS-ADTS-Schema_R144. DataSchemaSite.CaptureRequirementIfIsTrue( isObjectClassMultiValued && isObjectClassAppeared, 144, @"When instantiating a structural class, the objectClass attribute of the new object contains a sequence of class names"); //MS-ADTS-Schema_R145. DataSchemaSite.CaptureRequirementIfIsTrue( isObjectClassTop, 145, "In the ObjectClass first element is always class top."); //MS-ADTS-Schema_R146. DataSchemaSite.CaptureRequirementIfIsTrue( isObjectClassStructural, 146, "In the ObjectClass last element is the name of the structural class that was instantiated."); }
/// <summary> /// Inheritance is the ability to build new classes from existing classes. /// </summary> /// <param name="obj">The object of model.</param> public static void CheckInheritance(ModelObject obj) { string dn = (string)obj[StandardNames.shortName]; //Get super class id. string superClassId = (string)obj[StandardNames.subClassOf]; if (superClassId == null) { Checks.Fail("'{0}' must have a super class", dn); } else { ModelObject superClass; if (!obj.dc.TryGetClass(superClassId, out superClass)) { Checks.Fail("'{0}' has undefined super class '{1}'", dn, superClassId); } else { string thisClassId = (string)obj[StandardNames.governsId]; if (thisClassId != StandardNames.topGovernsId && thisClassId == superClassId) { Checks.Fail("{0} cannot inherit from itself", dn); } //Get super class and current class category. ObjectClassCategory thisCategory = (ObjectClassCategory)(int)obj[StandardNames.objectClassCategory]; ObjectClassCategory superCategory = (ObjectClassCategory)(int)superClass[StandardNames.objectClassCategory]; bool categoryOk; switch (thisCategory) { //Abstract Class must be inherited from Abstract Class. case ObjectClassCategory.AbstractClass: categoryOk = superCategory == ObjectClassCategory.AbstractClass; break; //Auxiliary Class must not be inherited from Structural Class case ObjectClassCategory.AuxiliaryClass: categoryOk = superCategory != ObjectClassCategory.StructuralClass; break; //Structural Class must not be inherited from Auxiliary Class case ObjectClassCategory.StructuralClass: categoryOk = superCategory != ObjectClassCategory.AuxiliaryClass; break; //Default. default: categoryOk = true; break; } if (!categoryOk) { Checks.Fail("{0} must have object class category which is compatible with its super class", dn); } } } }