/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* Simple bean representing an ldap entry. Contains a DN and ldap attributes.
*
* @author Middleware Services
*/
public class LdapEntry extends AbstractLdapBean
{
/** hash code seed. */
private static final int HASH_CODE_SEED = 331;
/** serial version uid. */
private static final long serialVersionUID = 7819007625501406463L;
/** Distinguished name for this entry. */
private String entryDn;
/** Attributes contained in this bean. */
private final Map<String, LdapAttribute> entryAttributes;
/** Default constructor. */
public LdapEntry()
{
this(SortBehavior.getDefaultSortBehavior());
}
/**
* Creates a new ldap entry.
*
* @param sb sort behavior
*/
public LdapEntry(final SortBehavior sb)
{
super(sb);
if (SortBehavior.UNORDERED == sb) {
entryAttributes = new HashMap<>();
} else if (SortBehavior.ORDERED == sb) {
entryAttributes = new LinkedHashMap<>();
} else if (SortBehavior.SORTED == sb) {
entryAttributes = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
} else {
throw new IllegalArgumentException("Unknown sort behavior: " + sb);
}
}
/**
* Creates a new ldap entry.
*
* @param dn dn for this entry
*/
public LdapEntry(final String dn)
{
this();
setDn(dn);
}
/**
* Creates a new ldap entry.
*
* @param dn dn for this entry
* @param attr ldap attribute for this entry
*/
public LdapEntry(final String dn, final LdapAttribute... attr)
{
this();
setDn(dn);
for (LdapAttribute a : attr) {
addAttribute(a);
}
}
/**
* Creates a new ldap entry.
*
* @param dn dn for this entry
* @param attrs collection of attributes to add
*/
public LdapEntry(final String dn, final Collection<LdapAttribute> attrs)
{
this();
setDn(dn);
addAttributes(attrs);
}
/**
* Returns the DN.
*
* @return entry DN
*/
public String getDn()
{
return entryDn;
}
/**
* Sets the DN.
*
* @param dn dn to set
*/
public void setDn(final String dn)
{
entryDn = dn;
}
/**
* Returns a collection of ldap attribute.
*
* @return collection of ldap attribute
*/
public Collection<LdapAttribute> getAttributes()
{
return entryAttributes.values();
}
/**
* Returns a single attribute of this attributes. If multiple attributes exist the first attribute returned by the
* underlying iterator is used. If no attributes exist null is returned.
*
* @return single attribute
*/
public LdapAttribute getAttribute()
{
if (entryAttributes.isEmpty()) {
return null;
}
return entryAttributes.values().iterator().next();
}
/**
* Returns the attribute with the supplied name.
*
* @param name of the attribute to return
*
* @return ldap attribute
*/
public LdapAttribute getAttribute(final String name)
{
if (name != null) {
return entryAttributes.get(name.toLowerCase());
}
return null;
}
/**
* Returns the attribute names in this entry.
*
* @return string array of attribute names
*/
public String[] getAttributeNames()
{
final String[] names = new String[entryAttributes.size()];
int i = 0;
for (LdapAttribute la : entryAttributes.values()) {
names[i++] = la.getName();
}
return names;
}
/**
* Adds an attribute to this ldap attributes.
*
* @param attr attribute to add
*/
public void addAttribute(final LdapAttribute... attr)
{
for (LdapAttribute a : attr) {
entryAttributes.put(a.getName().toLowerCase(), a);
}
}
/**
* Adds attribute(s) to this ldap attributes.
*
* @param attrs collection of attributes to add
*/
public void addAttributes(final Collection<LdapAttribute> attrs)
{
attrs.forEach(this::addAttribute);
}
/**
* Removes an attribute from this ldap attributes.
*
* @param attr attribute to remove
*/
public void removeAttribute(final LdapAttribute... attr)
{
for (LdapAttribute a : attr) {
entryAttributes.remove(a.getName().toLowerCase());
}
}
/**
* Removes the attribute of the supplied name from this ldap attributes.
*
* @param name of attribute to remove
*/
public void removeAttribute(final String name)
{
entryAttributes.remove(name.toLowerCase());
}
/**
* Removes the attribute(s) from this ldap attributes.
*
* @param attrs collection of ldap attributes to remove
*/
public void removeAttributes(final Collection<LdapAttribute> attrs)
{
attrs.forEach(this::removeAttribute);
}
/**
* Changes the name of an attribute in this entry. The old attribute is removed from this entry, the name is changed
* with {@link LdapAttribute#setName(String)}, and the attribute is added back to this entry. If oldName does not
* exist, this method does nothing.
*
* @param oldName attribute name to change from
* @param newName attribute name to change to
*/
public void renameAttribute(final String oldName, final String newName)
{
final LdapAttribute la = getAttribute(oldName);
if (la != null) {
removeAttribute(oldName);
la.setName(newName);
addAttribute(la);
}
}
/**
* Returns the number of attributes in this ldap attributes.
*
* @return number of attributes in this ldap attributes
*/
public int size()
{
return entryAttributes.size();
}
/** Removes all the attributes in this ldap attributes. */
public void clear()
{
entryAttributes.clear();
}
@Override
public boolean equals(final Object o)
{
if (o == this) {
return true;
}
if (o != null && getClass() == o.getClass()) {
final LdapEntry v = (LdapEntry) o;
return LdapUtils.areEqual(
entryDn != null ? entryDn.toLowerCase() : null,
v.entryDn != null ? v.entryDn.toLowerCase() : null) &&
LdapUtils.areEqual(entryAttributes, v.entryAttributes);
}
return false;
}
@Override
public int hashCode()
{
return
LdapUtils.computeHashCode(
HASH_CODE_SEED,
entryDn != null ? entryDn.toLowerCase() : null,
entryAttributes.values());
}
@Override
public String toString()
{
return String.format("[dn=%s%s]", entryDn, entryAttributes.values());
}
/**
* Returns the list of attribute modifications needed to change the supplied target entry into the supplied source
* entry.
*
* @param source ldap entry containing new data
* @param target ldap entry containing existing data
*
* @return attribute modifications needed to change target into source or an empty array
*/
public static AttributeModification[] computeModifications(final LdapEntry source, final LdapEntry target)
{
final List<AttributeModification> mods = new ArrayList<>();
for (LdapAttribute sourceAttr : source.getAttributes()) {
final LdapAttribute targetAttr = target.getAttribute(sourceAttr.getName());
if (targetAttr == null) {
final AttributeModification mod = new AttributeModification(AttributeModificationType.ADD, sourceAttr);
mods.add(mod);
} else if (!targetAttr.equals(sourceAttr)) {
final AttributeModification mod = new AttributeModification(AttributeModificationType.REPLACE, sourceAttr);
mods.add(mod);
}
}
for (LdapAttribute targetAttr : target.getAttributes()) {
final LdapAttribute sourceAttr = source.getAttribute(targetAttr.getName());
if (sourceAttr == null) {
final AttributeModification mod = new AttributeModification(AttributeModificationType.REMOVE, targetAttr);
mods.add(mod);
}
}
return mods.toArray(new AttributeModification[mods.size()]);
}
}