/* * 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.imageio.metadata; import java.util.ArrayList; import java.util.List; import org.geotools.imageio.metadata.DefinedByConversion.ParameterValue; import org.geotools.imageio.metadata.RectifiedGrid.AxisName; import org.geotools.imageio.metadata.RectifiedGrid.OffsetVector; import org.geotools.imageio.metadata.Band.Category; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * A list of child elements, for example {@code <Bands>} or * {@code <Axis>}. * * @author Martin Desruisseaux * @author Daniele Romagnoli, GeoSolutions * @author Alessio Fabiani, GeoSolutions */ abstract class ChildList<T extends MetadataAccessor> extends MetadataAccessor { /** * The list of children. */ private final List<T> children; /** * Creates a parser for children. The arguments are given unchanged to the * {@linkplain MetadataAccessor#MetadataAccessor super-class constructor}. * * @param metadata * The metadata node. * @param parentPath * The path to the {@linkplain Node node} of interest, or * {@code null} if {@code metadata} is directly the node of * interest. * @param childPath * The path (relative to {@code parentPath}) to the child * {@linkplain Element elements}, or {@code null} if none. */ protected ChildList(final SpatioTemporalMetadata metadata, final String parentPath, final String childPath) { super(metadata, parentPath, childPath); final int count = childCount(); children = new ArrayList<T>(count != 0 ? count : 4); } protected ChildList(final MetadataAccessor parentNode, final String parentPath, final String childPath) { super(parentNode, parentPath, childPath); final int count = childCount(); children = new ArrayList<T>(count != 0 ? count : 4); } /** * Returns the child at the specified index. * * @param index * the child index. * @throws IndexOutOfBoundsException * if the index is out of bounds. */ public T getChild(final int index) throws IndexOutOfBoundsException { if (index < 0 || index >= childCount()) { throw new IndexOutOfBoundsException(index + "out of range"); } while (children.size() <= index) { children.add(null); } T candidate = children.get(index); if (candidate == null) { candidate = newChild(index); children.set(index, candidate); } return candidate; } /** * Creates a new child, append to the list and returns it. */ public T addChild() { final int index = appendChild(); final T candidate = newChild(index); assert index == children.size(); children.add(candidate); return candidate; } /** * Creates a new child at the specified index. */ protected abstract T newChild(int index); /** * A list of {@linkplain Band bands}. */ static final class Bands extends ChildList<Band> { /** Creates a parser for bands. */ public Bands(final SpatioTemporalMetadata metadata) { super(metadata, SpatioTemporalMetadataFormat.MD_BANDS, SpatioTemporalMetadataFormat.MD_BD); } /** Create a new band. */ protected Band newChild(final int index) { return new Band(this, index); } } /** * A list of {@linkplain Category categories}. */ static final class Categories extends ChildList<Band.Category> { /** Creates a parser for categories. */ public Categories(final MetadataAccessor parent) { super(parent, SpatioTemporalMetadataFormat.MD_BD_CATEGORIES, SpatioTemporalMetadataFormat.MD_BD_CAT); } protected Category newChild(final int index) { return new Category(this, index); } } /** * A list of {@linkplain Axis axis}. */ static final class Axes extends ChildList<Axis> { /** Creates a parser for axis. */ public Axes(final SpatioTemporalMetadata metadata, final String parentCRS) { super(metadata, new StringBuilder(parentCRS).append(SEPARATOR) .append(SpatioTemporalMetadataFormat.MD_COORDINATESYSTEM).append(SEPARATOR) .append(SpatioTemporalMetadataFormat.MD_CS_AXES).toString(), SpatioTemporalMetadataFormat.MD_AXIS); } /** Create a new axis. */ protected Axis newChild(final int index) { return new Axis(this, index); } } /** * A list of {@linkplain AxisName axis}. */ static final class AxesNames extends ChildList<RectifiedGrid.AxisName> { /** Creates a parser for axis. */ public AxesNames(final SpatioTemporalMetadata metadata) { super(metadata, new StringBuilder(SpatioTemporalMetadataFormat.MD_RECTIFIEDGRID) .append(SEPARATOR).append(SpatioTemporalMetadataFormat.MD_RG_AXESNAMES).toString(), SpatioTemporalMetadataFormat.MD_RG_AX_AXISNAME); } protected AxisName newChild(final int index) { return new AxisName(this, index); } } /** * A list of {@linkplain OffsetVector vectors}. */ static final class OffsetVectors extends ChildList<RectifiedGrid.OffsetVector> { /** Creates a parser for offset Vectors. */ public OffsetVectors(final SpatioTemporalMetadata metadata) { super(metadata, new StringBuilder(SpatioTemporalMetadataFormat.MD_RECTIFIEDGRID) .append(SEPARATOR).append(SpatioTemporalMetadataFormat.MD_RG_OFFSETVECTORS).toString(), SpatioTemporalMetadataFormat.MD_RG_OV_OFFSETVECTOR); } protected OffsetVector newChild(int index) { return new OffsetVector(this, index); } } /** * A list of {@linkplain ParameterValue parameterValue}. */ static final class ParameterValues extends ChildList<DefinedByConversion.ParameterValue> { /** Creates a parser for operation. */ public ParameterValues(final MetadataAccessor parent) { super(parent, SpatioTemporalMetadataFormat.MD_SCRS_DBC_PARAMETERS, SpatioTemporalMetadataFormat.MD_SCRS_DBC_PARAMETER_VALUE); } protected ParameterValue newChild(int index) { return new ParameterValue(this, index); } } }