/* * ==================== * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common Development * and Distribution License("CDDL") (the "License"). You may not use this file * except in compliance with the License. * * You can obtain a copy of the License at * http://opensource.org/licenses/cddl1.php * See the License for the specific language governing permissions and limitations * under the License. * * When distributing the Covered Code, include this CDDL Header Notice in each file * and include the License file at http://opensource.org/licenses/cddl1.php. * If applicable, add the following below this CDDL Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * ==================== */ package org.identityconnectors.framework.common.objects; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.identityconnectors.common.Assertions; import org.identityconnectors.common.CollectionUtil; import org.identityconnectors.framework.api.operations.APIOperation; import org.identityconnectors.framework.common.serializer.SerializerUtil; /** * Determines the objects supported by a * {@link org.identityconnectors.framework.spi.Connector}. * * The {@link Schema} object is used to represent the basic objects that a * connector supports. This does not prevent a connector from supporting more. * Rather, this is informational for the caller of the connector to understand a * minimum support level. The schema defines 4 primary data structures * <ol> * <li>Declared ObjectClasses ({@link #getObjectClassInfo()}).</li> * <li>Declared OperationOptionInfo ({@link #getOperationOptionInfo()}).</li> * <li>Supported ObjectClasses by operation ( * {@link #getSupportedObjectClassesByOperation()}).</li> * <li>Supported OperationOptionInfo by operation( * {@link #getSupportedOptionsByOperation()()}).</li> * </ol> * * TODO: add more to describe and what is expected from this call and how it is * used.. based on OperationalAttribute etc.. */ public final class Schema { /** * */ private final Set<ObjectClassInfo> declaredObjectClasses; private final Set<OperationOptionInfo> declaredOperationOptions; private final Map<Class<? extends APIOperation>, Set<ObjectClassInfo>> supportedObjectClassesByOperation; private final Map<Class<? extends APIOperation>, Set<OperationOptionInfo>> supportedOptionsByOperation; /** * Public only for serialization; please use SchemaBuilder instead. * * @param info * @param supportedObjectClassesByOperation */ public Schema( Set<ObjectClassInfo> info, Set<OperationOptionInfo> options, Map<Class<? extends APIOperation>, Set<ObjectClassInfo>> supportedObjectClassesByOperation, Map<Class<? extends APIOperation>, Set<OperationOptionInfo>> supportedOptionsByOperation) { declaredObjectClasses = CollectionUtil.newReadOnlySet(info); declaredOperationOptions = CollectionUtil.newReadOnlySet(options); // make read-only { Map<Class<? extends APIOperation>, Set<ObjectClassInfo>> temp = new HashMap<Class<? extends APIOperation>, Set<ObjectClassInfo>>(); for (Map.Entry<Class<? extends APIOperation>, Set<ObjectClassInfo>> entry : supportedObjectClassesByOperation .entrySet()) { Class<? extends APIOperation> op = entry.getKey(); Set<ObjectClassInfo> resolvedClasses = CollectionUtil.newReadOnlySet(entry.getValue()); temp.put(op, resolvedClasses); } this.supportedObjectClassesByOperation = CollectionUtil.asReadOnlyMap(temp); } // make read-only { Map<Class<? extends APIOperation>, Set<OperationOptionInfo>> temp = new HashMap<Class<? extends APIOperation>, Set<OperationOptionInfo>>(); for (Map.Entry<Class<? extends APIOperation>, Set<OperationOptionInfo>> entry : supportedOptionsByOperation .entrySet()) { Class<? extends APIOperation> op = entry.getKey(); Set<OperationOptionInfo> resolvedClasses = CollectionUtil.newReadOnlySet(entry.getValue()); temp.put(op, resolvedClasses); } this.supportedOptionsByOperation = CollectionUtil.asReadOnlyMap(temp); } } /** * Returns the set of object classes that are defined in the schema, * regardless of which operations support them. */ public Set<ObjectClassInfo> getObjectClassInfo() { return declaredObjectClasses; } /** * Returns the ObjectClassInfo for the given type. * * @param type * The type to find. * @return the ObjectClassInfo for the given type or null if not found. */ public ObjectClassInfo findObjectClassInfo(String type) { Assertions.nullCheck(type, "type"); for (ObjectClassInfo info : declaredObjectClasses) { if (info.is(type)) { return info; } } return null; } /** * Returns the set of operation options that are defined in the schema, * regardless of which operations support them. * * @return The options defined in this schema. */ public Set<OperationOptionInfo> getOperationOptionInfo() { return declaredOperationOptions; } /** * Returns the OperationOptionInfo for the given name. * * @param name * The name to find. * @return the OperationOptionInfo for the given name or null if not found. */ public OperationOptionInfo findOperationOptionInfo(String name) { Assertions.nullCheck(name, "name"); for (OperationOptionInfo info : declaredOperationOptions) { if (info.getName().equals(name)) { return info; } } return null; } /** * Returns the supported object classes for the given operation. * * @param apiop * The operation. * @return the supported object classes for the given operation. */ public Set<ObjectClassInfo> getSupportedObjectClassesByOperation( Class<? extends APIOperation> apiop) { Set<ObjectClassInfo> rv = supportedObjectClassesByOperation.get(apiop); if (rv == null) { @SuppressWarnings("unchecked") Set<ObjectClassInfo> empty = Collections.EMPTY_SET; return empty; } else { return rv; } } /** * Returns the supported options for the given operation. * * @param apiop * The operation. * @return the supported options for the given operation. */ public Set<OperationOptionInfo> getSupportedOptionsByOperation( Class<? extends APIOperation> apiop) { Set<OperationOptionInfo> rv = supportedOptionsByOperation.get(apiop); if (rv == null) { @SuppressWarnings("unchecked") Set<OperationOptionInfo> empty = Collections.EMPTY_SET; return empty; } else { return rv; } } /** * Returns the set of object classes that apply to a particular operation. * * @return the set of object classes that apply to a particular operation. */ public Map<Class<? extends APIOperation>, Set<ObjectClassInfo>> getSupportedObjectClassesByOperation() { return supportedObjectClassesByOperation; } /** * Returns the set of operation options that apply to a particular * operation. * * @return the set of operation options that apply to a particular * operation. */ public Map<Class<? extends APIOperation>, Set<OperationOptionInfo>> getSupportedOptionsByOperation() { return supportedOptionsByOperation; } /** * {@inheritDoc} */ @Override public String toString() { return SerializerUtil.serializeXmlObject(this, false); } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { if (obj instanceof Schema) { Schema other = (Schema) obj; if (!CollectionUtil.equals(getObjectClassInfo(), other.getObjectClassInfo())) { return false; } if (!CollectionUtil.equals(getOperationOptionInfo(), other.getOperationOptionInfo())) { return false; } if (!CollectionUtil.equals(supportedObjectClassesByOperation, other.supportedObjectClassesByOperation)) { return false; } if (!CollectionUtil.equals(supportedOptionsByOperation, other.supportedOptionsByOperation)) { return false; } return true; } return false; } /** * Create a hash code from all the object info objects. * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return declaredObjectClasses.hashCode(); } }