ensureNonNull("properties", properties);
Object name = null;
Object alias = null;
Object identifiers = null;
Object remarks = null;
GrowableInternationalString growable = null;
GrowableInternationalString[] subGrowables = null;
/*
* Iterate through each map entry. This have two purposes:
*
* 1) Ignore case (a call to properties.get("foo") can't do that)
* 2) Find localized remarks.
*
* This algorithm is sub-optimal if the map contains a lot of entries of no interest to
* this object. Hopefully, most users will fill a map only with usefull entries.
*/
NEXT_KEY: for (final Map.Entry<String,?> entry : properties.entrySet()) {
String key = entry.getKey().trim().toLowerCase();
Object value = entry.getValue();
/*
* Note: String.hashCode() is part of J2SE specification,
* so it should not change across implementations.
*/
switch (key.hashCode()) {
// Fix case for common keywords. They are not used
// by this class, but are used by some subclasses.
case -1528693765: if (key.equalsIgnoreCase("anchorPoint")) key="anchorPoint"; break;
case -1805658881: if (key.equalsIgnoreCase("bursaWolf")) key="bursaWolf"; break;
case 109688209: if (key.equalsIgnoreCase("operationVersion")) key="operationVersion"; break;
case 1479434472: if (key.equalsIgnoreCase("coordinateOperationAccuracy")) key="coordinateOperationAccuracy"; break;
case 1126917133: if (key.equalsIgnoreCase("positionalAccuracy")) key="positionalAccuracy"; break;
case 1127093059: if (key.equalsIgnoreCase("realizationEpoch")) key="realizationEpoch"; break;
case 1790520781: if (key.equalsIgnoreCase("domainOfValidity")) key="domainOfValidity"; break;
case -1109785975: if (key.equalsIgnoreCase("validArea")) key="validArea"; break;
// -------------------------------------
// "name": String or ReferenceIdentifier
// -------------------------------------
case 3373707: {
if (key.equals(NAME_KEY)) {
if (value instanceof String) {
name = new NamedIdentifier(properties, false);
assert value.equals(((Identifier) name).getCode()) : name;
} else {
// Should be an instance of ReferenceIdentifier, but we don't check
// here. The type will be checked at the end of this method, which
// will thrown an exception with detailed message in case of mismatch.
name = value;
}
continue NEXT_KEY;
}
break;
}
// -------------------------------------------------------
// "alias": String, String[], GenericName or GenericName[]
// -------------------------------------------------------
case 92902992: {
if (key.equals(ALIAS_KEY)) {
alias = NameFactory.toArray(value);
continue NEXT_KEY;
}
break;
}
// -----------------------------------------------------------
// "identifiers": ReferenceIdentifier or ReferenceIdentifier[]
// -----------------------------------------------------------
case 1368189162: {
if (key.equals(IDENTIFIERS_KEY)) {
if (value != null) {
if (value instanceof ReferenceIdentifier) {
identifiers = new ReferenceIdentifier[] {
(ReferenceIdentifier) value
};
} else {
identifiers = value;
}
}
continue NEXT_KEY;
}
break;
}
// ----------------------------------------
// "remarks": String or InternationalString
// ----------------------------------------
case 1091415283: {
if (key.equals(REMARKS_KEY)) {
if (value instanceof InternationalString) {
remarks = value;
continue NEXT_KEY;
}
}
break;
}
}
/*
* Search for additional locales for remarks (e.g. "remarks_fr").
* 'growable.add(...)' will add the value only if the key starts
* with the "remarks" prefix.
*/
if (value instanceof String) {
if (growable == null) {
if (remarks instanceof GrowableInternationalString) {
growable = (GrowableInternationalString) remarks;
} else {
growable = new GrowableInternationalString();
}
}
if (growable.add(REMARKS_KEY, key, value.toString())) {
continue NEXT_KEY;
}
}
/*
* Search for user-specified localizable properties.
*/
if (subProperties == null) {
continue NEXT_KEY;
}
if (localizables != null) {
for (int i=0; i<localizables.length; i++) {
final String prefix = localizables[i];
if (key.equals(prefix)) {
if (value instanceof InternationalString) {
// Stores the value in 'subProperties' after the loop.
break;
}
}
if (value instanceof String) {
if (subGrowables == null) {
subGrowables = new GrowableInternationalString[localizables.length];
}
if (subGrowables[i] == null) {
final Object previous = subProperties.get(prefix);
if (previous instanceof GrowableInternationalString) {
subGrowables[i] = (GrowableInternationalString) previous;
} else {
subGrowables[i] = new GrowableInternationalString();
}
}
if (subGrowables[i].add(prefix, key, value.toString())) {
continue NEXT_KEY;
}
}
}
}
subProperties.put(key, value);
}
/*
* Get the localized remarks, if it was not yet set. If a user specified remarks
* both as InternationalString and as String for some locales (which is a weird
* usage...), then current implementation discart the later with a warning.
*/
if (growable!=null && !growable.getLocales().isEmpty()) {
if (remarks == null) {
remarks = growable;
} else if (!growable.isSubsetOf(remarks)) {
final Logger logger = Logging.getLogger(AbstractIdentifiedObject.class);
final LogRecord record = Loggings.format(Level.WARNING, LoggingKeys.LOCALES_DISCARTED);
record.setLoggerName(logger.getName());
logger.log(record);
}
}
/*
* Get the localized user-defined properties.
*/
if (subProperties!=null && subGrowables!=null) {
for (int i=0; i<subGrowables.length; i++) {
growable = subGrowables[i];
if (growable!=null && !growable.getLocales().isEmpty()) {
final String prefix = localizables[i];
final Object current = subProperties.get(prefix);
if (current == null) {
subProperties.put(prefix, growable);
} else if (!growable.isSubsetOf(current)) {
final Logger logger = Logging.getLogger(AbstractIdentifiedObject.class);
final LogRecord record = Loggings.format(Level.WARNING, LoggingKeys.LOCALES_DISCARTED);
record.setLoggerName(logger.getName());
logger.log(record);
}