001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2001, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.coverage.processing;
018:
019: // J2SE dependencies
020: import java.util.Arrays;
021: import java.util.Iterator;
022: import java.util.Map;
023: import java.util.TreeMap;
024:
025: // OpenGIS dependencies
026: import org.opengis.coverage.Coverage;
027: import org.opengis.coverage.processing.Operation;
028: import org.opengis.parameter.ParameterValueGroup;
029:
030: // Geotools dependencies
031: import org.geotools.coverage.CoverageCache;
032: import org.geotools.resources.Utilities;
033: import org.geotools.parameter.Parameters;
034:
035: /**
036: * An {@link Operation}-{@link ParameterValueGroup} pair, used by
037: * {@link DefaultOperation#doOperation} for caching the result of operations.
038: * Reusing previous computation outputs should be okay since grid coverage
039: * (both the sources and the result) are immutable by default.
040: *
041: * @todo There is a tricky issue for grid coverage backed by a writable rendered
042: * image. The OpenGIS specification allows to change sample values. What
043: * should be the semantic for operation using those images as sources?
044: *
045: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/coverage/src/main/java/org/geotools/coverage/processing/CachedOperation.java $
046: * @version $Id: CachedOperation.java 26655 2007-08-22 13:57:25Z desruisseaux $
047: * @author Martin Desruisseaux
048: */
049: final class CachedOperation {
050: /**
051: * The operation to apply on grid coverages.
052: */
053: private final Operation operation;
054:
055: /**
056: * The parameters names in alphabetical order, including source coverages.
057: */
058: private final String[] names;
059:
060: /**
061: * The parameters values. {@link Coverage} objects will be retained as weak references.
062: */
063: private final Object[] values;
064:
065: /**
066: * The hash code value for this key.
067: */
068: private final int hashCode;
069:
070: /**
071: * Constructs a new key for the specified operation and parameters.
072: *
073: * @param operation The operation to apply on grid coverages.
074: * @param parameters The parameters, including source grid coverages.
075: */
076: CachedOperation(final Operation operation,
077: final ParameterValueGroup parameters) {
078: this .operation = operation;
079: int hashCode = operation.hashCode();
080: final Map param = Parameters.toNameValueMap(parameters,
081: new TreeMap());
082: this .names = new String[param.size()];
083: this .values = new Object[names.length];
084: int index = 0;
085: for (final Iterator it = param.entrySet().iterator(); it
086: .hasNext(); index++) {
087: final Map.Entry entry = (Map.Entry) it.next();
088: names[index] = ((String) entry.getKey()).toLowerCase();
089: Object value = entry.getValue();
090: if (value instanceof Coverage) {
091: value = CoverageCache.DEFAULT
092: .reference((Coverage) value);
093: }
094: if (value != null) {
095: hashCode = 37 * hashCode + value.hashCode();
096: }
097: values[index] = value;
098: }
099: this .hashCode = hashCode;
100: }
101:
102: /**
103: * Compares the specified object with this key for equality.
104: */
105: //@Override
106: public boolean equals(final Object object) {
107: if (object instanceof CachedOperation) {
108: final CachedOperation that = (CachedOperation) object;
109: return Utilities.equals(this .operation, that.operation)
110: && Arrays.equals(this .names, that.names)
111: && Arrays.equals(this .values, that.values);
112: /*
113: * NOTE: values array may contains WeakReference, in which case the 'equals'
114: * method applies to reference instead of referent (i.e. Coverage). It
115: * should work anyway, since CoverageCache should returns the same
116: * WeakReference instance for the same Coverage.
117: */
118: }
119: return false;
120: }
121:
122: /**
123: * Returns a hash code value for this key.
124: */
125: //@Override
126: public int hashCode() {
127: return hashCode;
128: }
129: }
|