/* * * 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.flex.abc.semantics; import java.util.Arrays; import java.util.Iterator; import java.util.Collection; import org.apache.flex.abc.semantics.Namespace; /** * Nsset represents an ABC NamespaceSet, i.e., a set of Namespaces. */ public class Nsset implements Iterable<Namespace> { /** * Manifest constant passed to Collection<T>.toArray(T[]) to cause toArray() * to create a new array. */ private static final Namespace[] CREATE_NEW_NSSET_NAMESPACE_ARRAY = new Namespace[0]; /** * A prime number unlikely to be a divisor of the hash table size, used to * generate composite hash keys. * * @warn if you copy this, pick a new prime to generate distinct hash keys * in different classes. */ private static final long PRIME_MULTIPLIER = 9679; /** * Construct a Nsset from a single Namespace. */ public Nsset(Namespace single_ns) { namespaces = new Namespace[] {single_ns}; } /** * Construct a Nsset from a Collection of Namespaces. */ public Nsset(Collection<Namespace> nss) { namespaces = nss.toArray(CREATE_NEW_NSSET_NAMESPACE_ARRAY); } /** * The set's constituent Namespaces. */ private Namespace[] namespaces = null; /** * @return the namespace set's size. */ public int length() { return namespaces.length; } /** * @return an Iterator over this set's namespaces. */ @Override public Iterator<Namespace> iterator() { return Arrays.asList(namespaces).iterator(); } /** * @return the one consitutent Namespace of this set. * @throws AssertionError if more or less than one Namespace is present. */ public Namespace getSingleQualifier() { assert (namespaces.length == 1); return namespaces[0]; } @Override public String toString() { StringBuffer result = new StringBuffer(); result.append('{'); for (int i = 0; i < namespaces.length; i++) { if (i > 0) result.append(','); result.append(namespaces[i]); } result.append('}'); return result.toString(); } /** * Cached hash code. Generating a hash code for a Nsset is somewhat * expensive, so it's done on demand. */ private Integer cachedHashCode = null; /** * Generate a composite hash code using the Namespaces' hashes. * <p> * {@inheritDoc} */ @Override public int hashCode() { if (cachedHashCode == null) { int result = 0; for (Namespace ns : namespaces) result = (int)(PRIME_MULTIPLIER * result + ns.hashCode()); cachedHashCode = result; } return cachedHashCode; } /** * Determine equality by checking the Namespaces' corresponding fields. * <p> * {@inheritDoc} */ @Override public boolean equals(Object o) { if (this == o) { return true; } else if (!(o instanceof Nsset) || this.hashCode() != o.hashCode()) { return false; } else { // Do a namespace-by-namespace comparison. Nsset other = (Nsset)o; boolean result = this.namespaces.length == other.namespaces.length; for (int i = 0; i < this.namespaces.length && result; i++) result = this.namespaces[i].equals(other.namespaces[i]); return result; } } }