/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. * * This package contains documentation from OpenGIS specifications. * OpenGIS consortium's work is fully acknowledged here. */ package org.geotools.util; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.opengis.util.MemberName; import org.opengis.util.Record; import org.opengis.util.RecordSchema; import org.opengis.util.RecordType; import org.opengis.util.TypeName; /** * The type definition of a {@linkplain Record record}. * Used to provide a record of data type (in a manner similar to a strongly typed Map). * <p> * Please note that a record is <em>strongly</em> typed (and may be better thought * of as a mathematical tuple). The "keys" are strictly controlled "{@link MemberName}s" * and are usually defined in the context of a schema. * * @since 2.4 * * @source $URL$ * @version $Id$ * @author Jody Garnet * @author Martin Desruisseaux */ public class RecordTypeImpl implements RecordType { /** * The name that identifies this record type. */ private TypeName typeName; /** * The members and their values. */ private Map<MemberName,TypeName> attributeTypes; /** * The schema that contains this record type. */ private RecordSchema parent; /** * Empty constructor only used by JAXB. */ private RecordTypeImpl() { } /** * Creates a record with all attribute types specified. * * @param parent The schema that contains this record type. * @param typeName The name that identifies this record type. * @param members The name of the members to be included in this record type. */ public RecordTypeImpl(final RecordSchema parent, final TypeName typeName, final Collection<MemberName> members) { this.parent = parent; this.typeName = typeName; final Map<MemberName,TypeName> attributeTypes = new HashMap<MemberName,TypeName>(); for (final MemberName member : members) { attributeTypes.put(member, member.getAttributeType()); } this.attributeTypes = Collections.unmodifiableMap(attributeTypes); } /** * Creates a record with all attribute types specified. * * @param parent The schema that contains this record type. * @param typeName The name that identifies this record type. * @param attributeTypes * * @todo Should we really provide this method? There is no garantee that the user-provided * values are consistent with {@link MemberName#getAttributeType}. */ public RecordTypeImpl(final RecordSchema parent, final TypeName typeName, final Map<MemberName,TypeName> attributeTypes) { this.parent = parent; this.typeName = typeName; this.attributeTypes = Collections.unmodifiableMap(attributeTypes); } /** * Returns the name that identifies this record type. * If this {@code RecordType} is contained in a {@linkplain RecordSchema record schema}, * then the record type name should be a valid in the {@linkplain NameSpace name space} * of the record schema: * * <blockquote><code> * {@linkplain #getContainer()}.{@linkplain RecordSchema#getSchemaName * getSchemaName()}.{@linkplain org.opengis.util.LocalName#scope scope()} * </code></blockquote> */ public TypeName getTypeName() { return typeName; } /** * Returns the schema that contains this record type. */ public RecordSchema getContainer() { return parent; } /** * Returns the unmodifiable dictionary of all (<var>name</var>, <var>type</var>) * pairs in this record type. */ public Map<MemberName,TypeName> getAttributeTypes() { return attributeTypes; } /** * Returns the set of attribute names defined in this {@code RecordType}'s dictionary. * If there are no attributes, this method returns the empty set. This method is functionally * equivalent to <code>{@linkplain #getAttributeTypes()}.{@linkplain Map#keySet() keySet()}</code>. */ public Set<MemberName> getMembers() { return getAttributeTypes().keySet(); } /** * Looks up the provided attribute name and returns the associated type name. If the attribute * name is not defined in this record type, then this method returns {@code null}. This method * is functionnaly equivalent to * <code>{@linkplain #getAttributeTypes()}.{@linkplain Map#get get}(name)</code>. * * @todo Does it make sense given that {@link MemberName#getAttributeType} already provides * this information? */ public TypeName locate(final MemberName memberName) { return getAttributeTypes().get(memberName); } /** * Determines if the specified record is compatible with this record type. This method returns * {@code true} if the specified {@code record} argument is non-null and the following condition * holds: * <p> * <ul> * <li><code>{@linkplain #getMembers()}.{@linkplain Set#containsAll containsAll}(record.{@linkplain * Record#getAttributes() getAttributes()}.{@linkplain Map#keySet keySet()})</code></li> * <li>Any other implementation-specific conditions. * </ul> * * @todo Replace {@code equals} by {@code containsAll}. */ public boolean isInstance(final Record record) { return getMembers().equals(record.getAttributes().keySet()); } }