/**
* Copyright 2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.safehaus.penrose.schema;
import org.safehaus.penrose.directory.EntryConfig;
import org.safehaus.penrose.ldap.RDN;
import java.io.Serializable;
import java.util.*;
/**
* @author Endi S. Dewata
*/
public class Schema implements Serializable, Cloneable {
public final static long serialVersionUID = 1L;
private String name;
protected Set<AttributeType> attributeTypes = new LinkedHashSet<AttributeType>();
protected Map<String,AttributeType> attributeTypesByNameOrOid = new TreeMap<String,AttributeType>();
protected Set<ObjectClass> objectClasses = new LinkedHashSet<ObjectClass>();
protected Map<String,ObjectClass> objectClassesByNameOrOid = new TreeMap<String,ObjectClass>();
public Schema() {
}
public Schema(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Attribute Types
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public Collection<AttributeType> getAttributeTypes() {
return attributeTypes;
}
public Collection<String> getAttributeTypeNames() {
Collection<String> list = new TreeSet<String>();
for (AttributeType at : attributeTypes) {
list.addAll(at.getNames());
}
return list;
}
public Collection<String> getAttributeTypeOids() {
Collection<String> list = new ArrayList<String>();
for (AttributeType at : attributeTypes) {
list.add(at.getOid());
}
return list;
}
public AttributeType getAttributeType(String name) {
return attributeTypesByNameOrOid.get(name.toLowerCase());
}
public void addAttributeType(AttributeType at) {
attributeTypes.add(at);
attributeTypesByNameOrOid.put(at.getOid(), at);
for (String name : at.getNames()) {
attributeTypesByNameOrOid.put(name.toLowerCase(), at);
}
}
public void updateAttributeType(String name, AttributeType at) {
removeAttributeType(name);
addAttributeType(at);
}
public AttributeType removeAttributeType(String name) {
AttributeType at = getAttributeType(name.toLowerCase());
if (at == null) return null;
removeAttributeType(at);
return at;
}
public void removeAttributeType(AttributeType at) {
attributeTypes.remove(at);
attributeTypesByNameOrOid.remove(at.getOid());
for (String atName : at.getNames()) {
attributeTypesByNameOrOid.remove(atName.toLowerCase());
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Object Classes
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public Collection<ObjectClass> getObjectClasses() {
return objectClasses;
}
public Collection<String> getObjectClassNames() {
Collection<String> list = new TreeSet<String>();
for (ObjectClass oc : objectClasses) {
list.addAll(oc.getNames());
}
return list;
}
public Collection<String> getObjectClassOids() {
Collection<String> list = new ArrayList<String>();
for (ObjectClass oc : objectClasses) {
list.add(oc.getOid());
}
return list;
}
public ObjectClass getObjectClass(String name) {
return objectClassesByNameOrOid.get(name.toLowerCase());
}
public void addObjectClass(ObjectClass oc) {
objectClasses.add(oc);
objectClassesByNameOrOid.put(oc.getOid(), oc);
for (String name : oc.getNames()) {
objectClassesByNameOrOid.put(name.toLowerCase(), oc);
}
}
public void updateObjectClass(String name, ObjectClass objectClass) {
removeObjectClass(name);
addObjectClass(objectClass);
}
public ObjectClass removeObjectClass(String name) {
ObjectClass oc = getObjectClass(name.toLowerCase());
if (oc == null) return null;
removeObjectClass(oc);
return oc;
}
public void removeObjectClass(ObjectClass oc) {
objectClasses.remove(oc);
objectClassesByNameOrOid.remove(oc.getOid());
for (String ocName : oc.getNames()) {
objectClassesByNameOrOid.remove(ocName.toLowerCase());
}
}
public Collection<String> getAllObjectClassNames(String ocName) {
Collection<String> list = new ArrayList<String>();
getAllObjectClassNames(list, ocName);
return list;
}
public void getAllObjectClassNames(Collection<String> list, String ocName) {
if (list.contains(ocName)) return;
ObjectClass oc = getObjectClass(ocName);
if (oc == null) return;
Collection<String> superClasses = oc.getSuperClasses();
for (String supName : superClasses) {
getAllObjectClassNames(list, supName);
}
list.add(ocName);
}
public boolean isSuperClass(String parent, String child) {
if (parent.equals(child)) return true;
ObjectClass oc = getObjectClass(child);
if (oc == null) return false;
Collection<String> superClasses = oc.getSuperClasses();
for (String supName : superClasses) {
//log.debug(" - comparing "+parent+" with "+supName+": "+supName.equals(parent));
if (supName.equals(parent)) return true;
boolean result = isSuperClass(parent, supName);
if (result) return true;
}
return false;
}
public Collection<ObjectClass> getObjectClasses(EntryConfig entryConfig) {
Map<String,ObjectClass> map = new HashMap<String,ObjectClass>();
for (String ocName : entryConfig.getObjectClasses()) {
getAllObjectClasses(ocName, map);
}
return map.values();
}
public Collection<ObjectClass> getAllObjectClasses(String objectClassName) {
Map<String,ObjectClass> map = new HashMap<String,ObjectClass>();
getAllObjectClasses(objectClassName, map);
return map.values();
}
public void getAllObjectClasses(String objectClassName, Map<String,ObjectClass> map) {
if ("top".equalsIgnoreCase(objectClassName)) return;
if (map.containsKey(objectClassName)) return;
// add itself
//log.debug("Searching for object class "+objectClassName+" ... ");
ObjectClass objectClass = getObjectClass(objectClassName);
if (objectClass == null) {
//log.debug("--> NOT FOUND");
return;
}
//log.debug("--> FOUND");
map.put(objectClassName, objectClass);
if (objectClass.getSuperClasses() == null) return;
// add all superclasses
for (String ocName : objectClass.getSuperClasses()) {
getAllObjectClasses(ocName, map);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Matching
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public boolean partialMatch(RDN rdn1, RDN rdn2) throws Exception {
for (String name : rdn2.getNames()) {
Object v1 = rdn1.get(name);
Object v2 = rdn2.get(name);
if (v1 == null && v2 == null) {
} else if (v1 == null || v2 == null) {
return false;
} else if (!(v1.toString()).equalsIgnoreCase(v2.toString())) {
return false;
}
}
return true;
}
public boolean match(RDN rdn1, RDN rdn2) throws Exception {
if (!rdn1.getNames().equals(rdn2.getNames())) return false;
for (String name : rdn2.getNames()) {
Object v1 = rdn1.get(name);
Object v2 = rdn2.get(name);
if (v1 == null && v2 == null) {
} else if (v1 == null || v2 == null) {
return false;
} else if (!(v1.toString()).equalsIgnoreCase(v2.toString())) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Schema
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void add(Schema schema) {
attributeTypes.addAll(schema.attributeTypes);
attributeTypesByNameOrOid.putAll(schema.attributeTypesByNameOrOid);
objectClasses.addAll(schema.objectClasses);
objectClassesByNameOrOid.putAll(schema.objectClassesByNameOrOid);
}
public void remove(Schema schema) {
for (AttributeType at : schema.attributeTypes) {
removeAttributeType(at);
}
for (ObjectClass oc : schema.objectClasses) {
removeObjectClass(oc);
}
}
public void clear() {
attributeTypes.clear();
attributeTypesByNameOrOid.clear();
objectClasses.clear();
objectClassesByNameOrOid.clear();
}
public int hashCode() {
return (name == null ? 0 : name.hashCode()) +
(attributeTypes == null ? 0 : attributeTypes.hashCode()) +
(objectClasses == null ? 0 : objectClasses.hashCode());
}
boolean equals(Object o1, Object o2) {
if (o1 == null && o2 == null) return true;
if (o1 != null) return o1.equals(o2);
return o2.equals(o1);
}
public boolean equals(Object object) {
if (this == object) return true;
if (object == null) return false;
if (object.getClass() != this.getClass()) return false;
Schema schema = (Schema)object;
if (!equals(name, schema.name)) return false;
if (!equals(attributeTypes, schema.attributeTypes)) return false;
if (!equals(objectClasses, schema.objectClasses)) return false;
return true;
}
public void copy(Schema schema) throws CloneNotSupportedException {
name = schema.name;
attributeTypes = new LinkedHashSet<AttributeType>();
attributeTypesByNameOrOid = new TreeMap<String,AttributeType>();
for (AttributeType attributeType : schema.getAttributeTypes()) {
addAttributeType((AttributeType)attributeType.clone());
}
objectClasses = new LinkedHashSet<ObjectClass>();
objectClassesByNameOrOid = new TreeMap<String,ObjectClass>();
for (ObjectClass objectClass : schema.getObjectClasses()) {
addObjectClass((ObjectClass)objectClass.clone());
}
}
public Object clone() throws CloneNotSupportedException {
Schema schema = (Schema)super.clone();
schema.copy(this);
return schema;
}
}