/* * 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 java.util.ArrayList; import java.util.List; import org.geotools.resources.i18n.Errors; import org.geotools.resources.i18n.ErrorKeys; import org.w3c.dom.Element; /** * A list of child elements, for example {@code <SampleDimensions>} or {@code <Axis>}. * * @since 2.4 * @source $URL$ * @version $Id$ * @author Martin Desruisseaux * @author Cédric Briançon */ abstract class ChildList<T extends MetadataAccessor> extends MetadataAccessor { /** * The list of childs. */ private final List<T> childs; /** * Creates a parser for childs. 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 GeographicMetadata metadata, final String parentPath, final String childPath) { super(metadata, parentPath, childPath); final int count = childCount(); childs = 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(Errors.format(outOfBounds(), index)); } while (childs.size() <= index) { childs.add(null); } T candidate = childs.get(index); if (candidate == null) { candidate = newChild(index); childs.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 == childs.size(); childs.add(candidate); return candidate; } /** * Creates a new child at the specified index. */ protected abstract T newChild(int index); /** * Returns the key for "out of range" error localization. */ int outOfBounds() { return ErrorKeys.INDEX_OUT_OF_BOUNDS_$1; } /** * A list of {@linkplain Band bands}. */ static final class Bands extends ChildList<Band> { /** Creates a parser for bands. */ public Bands(final GeographicMetadata metadata) { super(metadata, "rectifiedGridDomain/rangeSet/bands", "band"); } /** Create a new band. */ protected Band newChild(final int index) { return new Band(this, index); } /** Returns the key for "out of range" error localization. */ @Override int outOfBounds() { return ErrorKeys.BAD_BAND_NUMBER_$1; } } /** * A list of {@linkplain Axis axis}. */ static final class Axes extends ChildList<Axis> { /** Creates a parser for axis. */ public Axes(final GeographicMetadata metadata) { super(metadata, "rectifiedGridDomain/crs/cs", "axis"); } /** Create a new band. */ protected Axis newChild(final int index) { return new Axis(this, index); } } /** * A list of {@linkplain Parameter parameters}. */ static final class Parameters extends ChildList<Parameter> { /** Creates a parser for parameters. */ public Parameters(final GeographicMetadata metadata) { super(metadata, "rectifiedGridDomain/crs/projection", "parameter"); } /** Create a new band. */ protected Parameter newChild(final int index) { return new Parameter(this, index); } } }