/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.directory.studio.schemaeditor.controller; import java.util.ArrayList; import java.util.List; import org.apache.commons.collections.MultiMap; import org.apache.commons.collections.map.MultiValueMap; import org.apache.directory.api.ldap.model.schema.AttributeType; import org.apache.directory.api.ldap.model.schema.LdapSyntax; import org.apache.directory.api.ldap.model.schema.MatchingRule; import org.apache.directory.api.ldap.model.schema.MutableAttributeType; import org.apache.directory.api.ldap.model.schema.MutableObjectClass; import org.apache.directory.api.ldap.model.schema.ObjectClass; import org.apache.directory.api.ldap.model.schema.SchemaObject; import org.apache.directory.api.util.Strings; import org.apache.directory.studio.schemaeditor.model.Schema; /** * This class represents the SchemaHandler. * <p> * It used to handle the whole Schema (including schemas, attribute types, * object classes, matching rules and syntaxes). * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class SchemaHandler { // // The Lists // /** The schemas List */ private List<Schema> schemasList; /** The attribute types List */ private List<AttributeType> attributeTypesList; /** The matching rules List */ private List<MatchingRule> matchingRulesList; /** The object classes List */ private List<ObjectClass> objectClassesList; /** The syntaxes List */ private List<LdapSyntax> syntaxesList; // // The MultiMap (for fast searching) // /** The schemas MultiMap */ private MultiMap schemasMap; /** The attribute types MultiMap */ private MultiMap attributeTypesMap; /** The matching rules MultiMap */ private MultiMap matchingRulesMap; /** The object classes MultiMap */ private MultiMap objectClassesMap; /** The syntaxes MultiMap */ private MultiMap syntaxesMap; // // The Listeners Lists // private List<SchemaHandlerListener> schemaHandlerListeners; /** * Creates a new instance of SchemaHandler. */ public SchemaHandler() { // Lists schemasList = new ArrayList<Schema>(); attributeTypesList = new ArrayList<AttributeType>(); matchingRulesList = new ArrayList<MatchingRule>();; objectClassesList = new ArrayList<ObjectClass>(); syntaxesList = new ArrayList<LdapSyntax>(); // Maps schemasMap = new MultiValueMap(); attributeTypesMap = new MultiValueMap(); matchingRulesMap = new MultiValueMap(); objectClassesMap = new MultiValueMap(); syntaxesMap = new MultiValueMap(); // Listeners schemaHandlerListeners = new ArrayList<SchemaHandlerListener>(); } /** * Gets the List of all the attribute types. * * @return * the List of all the attribute types */ public List<AttributeType> getAttributeTypes() { return attributeTypesList; } /** * Gets the List of all the matching rules. * * @return * the List of all the matching rules */ public List<MatchingRule> getMatchingRules() { return matchingRulesList; } /** * Gets the List of all the object classes. * * @return * the List of all the object classes */ public List<ObjectClass> getObjectClasses() { return objectClassesList; } /** * Gets the List of all the schemas. * * @return * the List of all the schemas */ public List<Schema> getSchemas() { return schemasList; } /** * Gets the List of all the matching rules. * * @return * the List of all the matching rules */ public List<LdapSyntax> getSyntaxes() { return syntaxesList; } /** * Gets an attribute type identified by an OID, or an alias. * * @param id * an OID or an alias * @return * the corresponding attribute type, or null if no one is found */ public AttributeType getAttributeType( String id ) { List<?> list = getAttributeTypeList( Strings.toLowerCase( id ) ); if ( ( list != null ) && ( list.size() >= 1 ) ) { return ( AttributeType ) list.get( 0 ); } else { return null; } } /** * Get the attribute type(s) List identified by an OID, or an alias. * * @param id * an OID or an alias * @return * the corresponding attribute type(s) List or null if no one is found */ public List<?> getAttributeTypeList( String id ) { return ( List<?> ) attributeTypesMap.get( Strings.toLowerCase( id ) ); } /** * Gets a matching rule identified by an OID, or an alias. * * @param id * an OID or an alias * @return * the corresponding matching rule, or null if no one is found */ public MatchingRule getMatchingRule( String id ) { List<?> list = getMatchingRuleList( Strings.toLowerCase( id ) ); if ( ( list != null ) && ( list.size() >= 1 ) ) { return ( MatchingRule ) list.get( 0 ); } else { return null; } } /** * Gets a matching rule(s) List identified by an OID, or an alias. * * @param id * an OID or an alias * @return * the corresponding matching rule(s) List, or null if no one is found */ public List<?> getMatchingRuleList( String id ) { return ( List<?> ) matchingRulesMap.get( Strings.toLowerCase( id ) ); } /** * Gets an object class identified by an OID, or an alias. * * @param id * an OID or an alias * @return * the corresponding object class, or null if no one is found */ public MutableObjectClass getObjectClass( String id ) { List<?> list = getObjectClassList( Strings.toLowerCase( id ) ); if ( ( list != null ) && ( list.size() >= 1 ) ) { return ( MutableObjectClass ) list.get( 0 ); } else { return null; } } /** * Gets an object class(es) List identified by an OID, or an alias. * * @param id * an OID or an alias * @return * the corresponding object class(es) List, or null if no one is found */ public List<?> getObjectClassList( String id ) { return ( List<?> ) objectClassesMap.get( Strings.toLowerCase( id ) ); } /** * Gets a schema identified by a name. * * @param name * a name * @return * the corresponding schema, or null if no one is found */ public Schema getSchema( String name ) { List<?> list = getSchemaList( Strings.toLowerCase( name ) ); if ( ( list != null ) && ( list.size() >= 1 ) ) { return ( Schema ) list.get( 0 ); } else { return null; } } /** * Gets a schema(s) List identified by a name. * * @param name * a name * @return * the corresponding schema(s) List, or null if no one is found */ public List<?> getSchemaList( String name ) { return ( List<?> ) schemasMap.get( Strings.toLowerCase( name ) ); } /** * Gets a syntax identified by an OID, or an alias. * * @param id * an OID or an alias * @return * the corresponding syntax, or null if no one is found */ public LdapSyntax getSyntax( String id ) { List<?> list = getSyntaxList( Strings.toLowerCase( id ) ); if ( ( list != null ) && ( list.size() >= 1 ) ) { return ( LdapSyntax ) list.get( 0 ); } else { return null; } } /** * Gets a syntax(es) List identified by an OID, or an alias. * * @param id * an OID or an alias * @return * the corresponding syntax(es) List, or null if no one is found */ public List<?> getSyntaxList( String id ) { return ( List<?> ) syntaxesMap.get( Strings.toLowerCase( id ) ); } /** * Adds a SchemaHandlerListener. * * @param listener * the listener */ public void addListener( SchemaHandlerListener listener ) { if ( !schemaHandlerListeners.contains( listener ) ) { schemaHandlerListeners.add( listener ); } } /** * Removes a SchemaHandlerListener. * * @param listener * the listener */ public void removeListener( SchemaHandlerListener listener ) { schemaHandlerListeners.remove( listener ); } /** * Adds a schema * * @param schema * the schema */ public void addSchema( Schema schema ) { // Adding the schema schemasList.add( schema ); schemasMap.put( Strings.toLowerCase( schema.getSchemaName() ), schema ); // Adding its attribute types for ( AttributeType at : schema.getAttributeTypes() ) { addSchemaObject( at ); } // Adding its matching rules for ( MatchingRule mr : schema.getMatchingRules() ) { addSchemaObject( mr ); } // Adding its object classes for ( ObjectClass oc : schema.getObjectClasses() ) { addSchemaObject( oc ); } // Adding its syntaxes for ( LdapSyntax syntax : schema.getSyntaxes() ) { addSchemaObject( syntax ); } notifySchemaAdded( schema ); } /** * Adds the given SchemaObject to the corresponding List and Map * * @param object * the SchemaObject */ private void addSchemaObject( SchemaObject object ) { if ( object instanceof AttributeType ) { AttributeType at = ( AttributeType ) object; attributeTypesList.add( at ); List<String> names = at.getNames(); if ( names != null ) { for ( String name : names ) { attributeTypesMap.put( Strings.toLowerCase( name ), at ); } } attributeTypesMap.put( at.getOid(), at ); } else if ( object instanceof MatchingRule ) { MatchingRule mr = ( MatchingRule ) object; matchingRulesList.add( mr ); List<String> names = mr.getNames(); if ( names != null ) { for ( String name : names ) { matchingRulesMap.put( Strings.toLowerCase( name ), mr ); } } matchingRulesMap.put( mr.getOid(), mr ); } else if ( object instanceof ObjectClass ) { ObjectClass oc = ( ObjectClass ) object; objectClassesList.add( oc ); List<String> names = oc.getNames(); if ( names != null ) { for ( String name : names ) { objectClassesMap.put( Strings.toLowerCase( name ), oc ); } } objectClassesMap.put( oc.getOid(), oc ); } else if ( object instanceof LdapSyntax ) { LdapSyntax syntax = ( LdapSyntax ) object; syntaxesList.add( syntax ); List<String> names = syntax.getNames(); if ( names != null ) { for ( String name : names ) { syntaxesMap.put( Strings.toLowerCase( name ), syntax ); } } syntaxesMap.put( syntax.getOid(), syntax ); } } /** * Removes the given schema. * * @param schema * the schema */ public void removeSchema( Schema schema ) { // Removing the schema schemasList.remove( schema ); schemasMap.remove( Strings.toLowerCase( schema.getSchemaName() ) ); // Removing its attribute types for ( AttributeType at : schema.getAttributeTypes() ) { removeSchemaObject( at ); } // Removing its matching rules for ( MatchingRule mr : schema.getMatchingRules() ) { removeSchemaObject( mr ); } // Removing its object classes for ( ObjectClass oc : schema.getObjectClasses() ) { removeSchemaObject( oc ); } // Removing its syntaxes for ( LdapSyntax syntax : schema.getSyntaxes() ) { removeSchemaObject( syntax ); } notifySchemaRemoved( schema ); } /** * Removes the given SchemaObject to the corresponding List and Map * * @param object * the SchemaObject */ private void removeSchemaObject( SchemaObject object ) { if ( object instanceof AttributeType ) { AttributeType at = ( AttributeType ) object; attributeTypesList.remove( at ); List<String> names = at.getNames(); if ( names != null ) { for ( String name : names ) { attributeTypesMap.remove( Strings.toLowerCase( name ) ); } } attributeTypesMap.remove( at.getOid() ); } else if ( object instanceof MatchingRule ) { MatchingRule mr = ( MatchingRule ) object; matchingRulesList.remove( mr ); List<String> names = mr.getNames(); if ( names != null ) { for ( String name : names ) { matchingRulesMap.remove( Strings.toLowerCase( name ) ); } } matchingRulesMap.remove( mr.getOid() ); } else if ( object instanceof ObjectClass ) { ObjectClass oc = ( ObjectClass ) object; objectClassesList.remove( oc ); List<String> names = oc.getNames(); if ( names != null ) { for ( String name : names ) { objectClassesMap.remove( Strings.toLowerCase( name ) ); } } objectClassesMap.remove( oc.getOid() ); } else if ( object instanceof LdapSyntax ) { LdapSyntax syntax = ( LdapSyntax ) object; syntaxesList.remove( syntax ); List<String> names = syntax.getNames(); if ( names != null ) { for ( String name : names ) { syntaxesMap.remove( Strings.toLowerCase( name ) ); } } syntaxesMap.remove( syntax.getOid() ); } } /** * Renames the given schema. * * @param schema the schema * @param newName the new name */ public void renameSchema( Schema schema, String newName ) { schemasMap.remove( Strings.toLowerCase( schema.getSchemaName() ) ); schema.setSchemaName( newName ); schemasMap.put( Strings.toLowerCase( schema.getSchemaName() ), schema ); // Removing its attribute types for ( AttributeType at : schema.getAttributeTypes() ) { at.setSchemaName( newName ); } // Removing its matching rules for ( MatchingRule mr : schema.getMatchingRules() ) { mr.setSchemaName( newName ); } // Removing its object classes for ( ObjectClass oc : schema.getObjectClasses() ) { oc.setSchemaName( newName ); } // Removing its syntaxes for ( LdapSyntax syntax : schema.getSyntaxes() ) { syntax.setSchemaName( newName ); } notifySchemaRenamed( schema ); } /** * Adds the given attribute type. * * @param at * the attribute type */ public void addAttributeType( AttributeType at ) { Schema schema = getSchema( at.getSchemaName() ); schema.addAttributeType( at ); addSchemaObject( at ); // Notifying the listeners notifyAttributeTypeAdded( at ); } /** * Update the source attribute type with the values of the * destination attribute type. * * @param at1 * the source attribute type * @param at2 * the destination attribute type */ public void modifyAttributeType( MutableAttributeType at1, MutableAttributeType at2 ) { // Removing the references (in case of the names or oid have changed) removeSchemaObject( at1 ); // Updating the attribute type at1.setNames( at2.getNames() ); at1.setOid( at2.getOid() ); at1.setDescription( at2.getDescription() ); at1.setSuperiorOid( at2.getSuperiorOid() ); at1.setUsage( at2.getUsage() ); at1.setSyntaxOid( at2.getSyntaxOid() ); at1.setSyntaxLength( at2.getSyntaxLength() ); at1.setObsolete( at2.isObsolete() ); at1.setSingleValued( at2.isSingleValued() ); at1.setCollective( at2.isCollective() ); at1.setUserModifiable( at2.isUserModifiable() ); at1.setEqualityOid( at2.getEqualityOid() ); at1.setOrderingOid( at2.getOrderingOid() ); at1.setSubstringOid( at2.getSubstringOid() ); // Adding the references (in case of the names or oid have changed) addSchemaObject( at1 ); // Notifying the listeners notifyAttributeTypeModified( at1 ); } /** * Removes the given attribute type. * * @param at * the attribute type */ public void removeAttributeType( AttributeType at ) { Schema schema = getSchema( at.getSchemaName() ); schema.removeAttributeType( at ); removeSchemaObject( at ); // Notifying the listeners notifyAttributeTypeRemoved( at ); } /** * Adds the given object class. * * @param oc * the object class */ public void addObjectClass( MutableObjectClass oc ) { Schema schema = getSchema( oc.getSchemaName() ); schema.addObjectClass( oc ); addSchemaObject( oc ); // Notifying the listeners notifyObjectClassAdded( oc ); } /** * Update the source object class with the values of the * destination object class. * * @param oc1 * the source object class * @param oc2 * the destination object class */ public void modifyObjectClass( MutableObjectClass oc1, ObjectClass oc2 ) { // Removing the references (in case of the names or oid have changed) removeSchemaObject( oc1 ); // Updating the object class oc1.setNames( oc2.getNames() ); oc1.setOid( oc2.getOid() ); oc1.setDescription( oc2.getDescription() ); oc1.setSuperiorOids( oc2.getSuperiorOids() ); oc1.setType( oc2.getType() ); oc1.setObsolete( oc2.isObsolete() ); oc1.setMustAttributeTypeOids( oc2.getMustAttributeTypeOids() ); oc1.setMayAttributeTypeOids( oc2.getMayAttributeTypeOids() ); // Adding the references (in case of the names or oid have changed) addSchemaObject( oc1 ); // Notifying the listeners notifyObjectClassModified( oc1 ); } /** * Removes the given object class. * * @param oc * the object class */ public void removeObjectClass( ObjectClass oc ) { Schema schema = getSchema( oc.getSchemaName() ); schema.removeObjectClass( oc ); removeSchemaObject( oc ); notifyObjectClassRemoved( oc ); } /** * Notifies the SchemaHandler listeners that a schema has been added. * * @param schema * the added schema */ private void notifySchemaAdded( Schema schema ) { for ( SchemaHandlerListener listener : schemaHandlerListeners.toArray( new SchemaHandlerListener[0] ) ) { listener.schemaAdded( schema ); } } /** * Notifies the given listeners that a schema has been removed. * * @param schema * the removed schema */ private void notifySchemaRemoved( Schema schema ) { for ( SchemaHandlerListener listener : schemaHandlerListeners.toArray( new SchemaHandlerListener[0] ) ) { listener.schemaRemoved( schema ); } } /** * Notifies the given listeners that a schema has been renamed. * * @param schema * the renamed schema */ private void notifySchemaRenamed( Schema schema ) { for ( SchemaHandlerListener listener : schemaHandlerListeners.toArray( new SchemaHandlerListener[0] ) ) { listener.schemaRenamed( schema ); } } /** * Notifies the SchemaHandler listeners that an attribute type has been added. * * @param at * the added attribute type */ private void notifyAttributeTypeAdded( AttributeType at ) { // SchemaHandler Listeners for ( SchemaHandlerListener listener : schemaHandlerListeners.toArray( new SchemaHandlerListener[0] ) ) { listener.attributeTypeAdded( at ); } } /** * Notifies the SchemaHandler listeners that an attribute type has been modified. * * @param at * the modified attribute type */ private void notifyAttributeTypeModified( AttributeType at ) { // SchemaHandler Listeners for ( SchemaHandlerListener listener : schemaHandlerListeners.toArray( new SchemaHandlerListener[0] ) ) { listener.attributeTypeModified( at ); } } /** * Notifies the SchemaHandler listeners that an attribute type has been removed. * * @param at * the removed attribute type */ private void notifyAttributeTypeRemoved( AttributeType at ) { // SchemaHandler Listeners for ( SchemaHandlerListener listener : schemaHandlerListeners.toArray( new SchemaHandlerListener[0] ) ) { listener.attributeTypeRemoved( at ); } } /** * Notifies the SchemaHandler listeners that an object class has been added. * * @param oc * the added object class */ private void notifyObjectClassAdded( ObjectClass oc ) { // SchemaHandler Listeners for ( SchemaHandlerListener listener : schemaHandlerListeners.toArray( new SchemaHandlerListener[0] ) ) { listener.objectClassAdded( oc ); } } /** * Notifies the SchemaHandler listeners that an object class has been modified. * * @param oc * the modified object class */ private void notifyObjectClassModified( ObjectClass oc ) { // SchemaHandler Listeners for ( SchemaHandlerListener listener : schemaHandlerListeners.toArray( new SchemaHandlerListener[0] ) ) { listener.objectClassModified( oc ); } } /** * Notifies the SchemaHandler listeners that an object class has been removed. * * @param oc * the removed object class */ private void notifyObjectClassRemoved( ObjectClass oc ) { // SchemaHandler Listeners for ( SchemaHandlerListener listener : schemaHandlerListeners.toArray( new SchemaHandlerListener[0] ) ) { listener.objectClassRemoved( oc ); } } /** * Verifies if the given oid is already taken by a schema object. * * @param oid the oid * @return <code>true</code> if the the oid is already taken */ public boolean isOidAlreadyTaken( String oid ) { String lowerCasedOid = Strings.toLowerCase( oid ); if ( attributeTypesMap.containsKey( lowerCasedOid ) ) { return true; } else if ( objectClassesMap.containsKey( lowerCasedOid ) ) { return true; } else if ( matchingRulesMap.containsKey( lowerCasedOid ) ) { return true; } else if ( syntaxesMap.containsKey( lowerCasedOid ) ) { return true; } return false; } /** * Verifies if the given alias is already taken by an attribute type. * * @param alias the alias * @return <code>true</code> if the the alias is already taken */ public boolean isAliasAlreadyTakenForAttributeType( String alias ) { return attributeTypesMap.containsKey( Strings.toLowerCase( alias ) ); } /** * Verifies if the given alias is already taken by an object class. * * @param alias the alias * @return <code>true</code> if the the alias is already taken */ public boolean isAliasAlreadyTakenForObjectClass( String alias ) { return objectClassesMap.containsKey( Strings.toLowerCase( alias ) ); } /** * Verifies if the given name for a schema is already taken by another schema. * * @param name * the name * @return * true if the the name is already taken */ public boolean isSchemaNameAlreadyTaken( String name ) { return schemasMap.containsKey( Strings.toLowerCase( name ) ); } }