org.geotoolkit.referencing.crs.UnprefixedMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of geotk-referencing Show documentation
Show all versions of geotk-referencing Show documentation
Implementations of Coordinate Reference Systems (CRS),
conversion and transformation services derived from ISO 19111.
/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2004-2011, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2011, Geomatys
*
* 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.geotoolkit.referencing.crs;
import java.util.Map;
import org.opengis.referencing.IdentifiedObject;
import org.geotoolkit.util.collection.DerivedMap;
/**
* A map without the {@code "conversion."} prefix in front of property keys. This
* implementation performs a special processing for the {@linkplain #prefix}.name
* 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.
*
* @author Martin Desruisseaux (IRD)
* @version 3.00
*
* @since 2.0
* @module
*/
final class UnprefixedMap extends DerivedMap {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = -5603681431606877770L;
/**
* The prefix to remove for this map.
*/
private final String prefix;
/**
* {@code true} if the {@linkplain #prefix}.name
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.
*/
@SuppressWarnings({"unchecked","rawtypes"}) // Okay because values are Object.
public UnprefixedMap(final Map 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;
}
/**
* Removes 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}.
*/
@Override
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;
}
/**
* Adds the prefix to the specified key.
*
* @param key A key in this map.
* @return The key stored in the {@linkplain #base} map.
*/
@Override
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) == '_');
}
}