001    /**
002     * ================================================
003     * LibLoader : a free Java resource loading library
004     * ================================================
005     *
006     * Project Info:  http://reporting.pentaho.org/libloader/
007     *
008     * (C) Copyright 2006, by Pentaho Corporation and Contributors.
009     *
010     * This library is free software; you can redistribute it and/or modify it under the terms
011     * of the GNU Lesser General Public License as published by the Free Software Foundation;
012     * either version 2.1 of the License, or (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016     * See the GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public License along with this
019     * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020     * Boston, MA 02111-1307, USA.
021     *
022     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023     * in the United States and other countries.]
024     *
025     *
026     * ------------
027     * $Id: ResourceKey.java 3520 2007-10-16 10:34:47Z tmorgner $
028     * ------------
029     * (C) Copyright 2006, by Pentaho Corporation.
030     */
031    package org.jfree.resourceloader;
032    
033    import java.io.Serializable;
034    import java.util.Collections;
035    import java.util.HashMap;
036    import java.util.Map;
037    import java.util.Arrays;
038    
039    /**
040     * The key is an unique identifier for the resource. Most of the time,
041     * this may be an URL, but other (especially database based) schemas are
042     * possible.
043     *
044     * A resource key must provide an 'equals' implementation. ResourceKeys should
045     * be implemented as immutable classes, so that they can be safely stored in
046     * collections or on external storages (like caches).
047     *
048     * @author Thomas Morgner
049     */
050    public final class ResourceKey implements Serializable
051    {
052      private static final Map EMPTY_MAP =
053          Collections.unmodifiableMap(new HashMap());
054    
055      private Map factoryParameters;
056      private Integer hashCode;
057      private Object schema;
058      private Object identifier;
059      private ResourceKey parent;
060    
061      public ResourceKey(final Object schema,
062                         final Object identifier,
063                         final Map factoryParameters)
064      {
065        if (schema == null)
066        {
067          throw new NullPointerException();
068        }
069        if (identifier == null)
070        {
071          throw new NullPointerException();
072        }
073    
074        this.schema = schema;
075        this.identifier = identifier;
076        if (factoryParameters != null)
077        {
078          this.factoryParameters =
079              Collections.unmodifiableMap(new HashMap(factoryParameters));
080        }
081        else
082        {
083          this.factoryParameters = EMPTY_MAP;
084        }
085      }
086    
087      public ResourceKey(final ResourceKey parent,
088                         final Object schema,
089                         final Object identifier,
090                         final Map factoryParameters)
091      {
092        this(schema, identifier, factoryParameters);
093        this.parent = parent;
094      }
095    
096      public ResourceKey getParent()
097      {
098        return parent;
099      }
100    
101      public Map getFactoryParameters ()
102      {
103        return factoryParameters;
104      }
105    
106      public boolean equals(final Object o)
107      {
108        if (this == o)
109        {
110          return true;
111        }
112        if (o == null || getClass() != o.getClass())
113        {
114          return false;
115        }
116    
117        final ResourceKey that = (ResourceKey) o;
118    
119        if (!schema.equals(that.schema))
120        {
121          return false;
122        }
123        if (!factoryParameters.equals(that.factoryParameters))
124        {
125          return false;
126        }
127        if (!identifier.equals(that.identifier))
128        {
129          if (identifier instanceof byte[] && that.identifier instanceof byte[])
130          {
131            final byte[] me = (byte[]) identifier;
132            final byte[] he = (byte[]) that.identifier;
133            Arrays.equals(me, he);
134          }
135          return false;
136        }
137    
138        return true;
139      }
140    
141      public int hashCode()
142      {
143        if (hashCode == null)
144        {
145          int result = factoryParameters.hashCode();
146          result = 29 * result + schema.hashCode();
147          result = 29 * result + identifier.hashCode();
148          hashCode = new Integer(result);
149        }
150        return hashCode.intValue();
151      }
152    
153      public Object getIdentifier()
154      {
155        return identifier;
156      }
157    
158      /**
159       * Returns the schema of this resource key. The schema is an internal
160       * identifier to locate the resource-loader implementation that was
161       * responsible for creating the key in the first place.
162       *
163       * The schema has no meaning outside the resource loading framework.
164       *
165       * @return
166       */
167      public Object getSchema ()
168      {
169        return schema;
170      }
171    
172    
173      public String toString()
174      {
175        return "ResourceKey{" +
176               "schema=" + schema +
177               ", identifier=" + identifier +
178               ", factoryParameters=" + factoryParameters +
179               ", parent=" + parent +
180               '}';
181      }
182    }
183