<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">/*
 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
 * Copyright (C) 2006 - JScience (http://jscience.org/)
 * All rights reserved.
 * 
 * Permission to use, copy, modify, and distribute this software is
 * freely granted, provided that this notice is preserved.
 */

/*
 * This class has been adapted from JScience to use 
 * JSR-363 and newer versions of opengis by Daryn 
 * Butler, Engineering Technician at the United States
 * Department of Agriculture, 2019
 */

package usda.weru.gis.latlong;

import java.util.Collection;
import java.util.Set;

import javax.measure.quantity.Angle;
import javax.measure.quantity.Time;
import javax.measure.quantity.Length;
import javax.measure.Quantity;
import javax.measure.Unit;

import javolution.util.FastSet;

import usda.weru.gis.latlong.CoordinatesConverter;
import usda.weru.gis.latlong.Coordinates;

import org.opengis.metadata.Identifier;
import org.opengis.metadata.citation.Citation;
import org.opengis.metadata.extent.Extent;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.util.InternationalString;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.util.GenericName;
import org.opengis.referencing.ReferenceIdentifier;
import org.opengis.referencing.cs.RangeMeaning;

/**
 * This class represents an arbitrary system of reference for which 
 * {@link Coordinates coordinates} of same significance can be stated.
 * 
 * @author &lt;a href="mailto:jean-marie@dautelle.com"&gt;Jean-Marie Dautelle&lt;/a&gt;
 * @version 3.0, February 13, 2006
 */
public abstract class CoordinateReferenceSystem&lt;C extends Coordinates&lt;?&gt;&gt;
        implements org.opengis.referencing.crs.CoordinateReferenceSystem {

    
    /**
     * This class represents an absolute position (can be be extended)
     */
    protected static class AbsolutePosition {

        /**
         * Holds the Geodetic Latitude (WGS84 Ellipsoid).
         */
        public Quantity&lt;Angle&gt; latitudeWGS84;

        /**
         * Holds the Geodetic Longitude (WGS84 Ellipsoid).
         */
        public Quantity&lt;Angle&gt; longitudeWGS84;

        /**
         * Holds the WGS84 Ellipsoidal Height.
         */
        public Quantity&lt;Length&gt; heightWGS84;

        /**
         * Holds the Time since midnight, January 1, 1970 UTC. 
         */
        public Quantity&lt;Time&gt; timeUTC;
    }

    /**
     * Returns the converter between this coordinate reference system 
     * and the one specified.
     * 
     * @param  that the coordinate reference system to convert to.
     * @return the corresponding coordinates converter.
     * @throws ConversionException if the conversion is not possible
     *         (e.g. geographic to temporal).
     */
    public &lt;T extends Coordinates&lt;?&gt;&gt; CoordinatesConverter&lt;C, T&gt; getConverterTo(
            CoordinateReferenceSystem&lt;T&gt; that) {
        return new GeneralConverter&lt;T&gt;(that);
    }

    // General implementation using absolute position as intermediary.
    private class GeneralConverter&lt;T extends Coordinates&lt;?&gt;&gt; implements
            CoordinatesConverter&lt;C, T&gt; {
        private final CoordinateReferenceSystem&lt;T&gt; _toCRS;

        private GeneralConverter(CoordinateReferenceSystem&lt;T&gt; toCRS) {
            _toCRS = toCRS;
        }

        public T convert(C source) {
            AbsolutePosition position = positionOf(source,
                    new AbsolutePosition());
            return _toCRS.coordinatesOf(position);
        }
    }

    /**
     * Returns the coordinates in this reference system of the specified 
     * absolute position.
     * 
     * @param position the absolute position for which the coordinates  
     *        in this reference system is returned.
     * @return the coordinates for the specified absolute position.
     * @throws ConversionException if a conversion error occurs.
     */
    protected abstract C coordinatesOf(AbsolutePosition position);

    /**
     * Returns the absolute position from the coordinates in
     * this reference system. This update may require information already 
     * supplied by the position. For example, the height for a pressure 
     * altitude might depends upon the latitude/longitude and the time.
     * 
     * @param coordinates the coordinates for which the absolute position 
     *        is adjusted.
     * @param position the position object to update.
     * @return the corresponding absolute position. 
     * @throws ConversionException if a conversion error occurs.
     */
    protected abstract AbsolutePosition positionOf(C coordinates,
            AbsolutePosition position);

    /**
     * Returns the OpenGIS coordinate system associated to this 
     * coordinate reference system.
     * 
     * @return the corresponding coordinate system. 
     */
    public abstract CoordinateSystem getCoordinateSystem();

    /////////////
    // OpenGIS //
    /////////////
    
    /**
     * OpenGIS&amp;reg; - Area for which the (coordinate) reference system is valid.
     *
     * @return coordinate reference system valid area, 
     *         or {@code null} (default) if not available.
     */
    public Extent getValidArea() {
        return null;
    }

    /**
     * OpenGIS&amp;reg; - Description of domain of usage, or limitations of usage,
     * for which this (coordinate) reference system object is valid.
     */
    public InternationalString getScope() {
        throw new UnsupportedOperationException();
    }

    /**
     * OpenGIS&amp;reg; - The primary name by which this object is identified.
     * 
     * @return an identifier holding the class name.
     */
    public ReferenceIdentifier getName() {
        throw new UnsupportedOperationException();
        //return new Name(CoordinateReferenceSystem.this.getClass().getName());
    }

    /**
     * OpenGIS&amp;reg; - An alternative name by which this object is identified.
     *
     * @return The aliases, or an empty collection if there is none.
     */
    public Collection&lt;GenericName&gt; getAlias() {
        throw new UnsupportedOperationException();
        //return EMPTY_SET;
    }

    /**
     * OpenGIS&amp;reg;  - An identifier which references elsewhere the object's defining information.
     * Alternatively an identifier by which this object can be referenced.
     *
     * @return This object identifiers, or an empty set if there is none.
     */
    public Set&lt;ReferenceIdentifier&gt; getIdentifiers() {
        throw new UnsupportedOperationException();
        //return EMPTY_SET;
    }

    /**
     * OpenGIS&amp;reg; - Comments on or information about this object, including 
     * data source information.
     * 
     * @return &lt;code&gt;null&lt;/code&gt; (default).
     */
    public InternationalString getRemarks() {
        return null;
    }

    /**
     * OpenGIS&amp;reg; - Returns a &lt;cite&gt;Well Known Text&lt;/cite&gt; (WKT)&lt;/A&gt; for 
     * this object. This operation may fails if an object is too complex for
     * the WKT format capability (for example an engineering CRS} with different
     * unit for each axis).
     *
     * @return The Well Know Text for this object.
     * @throws UnsupportedOperationException If this object can't be formatted 
     *         as WKT (default).
     */
    public String toWKT() throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    // Default coordinates axis.
    static class Axis implements CoordinateSystemAxis {

        private final Name _name;

        private final String _abbreviation;

        private final Unit&lt;?&gt; _unit;

        private final AxisDirection _direction;

        public Axis(final String name, String abbreviation, Unit&lt;?&gt; unit,
                AxisDirection direction) {
            _name = new Name(name);
            _abbreviation = abbreviation;
            _unit = unit;
            _direction = direction;
        }

        public final ReferenceIdentifier getName() {
            return _name;
        }

        public final String getAbbreviation() {
            return _abbreviation;
        }

        public final Unit&lt;?&gt; getUnit() {
            return _unit;
        }

        public final AxisDirection getDirection() {
            return _direction;
        }

        public Collection&lt;GenericName&gt; getAlias() {
            throw new UnsupportedOperationException();
            //return EMPTY_SET;
        }

        public Set&lt;ReferenceIdentifier&gt; getIdentifiers() {
            throw new UnsupportedOperationException();
            //return EMPTY_SET;
        }

        public InternationalString getRemarks() {
            throw new UnsupportedOperationException();
        }

        public String toWKT() throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }
        
        public RangeMeaning getRangeMeaning() {
            throw new UnsupportedOperationException();
        }

        public double getMinimumValue() {
            throw new UnsupportedOperationException();
        }
        
        public double getMaximumValue() {
            throw new UnsupportedOperationException();
        }
    }

    // Default coordinates axis.
    //Used to implement Identifier, it should now implement ReferenceIdentifier instead
    static class Name implements ReferenceIdentifier {
        final String _value;

        public Name(String value) {
            _value = value;
        }

        public String getCode() {
            return _value;
        }
        
        //Newer version of getCode() that was introduced with the move to ReferenceIdentifier
        public String getCodeSpace() {
            return _value;
        }

        public Citation getAuthority() {
            throw new UnsupportedOperationException();
        }

        public String getVersion() {
            throw new UnsupportedOperationException();
        }
    }

    static final FastSet&lt;Object&gt; EMPTY_SET = new FastSet&lt;Object&gt;();
}</pre></body></html>