/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2004-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. */ package org.geotools.referencing.crs; import java.util.Map; import org.opengis.referencing.IdentifiedObject; import org.geotools.util.DerivedMap; /** * A map without the <code>"conversion."</code> prefix in front of property keys. This * implementation performs a special processing for the <code>{@linkplain #prefix}.name</code> * key: if it doesn't exists, then the plain {@code name} key is used. In other words, * this map inherits the {@code "name"} property from the {@linkplain #base} map. * * @source $URL$ * @version $Id$ * @author Martin Desruisseaux (IRD) * * @since 2.0 */ final class UnprefixedMap extends DerivedMap<String,String,Object> { /** * The prefix to remove for this map. */ private final String prefix; /** * {@code true} if the <code>{@linkplain #prefix}.name</code> property exists * in the {@linkplain #base base} map. This class will inherit the name and alias * from the {@linkplain #base base} map only if this field is set to {@code false}. */ private final boolean hasName, hasAlias; /** * Creates a new unprefixed map from the specified base map and prefix. * * @param base The base map. * @param prefix The prefix to remove from the keys in the base map. */ public UnprefixedMap(final Map<String,?> base, final String prefix) { super((Map) base, String.class); this.prefix = prefix.trim(); final String nameKey = this.prefix + IdentifiedObject. NAME_KEY; final String aliasKey = this.prefix + IdentifiedObject.ALIAS_KEY; boolean hasName = false; boolean hasAlias = false; for (final Object value : base.keySet()) { final String candidate = value.toString().trim(); if (keyMatches(nameKey, candidate)) { hasName = true; if (hasAlias) break; } else if (keyMatches(aliasKey, candidate)) { hasAlias = true; if (hasName) break; } } this.hasName = hasName; this.hasAlias = hasAlias; } /** * Remove the prefix from the specified key. If the key doesn't begins with * the prefix, then this method returns {@code null}. * * @param key A key from the {@linkplain #base} map. * @return The key that this view should contains instead of {@code key}, * or {@code null}. */ protected String baseToDerived(final String key) { final int length = prefix.length(); final String textualKey = key.trim(); if (textualKey.regionMatches(true, 0, prefix, 0, length)) { return textualKey.substring(length).trim(); } if (isPlainKey(textualKey)) { return textualKey; } return null; } /** * Add the prefix to the specified key. * * @param key A key in this map. * @return The key stored in the {@linkplain #base} map. */ protected String derivedToBase(final String key) { final String textualKey = key.trim(); if (isPlainKey(textualKey)) { return textualKey; } return prefix + textualKey; } /** * Returns {@code true} if the specified candidate is {@code "name"} * or {@code "alias"} without prefix. Key starting with {@code "name_"} * or {@code "alias_"} are accepted as well. */ private boolean isPlainKey(final String key) { return (!hasName && keyMatches(IdentifiedObject.NAME_KEY, key)) || (!hasAlias && keyMatches(IdentifiedObject.ALIAS_KEY, key)); } /** * Returns {@code true} if the specified candidate matched * the specified key name. */ private static boolean keyMatches(final String key, final String candidate) { final int length = key.length(); return candidate.regionMatches(true, 0, key, 0, length) && (candidate.length()==length || candidate.charAt(length)=='_'); } }