/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2007-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.image.io.metadata;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOInvalidTreeException;
import org.geotools.resources.XArray;
/**
* Merges metadata.
*
* @todo This class is only a first draft. It will be expanded in the future for performing
* a real merge of two {@link GeographicMetadata} objects.
*
* @since 2.5
* @source $URL$
* @version $Id$
* @author Martin Desruisseaux
*/
public class MetadataMerge {
private MetadataMerge() {
}
/**
* Merges the two specified tree. If both source and target metadata are non-null, then this
* method performs the following steps:
* <p>
* <ul>
* <li>Searchs for a format name which is common to both metadata;</li>
* <li>invokes {@link IIOMetadata#getAsTree} on the source metadata;</li>
* <li>invokes {@link IIOMetadata#mergeTree} on the target metadata.</li>
* </ul>
*
* @param source The source metadata, or {@code null}.
* @param target The target metadata, or {@code null}.
* @return {@code source} if {@code target} was null, or {@code target} otherwise.
*
* @throws IllegalStateException if {@code target} is read-only.
* @throws IIOInvalidTreeException if the {@code source} tree cannot be parsed successfully.
*/
public static IIOMetadata merge(final IIOMetadata source, final IIOMetadata target)
throws IllegalStateException, IIOInvalidTreeException
{
if (source == null) {
return target;
}
if (target == null) {
return source;
}
final String format = commonFormatName(source, target);
if (format != null) {
target.mergeTree(format, source.getAsTree(format));
}
return null;
}
/**
* Returns the name of a format which is common to both metadata.
* The preferred formats are (in order):
*
* <ul>
* <li>The native format of target metadata.<li>
* <li>The native format of source metadata.<li>
* <li>A format supported by both metadata which is not the standard format.</li>
* <li>The standard format is last resort, because it contains no geographic
* data and we wanted to give the priority to geographic formats.</li>
* </ul>
*
* If no common format is found, then this method returns {@code null}.
*/
private static String commonFormatName(final IIOMetadata source, final IIOMetadata target) {
final String[] sourceFormats = source.getMetadataFormatNames();
String format = target.getNativeMetadataFormatName();
if (format != null) {
if (XArray.contains(sourceFormats, format)) {
return format;
}
}
/*
* The target native format is not supported. Try the source native format. We will search
* only in extra names (not in all names) because we don't want to consider the standard
* format now, and because it is not worth to test again the target native format since we
* just did that in the block before.
*/
final String[] targetFormats = target.getExtraMetadataFormatNames();
if (targetFormats != null) {
format = source.getNativeMetadataFormatName();
if (format != null) {
if (XArray.contains(targetFormats, format)) {
return format;
}
}
/*
* Checks if there is a target extra format supported by the source metadata.
*/
for (int i=0; i<targetFormats.length; i++) {
format = targetFormats[i];
if (XArray.contains(sourceFormats, format)) {
return format;
}
}
}
/*
* The standard format is the only one left. We try it last because it contains no
* geographic information, and we wanted to give the priority to geographic formats.
*/
if (source.isStandardMetadataFormatSupported() && target.isStandardMetadataFormatSupported()) {
return IIOMetadataFormatImpl.standardMetadataFormatName;
}
return null;
}
}