📄 dxattributes.java
字号:
/**
* <p>Returns the set of attributes that are in the newSet, but
* not in the old set, excluding the rdnclass).</p>
*
* <p>It also returns partial attributes that contain values that
* are in the newSet but not in the oldSet, when either a)
* either attribute has a size larger than one, or b) the attribute has
* a distinguished value.</p>
*
* <p>The logic for case a) is that we can use adds and deletes on
* individual attributes to simulate a 'replace' operation, but we
* need to avoid doing this for single valued attributes (for which
* we *always* use replace). So if Attribute A has values {1,2,3},
* and is changed to A' {1,3,5,6}, this method returns an 'add' {5,6}.</p>
*
* <p>The logic for case b) is that we cannot use 'replace' on an
* attribute with a naming value in it, so we *must* use adds and
* deletes - and we'll have to take our chances that it is not
* single valued. (Possibly later on we can check this from schema).
* This method cannot change the distinguished value, but produces an
* 'add' for any other changed. So if, for entry cn=fred, Attribute cn
* has values {fred,erik}
* and cn' has values {fred, nigel], this method produces an 'add' {nigel}.</p>
*
*
* @param newRDN the new RDN of the entry that is being created
* (usually this is the same as the RDN of the original entry)
* May be null if it is not to be checked.
* @param oldSet the set of already existing attributes
* @param newSet the set of new attributes to test
* @return attributes that must be added to the object.
*/
public static DXAttributes getAdditionSet(RDN newRDN, Attributes oldSet, Attributes newSet)
throws NamingException
{
DXAttributes additionSet = new DXAttributes();
NamingEnumeration listOfNewAttributes = newSet.getAll();
while (listOfNewAttributes.hasMore())
{
Attribute newAtt = (Attribute)listOfNewAttributes.next();
String attributeName = newAtt.getID();
boolean isNamingAttribute = newRDN.contains(attributeName);
Attribute oldAtt = oldSet.get(attributeName);
if (! emptyAtt(newAtt)) // don't add empty atts!
{
/*
* Check for simple "whole attribute" adds
* if the old Att is null, or only had null values add it.
* (It was probably created by the browser,
* and doesn't exist in the database)
*/
if ((isNamingAttribute == false) && (oldAtt == null || emptyAtt(oldAtt)))
{
additionSet.put(newAtt);
}
/*
* Check for attribute values that have been changed in attributes
* that are larger than 1, or that are naming attributes
*/
// TODO: - clean this up for DSML etc. ...
else if (isNamingAttribute || (oldAtt.size() > 1 || newAtt.size() > 1 ))
{
DXNamingEnumeration valuesToAdd = getMissingValues(oldAtt.getAll(), newAtt.getAll());
// check for distinguished value, and ignore it...
if (isNamingAttribute)
removeAnyDistinguishedValues(newRDN, attributeName, valuesToAdd);
if (valuesToAdd.size()>0)
additionSet.put(new DXAttribute(attributeName, valuesToAdd));
}
}
}
return additionSet;
}
/**
* <p>Returns all single valued attributes whose values have changed -
* that is, exist in both the new set and the old set, but have different values.
* Note that this function ignores the naming attribute.</p>
*
* <p>We need this function to cope with mandatory single valued attributes
* (otherwise we could just use add and delete).</p>
*
* <p>All other attribute combinations are handled by attribute value adds and
* deletes. (This is slightly more efficient, and is required to modify
* non-distinguished values of the naming attribute anyway).</p>
*
* @param newRDN the RDN of the newer entry.
* (usually this is the same as the RDN of the original entry)
* May be null if it is not to be checked.
* @param oldSet the set of already existing attributes
* @param newSet the set of new attributes to test
* @return attributes that require updating
*/
// LOGIC NOTE - only replace attributes that are single valued (old & new) and NOT naming values.
public static DXAttributes getReplacementSet(RDN newRDN, Attributes oldSet, Attributes newSet)
throws NamingException
{
DXAttributes replacementSet = new DXAttributes();
NamingEnumeration listOfNewAttributes = newSet.getAll();
while (listOfNewAttributes.hasMore()) // find changed attributes
{
Attribute newAtt = (Attribute)listOfNewAttributes.next();
if (newAtt != null && newAtt.size() == 1) // only consider a single valued new attribute
{
String attributeName = newAtt.getID();
if (newRDN.contains(attributeName) == false) // skip any naming attributes
{
Attribute oldAtt = oldSet.get(attributeName);
if (oldAtt != null && oldAtt.size() == 1) // only look at changed single valued attributes.
{
// if a single valued attribute has changed, make it a 'replace' op.
if (attributesEqual(newAtt, oldAtt)==false)
replacementSet.put(newAtt);
}
}
}
}
return replacementSet;
}
/**
* <p>Returns the set of attributes that are in the oldSet, but
* not in the new set, and thus must be deleted. </p>
*
* <p>It also returns the set of attribute *values* that are in
* the old set, but not in the new set. E.g. if attribute A
* has values {1,2,3,4}, and the new attribute A' has {1,4,6,7},
* this returns {2,3} for deletion.</p>
*
* <p>This method will ignore naming values, but will correctly
* handle other values of the naming attribute.</p>
*
* @param newRDN the RDN of the newer entry.
* (usually this is the same as the RDN of the original entry).
* May be null if it is not to be checked.
* @param oldSet the set of already existing attributes
* @param newSet the set of new attributes to test
*/
public static DXAttributes getDeletionSet(RDN newRDN, Attributes oldSet, Attributes newSet)
throws NamingException
{
DXAttributes deletionSet = new DXAttributes();
NamingEnumeration listOfOldAttributes = oldSet.getAll();
while (listOfOldAttributes.hasMore())
{
Attribute oldAtt = (Attribute)listOfOldAttributes.next();
if (! emptyAtt(oldAtt)) // don't delete empty atts!
{
String attributeName = oldAtt.getID();
boolean isNamingAttribute = newRDN.contains(attributeName);
Attribute newAtt = newSet.get(attributeName);
if (newAtt == null)
newAtt = new DXAttribute(attributeName);
/*
* Check for simple "whole attribute" deletes
*/
if (emptyAtt(newAtt) && !isNamingAttribute)
{
deletionSet.put(newAtt);
}
/*
* Check for attribute values that have been dropped, in attributes
* that are larger than 1
*/
else if (isNamingAttribute || oldAtt.size() > 1 || newAtt.size() > 1 )
{
DXNamingEnumeration valuesToDelete = getMissingValues(newAtt.getAll(), oldAtt.getAll());
// check for distinguished value, and ignore it...
if (isNamingAttribute)
removeAnyDistinguishedValues(newRDN, attributeName, valuesToDelete);
if (valuesToDelete.size()>0)
deletionSet.put(new DXAttribute(attributeName, valuesToDelete));
}
}
}
return deletionSet;
}
/**
* Checks two 'Attribute' objects for equality.
* XXX - should this be moved to DXAttribute?
*/
private static boolean attributesEqual(Attribute a, Attribute b)
throws NamingException
{
// sanity checks...
if (a == null && b == null) return true;
if (a == null || b == null) return false;
if (a.size() == 0 && b.size() == 0) return true;
if (a.size() != b.size()) return false;
if (a.get() == null && b.get() == null) return true;
if (a.get() == null || b.get() == null) return false;
if (a.getID().equalsIgnoreCase(b.getID())==false) return false;
try
{
Object[] A = CBArray.enumerationToArray(a.getAll());
Object[] B = CBArray.enumerationToArray(b.getAll());
return CBArray.isUnorderedEqual(A,B);
}
catch (NamingException e)
{
log.log(Level.WARNING, "Naming Exception testing attributes " + a.getID() + " & " + b.getID() + " in DXAttributes:attributesEqual()", e);
}
return false; // only here if error occurred.
}
/**
* Checks whether two 'Attributes' objects are equivalent (including naming attributes, if any).
*/
public static boolean attributesEqual(Attributes a, Attributes b)
{
if (a == null && b == null) return true;
if (a == null || b == null) return false;
return a.equals(b);
}
public boolean equals(Object o)
{
if (o == null) return false;
try
{
if (o instanceof Attributes)
return this.equals((Attributes) o);
}
catch (NamingException e)
{
return false; // suppress exception :-(...
}
return false;
}
public boolean equals(Attributes atts) throws NamingException
{
// some quick and simple equality checks
if (atts == null) return false;
if (size() == 0 && atts.size() == 0) return true;
if (size() != atts.size()) return false;
// at this stage, we have equality candidates - two equally sized attributes...
NamingEnumeration testAtts = getAll();
while (testAtts.hasMore()) // find changed attributes
{
Attribute testAtt = (Attribute)testAtts.next();
String ID = testAtt.getID();
Attribute bAtt = atts.get(ID);
if ( emptyAtt(bAtt) ^ emptyAtt(testAtt) ) return false;
if (attributesEqual(testAtt, bAtt) == false) return false;
}
// if we're here, the attributes must be equal!
return true;
}
/**
* Checks the naming enumeration and removes any distinguished values that
* occur in the RDN.
* @param newRDN the rdn to check for values in
* @param attributeName the name of the attribute (potentially) in the RDN
* @param values the list of values to potentially remove the distinguished value from
*/
private static void removeAnyDistinguishedValues(RDN newRDN, String attributeName, DXNamingEnumeration values)
{
String distinguishedValue = newRDN.getRawVal(attributeName);
values.remove(distinguishedValue); // remove dist. val. (if it is there)
}
/**
* Returns all the values in B that are missing in A. (i.e. return B minus (B union A)).
* @param A the list of values to exclude.
* @param B the list of values to include.
* @return all elements of B not found in A.
*/
static private DXNamingEnumeration getMissingValues(NamingEnumeration A, NamingEnumeration B)
throws NamingException
{
DXNamingEnumeration ret = new DXNamingEnumeration(B);
if (A == null) return ret;
while (A.hasMore())
{
ret.remove(A.next());
}
return ret;
}
// public DirContext getSchema() { return schema; }
public String[] toIDStringArray()
{
DXNamingEnumeration ret = new DXNamingEnumeration(getIDs());
return ret.toStringArray();
}
/**
* A quick test - do we have any numeric OIDs
*
*/
public boolean hasOIDs()
{
return (attOIDs.size()>0);
}
/**
* Utility ftn: checks that an attribute is not null and has at least
* one non-null value.
*/
public static boolean emptyAtt(Attribute att)
{
return DXAttribute.isEmpty(att);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -