text:
package org.apache.sis.referencing.factory;

import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogRecord;
import java.util.concurrent.atomic.AtomicReference;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.measure.unit.Unit;
import javax.measure.quantity.Angle;
import javax.measure.quantity.Length;
import javax.xml.bind.JAXBException;
import org.opengis.util.GenericName;
import org.opengis.util.FactoryException;
import org.opengis.util.InternationalString;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.extent.Extent;
import org.opengis.referencing.*;
import org.opengis.referencing.cs.*;
import org.opengis.referencing.crs.*;
import org.opengis.referencing.datum.*;
import org.opengis.referencing.operation.*;
import org.opengis.parameter.ParameterNotFoundException;
import org.apache.sis.referencing.cs.*;
import org.apache.sis.referencing.crs.*;
import org.apache.sis.referencing.datum.*;
import org.apache.sis.referencing.NamedIdentifier;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.AbstractReferenceSystem;
import org.apache.sis.referencing.AbstractIdentifiedObject;
import org.apache.sis.internal.metadata.ReferencingServices;
import org.apache.sis.internal.referencing.MergedProperties;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.internal.system.Loggers;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.util.collection.WeakHashSet;
import org.apache.sis.util.iso.AbstractFactory;
import org.apache.sis.util.resources.Messages;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.io.wkt.Parser;
import org.apache.sis.xml.XML;

/**
 * Creates {@linkplain org.apache.sis.referencing.crs.AbstractCRS Coordinate Reference System} (CRS) implementations,
 * with their {@linkplain org.apache.sis.referencing.cs.AbstractCS Coordinate System} (CS)
 * and {@linkplain org.apache.sis.referencing.datum.AbstractDatum Datum} components.
 * This factory serves two purposes:
 *
 *

 *
For users, allows the creation of complex objects that can not be created by the authority factories,
 *       without explicit dependency to Apache SIS (when using the GeoAPI interfaces implemented by this class).

 *
For providers, allows inversion of control by overriding methods in this class,
 *       then specifying the customized instance to other services that consume {@code CRSFactory} (for example
 *       authority factories or {@linkplain org.apache.sis.io.wkt.WKTFormat WKT parsers}).

 *

 *
 * This {@code GeodeticObjectFactory} class is not easy to use directly.
 * Users are encouraged to use an authority factory instead
 * (or the {@link org.apache.sis.referencing.CRS#forCode(String)} convenience method)
 * when the CRS object to construct can be identified by a code in the namespace of an authority (typically EPSG).
 *
 *
Object properties

 * Most factory methods expect a {@link Map Map<String,?>} argument, often followed by explicit arguments.
 * Unless otherwise noticed, information provided in the {@code properties} map are considered ignorable metadata
 * while information provided in explicit arguments have an impact on coordinate transformation results.
 *
 *
The following table lists the keys recognized by the {@code GeodeticObjectFactory} default implementation,
 * together with the type of values associated to those keys.
 * A value for the {@code "name"} key is mandatory for all objects, while all other properties are optional.
 * {@code GeodeticObjectFactory} methods ignore all unknown properties.

 *
 *

 *
Recognized properties (non exhaustive list)

 *

 *     Property name
 *     Value type
 *     Returned by
 *

 *

 *     {@value org.opengis.referencing.IdentifiedObject#NAME_KEY}
 *     {@link Identifier} or {@link String}
 *     {@link AbstractIdentifiedObject#getName()}
 *

 *

 *     {@value org.opengis.metadata.Identifier#AUTHORITY_KEY}
 *     {@link String} or {@link Citation}
 *     {@link NamedIdentifier#getAuthority()} on the {@linkplain AbstractIdentifiedObject#getName() name}
 *

 *

 *     {@value org.opengis.metadata.Identifier#CODE_KEY}
 *     {@link String}
 *     {@link NamedIdentifier#getCode()} on the {@linkplain AbstractIdentifiedObject#getName() name}
 *

 *

 *     {@value org.opengis.metadata.Identifier#CODESPACE_KEY}
 *     {@link String}
 *     {@link NamedIdentifier#getCodeSpace()} on the {@linkplain AbstractIdentifiedObject#getName() name}
 *

 *

 *     {@value org.opengis.metadata.Identifier#VERSION_KEY}
 *     {@link String}
 *     {@link NamedIdentifier#getVersion()} on the {@linkplain AbstractIdentifiedObject#getName() name}
 *

 *

 *     {@value org.opengis.metadata.Identifier#DESCRIPTION_KEY}
 *     {@link String}
 *     {@link NamedIdentifier#getDescription()} on the {@linkplain AbstractIdentifiedObject#getName() name}
 *

 *

 *     {@value org.opengis.referencing.IdentifiedObject#ALIAS_KEY}
 *     {@link GenericName} or {@link CharSequence} (optionally as array)
 *     {@link AbstractIdentifiedObject#getAlias()}
 *

 *

 *     {@value org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY}
 *     {@link Identifier} (optionally as array)
 *     {@link AbstractIdentifiedObject#getIdentifiers()}
 *

 *

 *     {@value org.opengis.referencing.ReferenceSystem#DOMAIN_OF_VALIDITY_KEY}
 *     {@link Extent}
 *     {@link AbstractReferenceSystem#getDomainOfValidity()}
 *

 *

 *     {@value org.opengis.referencing.ReferenceSystem#SCOPE_KEY}
 *     {@link String} or {@link InternationalString}
 *     {@link AbstractReferenceSystem#getScope()}
 *

 *

 *     {@value org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}
 *     {@link InternationalString} or {@link String}
 *     {@link AbstractDatum#getAnchorPoint()}
 *

 *

 *     {@value org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}
 *     {@link Date}
 *     {@link AbstractDatum#getRealizationEpoch()}
 *

 *

 *     {@value org.opengis.referencing.IdentifiedObject#REMARKS_KEY}
 *     {@link InternationalString} or {@link String}
 *     {@link AbstractIdentifiedObject#getRemarks()}
 *

 *

 *     {@value org.apache.sis.referencing.AbstractIdentifiedObject#DEPRECATED_KEY}
 *     {@link Boolean}
 *     {@link AbstractIdentifiedObject#isDeprecated()}
 *

 *

 *     {@value org.apache.sis.referencing.AbstractIdentifiedObject#LOCALE_KEY}
 *     {@link Locale}
 *     (none)
 *

 *

 *
 *
Localization

 * All localizable attributes like {@code "remarks"} may have a language and country code suffix.
 * For example the {@code "remarks_fr"} property stands for remarks in {@linkplain Locale#FRENCH French} and
 * the {@code "remarks_fr_CA"} property stands for remarks in {@linkplain Locale#CANADA_FRENCH French Canadian}.
 * They are convenience properties for building the {@code InternationalString} value.
 *
 *
The {@code "locale"} property applies only in case of exception for formatting the error message, and
 * is used only on a best effort basis. The locale is discarded after successful construction
 * since localizations are applied by the {@link InternationalString#toString(Locale)} method.

 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @author  Guilhem Legal (Geomatys)
 * @author  Johann Sorel (Geomatys)
 * @since   0.6
 * @version 0.7
 * @module
 */
public class GeodeticObjectFactory extends AbstractFactory implements CRSFactory, CSFactory, DatumFactory, Parser {
    /**
     * The logger to use for reporting object creations.
     */
    private static final Logger LOGGER = Logging.getLogger(Loggers.CRS_FACTORY);

    /**
     * The constructor for WKT parsers, fetched when first needed. The WKT parser is defined in the
     * same module than this class, so we will hopefully not have security issues.  But we have to
     * use reflection because the parser class is not yet public (because we do not want to commit
     * its API yet).
     */
    private static volatile Constructor<? extends Parser> parserConstructor;

    /**
     * The default properties, or an empty map if none. This map shall not change after construction in
     * order to allow usage without synchronization in multi-thread context. But we do not need to wrap
     * in a unmodifiable map since {@code GeodeticObjectFactory} does not provide public access to it.
     */
    private final Map<String,?> defaultProperties;

    /**
     * The math transform factory. Will be created only when first needed.
     * This is normally not needed by this factory, except when constructing derived and projected CRS.
     *
     * @see #getMathTransformFactory()
     */
    private volatile MathTransformFactory mtFactory;

    /**
     * Weak references to existing objects (CRS, CS, Datum, Ellipsoid or PrimeMeridian).
     * This set is used in order to return a pre-existing object instead of creating a new one.
     */
    private final WeakHashSet<AbstractIdentifiedObject> pool;

    /**
     * The Well Known Text parser for {@code CoordinateReferenceSystem} instances.
     * This parser is not thread-safe, so we need to prevent two threads from using the same instance in same time.
     */
    private final AtomicReference<Parser> parser;

    /**
     * Constructs a factory with no default properties.
     */
    public GeodeticObjectFactory() {
        this(null);
    }

    /**
     * Constructs a factory with the given default properties.
     * {@code GeodeticObjectFactory} will fallback on the map given to this constructor for any property
     * not present in the map provided to a {@code createFoo(Map<String,?>, …)} method.
     *
     * @param properties The default properties, or {@code null} if none.
     */
    public GeodeticObjectFactory(Map<String,?> properties) {
        if (properties == null || properties.isEmpty()) {
            properties = Collections.emptyMap();
        } else {
            properties = CollectionsExt.compact(new HashMap<String,Object>(properties));
        }
        defaultProperties = properties;
        pool = new WeakHashSet<>(AbstractIdentifiedObject.class);
        parser = new AtomicReference<>();
    }

    /**
     * Returns the union of the given {@code properties} map with the default properties given at
     * {@linkplain #GeodeticObjectFactory(Map) construction time}. Entries in the given properties
     * map have precedence, even if their {@linkplain java.util.Map.Entry#getValue() value} is {@code null}
     * (i.e. a null value "erase" the default property value).
     * Entries with null value after the union will be omitted.
     *
     *
This method is invoked by all {@code createFoo(Map<String,?>, …)} methods.

     *
     * @param  properties The user-supplied properties.
     * @return The union of the given properties with the default properties.
     */
    protected Map<String,?> complete(final Map<String,?> properties) {
        ArgumentChecks.ensureNonNull("properties", properties);
        return new MergedProperties(properties, defaultProperties) {
            /**
             * Handles the {@code "mtFactory"} key in a special way since this is normally not needed for
             * {@link GeodeticObjectFactory}, except when creating the SIS implementation of derived or
             * projected CRS (because of the way we implemented derived CRS, but this is specific to SIS).
             */
            @Override
            protected Object invisibleEntry(final Object key) {
                if (ReferencingServices.MT_FACTORY.equals(key)) {
                    return getMathTransformFactory();
                } else {
                    return super.invisibleEntry(key);
                }
            }
        };
    }

    /**
     * Returns the math transform factory for internal usage only.
     * The {@code MathTransformFactory} is normally not needed by {@code GeodeticObjectFactory},
     * except when constructing the Apache SIS implementation of derived and projected CRS.
     * For this reason, we will fetch this dependency only if really requested.
     */
    final MathTransformFactory getMathTransformFactory() {
        MathTransformFactory factory = mtFactory;
        if (factory == null) {
            mtFactory = factory = DefaultFactories.forBuildin(MathTransformFactory.class);
        }
        return factory;
    }

    /**
     * Returns a unique instance of the given object. If this method recycles an existing object,
     * then the existing instance is returned silently. Otherwise this method logs a message at
     * {@link Level#FINE} telling that a new object has been created.
     */
    private <T extends AbstractIdentifiedObject> T unique(final String caller, final T object) {
        final T c = pool.unique(object);
        if (c == object && LOGGER.isLoggable(Level.FINE)) {
            final String id = IdentifiedObjects.toString(IdentifiedObjects.getIdentifier(c, null));
            final LogRecord record = Messages.getResources(null).getLogRecord(Level.FINE,
                    (id != null) ? Messages.Keys.CreatedIdentifiedObject_3
                                 : Messages.Keys.CreatedNamedObject_2,
                    c.getInterface(), c.getName().getCode(), id);
            record.setSourceClassName(GeodeticObjectFactory.class.getCanonicalName());
            record.setSourceMethodName(caller);
            record.setLoggerName(LOGGER.getName());
            LOGGER.log(record);
        }
        return c;
    }

    /**
     * Creates a geocentric coordinate reference system from a {@linkplain CartesianCS Cartesian coordinate system}.
     * Geocentric CRS have their origin at the approximate centre of mass of the earth.
     * An {@linkplain #createGeocentricCRS(Map, GeodeticDatum, SphericalCS) alternate method} allows creation of the
     * same kind of CRS with spherical coordinate system instead than a Cartesian one.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *
{@link #createCartesianCS(Map, CoordinateSystemAxis, CoordinateSystemAxis, CoordinateSystemAxis)}

     *
One of:

     *
{@link #createEllipsoid(Map, double, double, Unit)}

     *
{@link #createFlattenedSphere(Map, double, double, Unit)}

     *

     *
{@link #createPrimeMeridian(Map, double, Unit)}

     *
{@link #createGeodeticDatum(Map, Ellipsoid, PrimeMeridian)}

     *

     *
     * The default implementation creates a {@link DefaultGeocentricCRS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  datum      The geodetic datum to use in created CRS.
     * @param  cs         The three-dimensional Cartesian coordinate system for the created CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see GeodeticAuthorityFactory#createGeocentricCRS(String)
     * @see DefaultGeocentricCRS#DefaultGeocentricCRS(Map, GeodeticDatum, CartesianCS)
     */
    @Override
    public GeocentricCRS createGeocentricCRS(final Map<String,?> properties,
            final GeodeticDatum datum, final CartesianCS cs) throws FactoryException
    {
        final DefaultGeocentricCRS crs;
        try {
            crs = new DefaultGeocentricCRS(complete(properties), datum, cs);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createGeocentricCRS", crs);
    }

    /**
     * Creates a three-dimensional Cartesian coordinate system from the given set of axis.
     * This coordinate system can be used with geocentric, engineering and derived CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultCartesianCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis (e.g. "Geocentric X").
     * @param  axis1 The second axis (e.g. "Geocentric Y").
     * @param  axis2 The third  axis (e.g. "Geocentric Z").
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultCartesianCS#DefaultCartesianCS(Map, CoordinateSystemAxis, CoordinateSystemAxis, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createCartesianCS(String)
     */
    @Override
    public CartesianCS createCartesianCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1,
            final CoordinateSystemAxis axis2) throws FactoryException
    {
        final DefaultCartesianCS cs;
        try {
            cs = new DefaultCartesianCS(complete(properties), axis0, axis1, axis2);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createCartesianCS", cs);
    }

    /**
     * Creates a geocentric coordinate reference system from a {@linkplain SphericalCS spherical coordinate system}.
     * Geocentric CRS have their origin at the approximate centre of mass of the earth.
     * An {@linkplain #createGeocentricCRS(Map, GeodeticDatum, CartesianCS) alternate method} allows creation of the
     * same kind of CRS with Cartesian coordinate system instead than a spherical one.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *
{@link #createSphericalCS(Map, CoordinateSystemAxis, CoordinateSystemAxis, CoordinateSystemAxis)}

     *
One of:

     *
{@link #createEllipsoid(Map, double, double, Unit)}

     *
{@link #createFlattenedSphere(Map, double, double, Unit)}

     *

     *
{@link #createPrimeMeridian(Map, double, Unit)}

     *
{@link #createGeodeticDatum(Map, Ellipsoid, PrimeMeridian)}

     *

     *
     * The default implementation creates a {@link DefaultGeocentricCRS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  datum      Geodetic datum to use in created CRS.
     * @param  cs         The spherical coordinate system for the created CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultGeocentricCRS#DefaultGeocentricCRS(Map, GeodeticDatum, SphericalCS)
     * @see GeodeticAuthorityFactory#createGeocentricCRS(String)
     */
    @Override
    public GeocentricCRS createGeocentricCRS(final Map<String,?> properties,
            final GeodeticDatum datum, final SphericalCS cs) throws FactoryException
    {
        final DefaultGeocentricCRS crs;
        try {
            crs = new DefaultGeocentricCRS(complete(properties), datum, cs);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createGeocentricCRS", crs);
    }

    /**
     * Creates a spherical coordinate system from the given set of axis.
     * This coordinate system can be used with geocentric, engineering and derived CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultSphericalCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis (e.g. "Spherical latitude").
     * @param  axis1 The second axis (e.g. "Spherical longitude").
     * @param  axis2 The third  axis (e.g. "Geocentric radius").
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultSphericalCS#DefaultSphericalCS(Map, CoordinateSystemAxis, CoordinateSystemAxis, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createSphericalCS(String)
     */
    @Override
    public SphericalCS createSphericalCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1,
            final CoordinateSystemAxis axis2) throws FactoryException
    {
        final DefaultSphericalCS cs;
        try {
            cs = new DefaultSphericalCS(complete(properties), axis0, axis1, axis2);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createSphericalCS", cs);
    }

    /**
     * Creates a geographic coordinate reference system. It can be (<var>latitude</var>, <var>longitude</var>)
     * or (<var>longitude</var>, <var>latitude</var>), optionally with an ellipsoidal height.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *
One of:

     *
{@link #createEllipsoidalCS(Map, CoordinateSystemAxis, CoordinateSystemAxis)}

     *
{@link #createEllipsoidalCS(Map, CoordinateSystemAxis, CoordinateSystemAxis, CoordinateSystemAxis)}

     *

     *
One of:

     *
{@link #createEllipsoid(Map, double, double, Unit)}

     *
{@link #createFlattenedSphere(Map, double, double, Unit)}

     *

     *
{@link #createPrimeMeridian(Map, double, Unit)}

     *
{@link #createGeodeticDatum(Map, Ellipsoid, PrimeMeridian)}

     *

     *
     * The default implementation creates a {@link DefaultGeographicCRS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  datum      Geodetic datum to use in created CRS.
     * @param  cs         The two- or three-dimensional ellipsoidal coordinate system for the created CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultGeographicCRS#DefaultGeographicCRS(Map, GeodeticDatum, EllipsoidalCS)
     * @see GeodeticAuthorityFactory#createGeographicCRS(String)
     */
    @Override
    public GeographicCRS createGeographicCRS(final Map<String,?> properties,
            final GeodeticDatum datum, final EllipsoidalCS cs) throws FactoryException
    {
        final DefaultGeographicCRS crs;
        try {
            crs = new DefaultGeographicCRS(complete(properties), datum, cs);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createGeographicCRS", crs);
    }

    /**
     * Creates geodetic datum from ellipsoid and (optionally) Bursa-Wolf parameters.
     * Geodetic datum defines the location and orientation of an ellipsoid that approximates the shape of the earth.
     * This datum can be used with geographic, geocentric and engineering CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
One of:

     *
{@link #createEllipsoid(Map, double, double, Unit)}

     *
{@link #createFlattenedSphere(Map, double, double, Unit)}

     *

     *
{@link #createPrimeMeridian(Map, double, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultGeodeticDatum} instance.
     *
     * @param  properties    Name and other properties to give to the new object.
     * @param  ellipsoid     The ellipsoid to use in new geodetic datum.
     * @param  primeMeridian The prime meridian to use in new geodetic datum.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultGeodeticDatum#DefaultGeodeticDatum(Map, Ellipsoid, PrimeMeridian)
     * @see GeodeticAuthorityFactory#createGeodeticDatum(String)
     */
    @Override
    public GeodeticDatum createGeodeticDatum(final Map<String,?> properties,
            final Ellipsoid ellipsoid, final PrimeMeridian primeMeridian) throws FactoryException
    {
        final DefaultGeodeticDatum datum;
        try {
            datum = new DefaultGeodeticDatum(complete(properties), ellipsoid, primeMeridian);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createGeodeticDatum", datum);
    }

    /**
     * Creates a prime meridian, relative to Greenwich.
     * Defines the origin from which longitude values are determined.
     *
     *
The default implementation creates a {@link DefaultPrimeMeridian} instance.

     *
     * @param  properties  Name and other properties to give to the new object.
     * @param  longitude   The longitude of prime meridian in supplied angular units East of Greenwich.
     * @param  angularUnit The angular units of longitude.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultPrimeMeridian#DefaultPrimeMeridian(Map, double, Unit)
     * @see GeodeticAuthorityFactory#createPrimeMeridian(String)
     */
    @Override
    public PrimeMeridian createPrimeMeridian(final Map<String,?> properties,
            final double longitude, final Unit<Angle> angularUnit) throws FactoryException
    {
        final DefaultPrimeMeridian meridian;
        try {
            meridian = new DefaultPrimeMeridian(complete(properties), longitude, angularUnit);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createPrimeMeridian", meridian);
    }

    /**
     * Creates an ellipsoidal coordinate system without ellipsoidal height.
     * It can be (<var>latitude</var>, <var>longitude</var>) or (<var>longitude</var>, <var>latitude</var>).
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultEllipsoidalCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis (e.g. "Geodetic latitude").
     * @param  axis1 The second axis (e.g. "Geodetic longitude").
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultEllipsoidalCS#DefaultEllipsoidalCS(Map, CoordinateSystemAxis, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createEllipsoidalCS(String)
     */
    @Override
    public EllipsoidalCS createEllipsoidalCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1) throws FactoryException
    {
        final DefaultEllipsoidalCS cs;
        try {
            cs = new DefaultEllipsoidalCS(complete(properties), axis0, axis1);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createEllipsoidalCS", cs);
    }

    /**
     * Creates an ellipsoidal coordinate system with ellipsoidal height.
     * It can be (<var>latitude</var>, <var>longitude</var>, <var>height</var>)
     * or (<var>longitude</var>, <var>latitude</var>, <var>height</var>).
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultEllipsoidalCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis (e.g. "Geodetic latitude").
     * @param  axis1 The second axis (e.g. "Geodetic longitude").
     * @param  axis2 The third  axis (e.g. "Ellipsoidal height").
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultEllipsoidalCS#DefaultEllipsoidalCS(Map, CoordinateSystemAxis, CoordinateSystemAxis, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createEllipsoidalCS(String)
     */
    @Override
    public EllipsoidalCS createEllipsoidalCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1,
            final CoordinateSystemAxis axis2) throws FactoryException
    {
        final DefaultEllipsoidalCS cs;
        try {
            cs = new DefaultEllipsoidalCS(complete(properties), axis0, axis1, axis2);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createEllipsoidalCS", cs);
    }

    /**
     * Creates an ellipsoid from semi-axis length values.
     * The default implementation creates a {@link DefaultEllipsoid} instance.
     *
     * @param  properties    Name and other properties to give to the new object.
     * @param  semiMajorAxis The equatorial radius in supplied linear units.
     * @param  semiMinorAxis The polar radius in supplied linear units.
     * @param  unit          The linear units of ellipsoid axes.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultEllipsoid#createEllipsoid(Map, double, double, Unit)
     * @see GeodeticAuthorityFactory#createEllipsoid(String)
     */
    @Override
    public Ellipsoid createEllipsoid(final Map<String,?> properties,
            final double semiMajorAxis, final double semiMinorAxis,
            final Unit<Length> unit) throws FactoryException
    {
        final DefaultEllipsoid ellipsoid;
        try {
            ellipsoid = DefaultEllipsoid.createEllipsoid(complete(properties), semiMajorAxis, semiMinorAxis, unit);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createEllipsoid", ellipsoid);
    }

    /**
     * Creates an ellipsoid from a major semi-axis length and inverse flattening.
     * The default implementation creates a {@link DefaultEllipsoid} instance.
     *
     * @param  properties        Name and other properties to give to the new object.
     * @param  semiMajorAxis     The equatorial radius in supplied linear units.
     * @param  inverseFlattening The eccentricity of ellipsoid.
     * @param  unit              The linear units of major axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultEllipsoid#createFlattenedSphere(Map, double, double, Unit)
     * @see GeodeticAuthorityFactory#createEllipsoid(String)
     */
    @Override
    public Ellipsoid createFlattenedSphere(final Map<String,?> properties,
            final double semiMajorAxis, final double inverseFlattening,
            final Unit<Length> unit) throws FactoryException
    {
        final DefaultEllipsoid ellipsoid;
        try {
            ellipsoid = DefaultEllipsoid.createFlattenedSphere(complete(properties), semiMajorAxis, inverseFlattening, unit);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createFlattenedSphere", ellipsoid);
    }

    /**
     * Creates a projected coordinate reference system from a conversion.
     * Projected CRS are used to approximate the shape of the earth on a planar surface in such a way
     * that the distortion that is inherent to the approximation is controlled and known.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *
{@link #createCartesianCS(Map, CoordinateSystemAxis, CoordinateSystemAxis)}

     *
{@link #createEllipsoidalCS(Map, CoordinateSystemAxis, CoordinateSystemAxis)}

     *
One of:

     *
{@link #createEllipsoid(Map, double, double, Unit)}

     *
{@link #createFlattenedSphere(Map, double, double, Unit)}

     *

     *
{@link #createPrimeMeridian(Map, double, Unit)}

     *
{@link #createGeodeticDatum(Map, Ellipsoid, PrimeMeridian)}

     *
{@link #createGeographicCRS(Map, GeodeticDatum, EllipsoidalCS)}

     *
{@link org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory#createDefiningConversion(Map, OperationMethod, ParameterValueGroup)}

     *

     *
     * The supplied {@code conversion} argument shall not includes the operation steps
     * for performing {@linkplain org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes unit
     * conversions and change of axis order} since those operations will be inferred by this constructor.
     *
     *
The default implementation creates a {@link DefaultProjectedCRS} instance.

     *
     * @param  properties Name and other properties to give to the new object.
     * @param  baseCRS    The geographic coordinate reference system to base projection on.
     * @param  conversion The defining conversion from a {@linkplain org.apache.sis.referencing.cs.AxesConvention#NORMALIZED
     *                    normalized} base to a normalized derived CRS.
     * @param  derivedCS  The coordinate system for the projected CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultProjectedCRS#DefaultProjectedCRS(Map, GeographicCRS, Conversion, CartesianCS)
     * @see GeodeticAuthorityFactory#createProjectedCRS(String)
     */
    @Override
    public ProjectedCRS createProjectedCRS(final Map<String,?> properties,
            final GeographicCRS baseCRS, final Conversion conversion,
            final CartesianCS derivedCS) throws FactoryException
    {
        final DefaultProjectedCRS crs;
        try {
            crs = new DefaultProjectedCRS(complete(properties), baseCRS, conversion, derivedCS);
        } catch (IllegalArgumentException exception) {
            final Throwable cause = exception.getCause();
            if (cause instanceof FactoryException) {
                throw (FactoryException) cause;         // Must be propagated for allowing caller to catch NoSuchIdentifierException.
            }
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createProjectedCRS", crs);
    }

    /**
     * Creates a two-dimensional Cartesian coordinate system from the given pair of axis.
     * This coordinate system can be used with projected, engineering and derived CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultCartesianCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis (e.g. "Easting").
     * @param  axis1 The second axis (e.g. "Northing").
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultCartesianCS#DefaultCartesianCS(Map, CoordinateSystemAxis, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createCartesianCS(String)
     */
    @Override
    public CartesianCS createCartesianCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1) throws FactoryException
    {
        final DefaultCartesianCS cs;
        try {
            cs = new DefaultCartesianCS(complete(properties), axis0, axis1);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createCartesianCS", cs);
    }

    /**
     * Creates a derived coordinate reference system from a conversion.
     * The derived CRS returned by this method may also implement the {@link GeodeticCRS}, {@link VerticalCRS},
     * {@link TemporalCRS} or {@link EngineeringCRS} interface depending on the type of the base CRS and the
     * coordinate system.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *
A {@code createFooCS(…)} method for Cartesian, spherical, ellipsoidal, vertical, temporal, linear, affine, polar, cylindrical or user-defined CS.

     *
An other {@code createFooCRS(…)} method for geocentric, geographic, vertical, temporal or engineering CRS.

     *
{@link org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory#createDefiningConversion(Map, OperationMethod, ParameterValueGroup)}

     *

     *
     * The supplied {@code conversion} argument shall not includes the operation steps
     * for performing {@linkplain org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes unit
     * conversions and change of axis order} since those operations will be inferred by this constructor.
     *
     *
The default implementation creates a {@link DefaultDerivedCRS} instance.

     *
     * @param  properties Name and other properties to give to the new object.
     * @param  baseCRS    The coordinate reference system to base projection on. Shall be an instance of {@link SingleCRS}.
     * @param  conversion The defining conversion from a {@linkplain org.apache.sis.referencing.cs.AxesConvention#NORMALIZED
     *                    normalized} base to a normalized derived CRS.
     * @param  derivedCS  The coordinate system for the derived CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultDerivedCRS#create(Map, SingleCRS, Conversion, CoordinateSystem)
     * @see GeodeticAuthorityFactory#createDerivedCRS(String)
     */
    @Override
    public DerivedCRS createDerivedCRS(final Map<String,?> properties,
            final CoordinateReferenceSystem baseCRS, final Conversion conversion,
            final CoordinateSystem derivedCS) throws FactoryException
    {
        ArgumentChecks.ensureCanCast("baseCRS", SingleCRS.class, baseCRS);
        final DefaultDerivedCRS crs;
        try {
            crs = DefaultDerivedCRS.create(complete(properties), (SingleCRS) baseCRS, conversion, derivedCS);
        } catch (IllegalArgumentException exception) {
            final Throwable cause = exception.getCause();
            if (cause instanceof FactoryException) {
                throw (FactoryException) cause;         // Must be propagated for allowing caller to catch NoSuchIdentifierException.
            }
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createDerivedCRS", crs);
    }

    /**
     * Creates a vertical coordinate reference system.
     * Vertical CRSs make use of the direction of gravity to define the concept of height or depth,
     * but the relationship with gravity may not be straightforward.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *
{@link #createVerticalCS(Map, CoordinateSystemAxis)}

     *
{@link #createVerticalDatum(Map, VerticalDatumType)}

     *

     *
     * The default implementation creates a {@link DefaultVerticalCRS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  datum      The vertical datum to use in created CRS.
     * @param  cs         The vertical coordinate system for the created CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultVerticalCRS#DefaultVerticalCRS(Map, VerticalDatum, VerticalCS)
     * @see GeodeticAuthorityFactory#createVerticalCRS(String)
     */
    @Override
    public VerticalCRS createVerticalCRS(final Map<String,?> properties,
            final VerticalDatum datum, final VerticalCS cs) throws FactoryException
    {
        final DefaultVerticalCRS crs;
        try {
            crs = new DefaultVerticalCRS(complete(properties), datum, cs);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createVerticalCRS", crs);
    }

    /**
     * Creates a vertical datum from an enumerated type value.
     * The default implementation creates a {@link DefaultVerticalDatum} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  type       The type of this vertical datum (often geoidal).
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultVerticalDatum#DefaultVerticalDatum(Map, VerticalDatumType)
     * @see GeodeticAuthorityFactory#createVerticalDatum(String)
     */
    @Override
    public VerticalDatum createVerticalDatum(final Map<String,?> properties,
            final VerticalDatumType type) throws FactoryException
    {
        final DefaultVerticalDatum datum;
        try {
            datum = new DefaultVerticalDatum(complete(properties), type);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createVerticalDatum", datum);
    }

    /**
     * Creates a vertical coordinate system.
     * This coordinate system can be used with vertical and derived CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultVerticalCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis The single axis (e.g. "height" or "depth").
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultVerticalCS#DefaultVerticalCS(Map, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createVerticalCS(String)
     */
    @Override
    public VerticalCS createVerticalCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis) throws FactoryException
    {
        final DefaultVerticalCS cs;
        try {
            cs = new DefaultVerticalCS(complete(properties), axis);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createVerticalCS", cs);
    }

    /**
     * Creates a temporal coordinate reference system.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *
{@link #createTimeCS(Map, CoordinateSystemAxis)}

     *
{@link #createTemporalDatum(Map, Date)}

     *

     *
     * The default implementation creates a {@link DefaultTemporalCRS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  datum      The temporal datum to use in created CRS.
     * @param  cs         The temporal coordinate system for the created CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultTemporalCRS#DefaultTemporalCRS(Map, TemporalDatum, TimeCS)
     * @see GeodeticAuthorityFactory#createTemporalCRS(String)
     */
    @Override
    public TemporalCRS createTemporalCRS(final Map<String,?> properties,
            final TemporalDatum datum, final TimeCS cs) throws FactoryException
    {
        final DefaultTemporalCRS crs;
        try {
            crs = new DefaultTemporalCRS(complete(properties), datum, cs);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createTemporalCRS", crs);
    }

    /**
     * Creates a temporal datum from an enumerated type value.
     * The default implementation creates a {@link DefaultTemporalDatum} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  origin     The date and time origin of this temporal datum.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultTemporalDatum#DefaultTemporalDatum(Map, Date)
     * @see GeodeticAuthorityFactory#createTemporalDatum(String)
     */
    @Override
    public TemporalDatum createTemporalDatum(final Map<String,?> properties,
            final Date origin) throws FactoryException
    {
        final DefaultTemporalDatum datum;
        try {
            datum = new DefaultTemporalDatum(complete(properties), origin);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createTemporalDatum", datum);
    }

    /**
     * Creates a temporal coordinate system.
     * This coordinate system can be used with temporal and derived CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultTimeCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis The single axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultTimeCS#DefaultTimeCS(Map, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createTimeCS(String)
     */
    @Override
    public TimeCS createTimeCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis) throws FactoryException
    {
        final DefaultTimeCS cs;
        try {
            cs = new DefaultTimeCS(complete(properties), axis);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createTimeCS", cs);
    }

    /**
     * Creates a parametric coordinate reference system.
     * Parametric CRS can be used for physical properties or functions that vary monotonically with height.
     * A typical example is the pressure in meteorological applications.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *
{@link #createParametricCS(Map, CoordinateSystemAxis)}

     *
{@link #createParametricDatum(Map)}

     *

     *
     * The default implementation creates a {@link DefaultParametricCRS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  datum      The parametric datum to use in created CRS.
     * @param  cs         The parametric coordinate system for the created CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultParametricCRS#DefaultParametricCRS(Map, ParametricDatum, ParametricCS)
     * @see GeodeticAuthorityFactory#createParametricCRS(String)
     */
    @Override
    public ParametricCRS createParametricCRS(final Map<String,?> properties,
            final ParametricDatum datum, final ParametricCS cs) throws FactoryException
    {
        final DefaultParametricCRS crs;
        try {
            crs = new DefaultParametricCRS(complete(properties), datum, cs);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createParametricCRS", crs);
    }

    /**
     * Creates a parametric datum.
     * The default implementation creates a {@link DefaultParametricDatum} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultParametricDatum#DefaultParametricDatum(Map)
     * @see GeodeticAuthorityFactory#createParametricDatum(String)
     */
    @Override
    public ParametricDatum createParametricDatum(final Map<String,?> properties)
            throws FactoryException
    {
        final DefaultParametricDatum datum;
        try {
            datum = new DefaultParametricDatum(complete(properties));
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createParametricDatum", datum);
    }

    /**
     * Creates a parametric coordinate system.
     * This coordinate system can be used only with parametric CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultParametricCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis The single axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultParametricCS#DefaultParametricCS(Map, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createParametricCS(String)
     */
    @Override
    public ParametricCS createParametricCS(Map<String, ?> properties, CoordinateSystemAxis axis) throws FactoryException {
        final DefaultParametricCS cs;
        try {
            cs = new DefaultParametricCS(complete(properties), axis);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createParametricCS", cs);
    }

    /**
     * Creates a compound coordinate reference system from an ordered list of {@code CoordinateReferenceSystem} objects.
     * Apache SIS puts no restriction on the components that can be used in a compound CRS.
     * However for better inter-operability, users are encouraged to follow the order mandated by ISO 19162:
     *
     *

     *
A mandatory horizontal CRS (only one of two-dimensional {@code GeographicCRS} or {@code ProjectedCRS} or {@code EngineeringCRS}).

     *
Optionally followed by a {@code VerticalCRS} or a {@code ParametricCRS} (but not both).

     *
Optionally followed by a {@code TemporalCRS}.

     *

     *
     * The default implementation creates a {@link DefaultCompoundCRS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  elements   Ordered array of {@code CoordinateReferenceSystem} objects.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultCompoundCRS#DefaultCompoundCRS(Map, CoordinateReferenceSystem...)
     * @see GeodeticAuthorityFactory#createCompoundCRS(String)
     */
    @Override
    public CompoundCRS createCompoundCRS(final Map<String,?> properties,
            final CoordinateReferenceSystem... elements) throws FactoryException
    {
        final DefaultCompoundCRS crs;
        try {
            crs = new DefaultCompoundCRS(complete(properties), elements);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createCompoundCRS", crs);
    }

    /**
     * Creates an image coordinate reference system.
     * The default implementation creates a {@link DefaultImageCRS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  datum      The image datum to use in created CRS.
     * @param  cs         The Cartesian or oblique Cartesian coordinate system for the created CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultImageCRS#DefaultImageCRS(Map, ImageDatum, AffineCS)
     * @see GeodeticAuthorityFactory#createImageCRS(String)
     */
    @Override
    public ImageCRS createImageCRS(final Map<String,?> properties,
            final ImageDatum datum, final AffineCS cs) throws FactoryException
    {
        final DefaultImageCRS crs;
        try {
            crs = new DefaultImageCRS(complete(properties), datum, cs);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createImageCRS", crs);
    }

    /**
     * Creates an image datum.
     * The default implementation creates a {@link DefaultImageDatum} instance.
     *
     * @param  properties  Name and other properties to give to the new object.
     * @param  pixelInCell Specification of the way the image grid is associated with the image data attributes.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultImageDatum#DefaultImageDatum(Map, PixelInCell)
     * @see GeodeticAuthorityFactory#createImageDatum(String)
     */
    @Override
    public ImageDatum createImageDatum(final Map<String,?> properties,
            final PixelInCell pixelInCell) throws FactoryException
    {
        final DefaultImageDatum datum;
        try {
            datum = new DefaultImageDatum(complete(properties), pixelInCell);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createImageDatum", datum);
    }

    /**
     * Creates a two-dimensional affine coordinate system from the given pair of axis.
     * This coordinate system can be used with image and engineering CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultAffineCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis.
     * @param  axis1 The second axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultAffineCS#DefaultAffineCS(Map, CoordinateSystemAxis, CoordinateSystemAxis)
     */
    @Override
    public AffineCS createAffineCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1) throws FactoryException
    {
        final DefaultAffineCS cs;
        try {
            cs = new DefaultAffineCS(complete(properties), axis0, axis1);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createAffineCS", cs);
    }

    /**
     * Creates a engineering coordinate reference system.
     * Engineering CRS can be divided into two broad categories:
     *
     *

     *
earth-fixed systems applied to engineering activities on or near the surface of the earth;

     *
CRSs on moving platforms such as road vehicles, vessels, aircraft, or spacecraft.

     *

     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *
A {@code createFooCS(…)} method for Cartesian, spherical, linear, affine, polar, cylindrical or user-defined CS.

     *
{@link #createEngineeringDatum(Map)}

     *

     *
     * The default implementation creates a {@link DefaultEngineeringCRS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  datum      The engineering datum to use in created CRS.
     * @param  cs         The coordinate system for the created CRS.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultEngineeringCRS#DefaultEngineeringCRS(Map, EngineeringDatum, CoordinateSystem)
     * @see GeodeticAuthorityFactory#createEngineeringCRS(String)
     */
    @Override
    public EngineeringCRS createEngineeringCRS(final Map<String,?> properties,
            final EngineeringDatum datum, final CoordinateSystem cs) throws FactoryException
    {
        final DefaultEngineeringCRS crs;
        try {
            crs = new DefaultEngineeringCRS(complete(properties), datum, cs);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createEngineeringCRS", crs);
    }

    /**
     * Creates an engineering datum.
     * The default implementation creates a {@link DefaultEngineeringDatum} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultEngineeringDatum#DefaultEngineeringDatum(Map)
     * @see GeodeticAuthorityFactory#createEngineeringDatum(String)
     */
    @Override
    public EngineeringDatum createEngineeringDatum(final Map<String,?> properties)
            throws FactoryException
    {
        final DefaultEngineeringDatum datum;
        try {
            datum = new DefaultEngineeringDatum(complete(properties));
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createEngineeringDatum", datum);
    }

    /**
     * Creates a three-dimensional affine coordinate system from the given set of axis.
     * This coordinate system can be used with engineering CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultAffineCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis.
     * @param  axis1 The second axis.
     * @param  axis2 The third  axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultAffineCS#DefaultAffineCS(Map, CoordinateSystemAxis, CoordinateSystemAxis, CoordinateSystemAxis)
     */
    @Override
    public AffineCS createAffineCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1,
            final CoordinateSystemAxis axis2) throws FactoryException
    {
        final DefaultAffineCS cs;
        try {
            cs = new DefaultAffineCS(complete(properties), axis0, axis1, axis2);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createAffineCS", cs);
    }

    /**
     * Creates a cylindrical coordinate system from the given set of axis.
     * This coordinate system can be used with engineering CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultCylindricalCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis.
     * @param  axis1 The second axis.
     * @param  axis2 The third  axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultCylindricalCS#DefaultCylindricalCS(Map, CoordinateSystemAxis, CoordinateSystemAxis, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createCylindricalCS(String)
     */
    @Override
    public CylindricalCS createCylindricalCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1,
            final CoordinateSystemAxis axis2) throws FactoryException
    {
        final DefaultCylindricalCS cs;
        try {
            cs = new DefaultCylindricalCS(complete(properties), axis0, axis1, axis2);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createCylindricalCS", cs);
    }

    /**
     * Creates a polar coordinate system from the given pair of axis.
     * This coordinate system can be used with engineering CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultPolarCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis.
     * @param  axis1 The second axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultPolarCS#DefaultPolarCS(Map, CoordinateSystemAxis, CoordinateSystemAxis)
     * @see GeodeticAuthorityFactory#createPolarCS(String)
     */
    @Override
    public PolarCS createPolarCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1) throws FactoryException
    {
        final DefaultPolarCS cs;
        try {
            cs = new DefaultPolarCS(complete(properties), axis0, axis1);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createPolarCS", cs);
    }

    /**
     * Creates a linear coordinate system.
     * This coordinate system can be used with engineering CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultLinearCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis The single axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultLinearCS#DefaultLinearCS(Map, CoordinateSystemAxis)
     */
    @Override
    public LinearCS createLinearCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis) throws FactoryException
    {
        final DefaultLinearCS cs;
        try {
            cs = new DefaultLinearCS(complete(properties), axis);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createLinearCS", cs);
    }

    /**
     * Creates a two-dimensional user defined coordinate system from the given pair of axis.
     * This coordinate system can be used with engineering CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultUserDefinedCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis.
     * @param  axis1 The second axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultUserDefinedCS#DefaultUserDefinedCS(Map, CoordinateSystemAxis, CoordinateSystemAxis)
     */
    @Override
    public UserDefinedCS createUserDefinedCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1) throws FactoryException
    {
        final DefaultUserDefinedCS cs;
        try {
            cs = new DefaultUserDefinedCS(complete(properties), axis0, axis1);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createUserDefinedCS", cs);
    }

    /**
     * Creates a three-dimensional user defined coordinate system from the given set of axis.
     * This coordinate system can be used with engineering CRS.
     *
     *
Dependencies:
     * the components needed by this method can be created by the following methods:
     *

     *
{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}

     *

     *
     * The default implementation creates a {@link DefaultUserDefinedCS} instance.
     *
     * @param  properties Name and other properties to give to the new object.
     * @param  axis0 The first  axis.
     * @param  axis1 The second axis.
     * @param  axis2 The third  axis.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultUserDefinedCS#DefaultUserDefinedCS(Map, CoordinateSystemAxis, CoordinateSystemAxis, CoordinateSystemAxis)
     */
    @Override
    public UserDefinedCS createUserDefinedCS(final Map<String,?> properties,
            final CoordinateSystemAxis axis0,
            final CoordinateSystemAxis axis1,
            final CoordinateSystemAxis axis2) throws FactoryException
    {
        final DefaultUserDefinedCS cs;
        try {
            cs = new DefaultUserDefinedCS(complete(properties), axis0, axis1, axis2);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createUserDefinedCS", cs);
    }

    /**
     * Creates a coordinate system axis from an abbreviation and a unit.
     * Note that the axis name is constrained by ISO 19111 depending on the coordinate reference system type.
     * See the GeoAPI {@link CoordinateSystemAxis} javadoc for more information.
     *
     *
The default implementation creates a {@link DefaultCoordinateSystemAxis} instance.

     *
     * @param  properties   Name and other properties to give to the new object.
     * @param  abbreviation The coordinate axis abbreviation.
     * @param  direction    The axis direction.
     * @param  unit         The coordinate axis unit.
     * @throws FactoryException if the object creation failed.
     *
     * @see DefaultCoordinateSystemAxis#DefaultCoordinateSystemAxis(Map, String, AxisDirection, Unit)
     * @see GeodeticAuthorityFactory#createCoordinateSystemAxis(String)
     */
    @Override
    public CoordinateSystemAxis createCoordinateSystemAxis(final Map<String,?> properties,
            final String abbreviation, final AxisDirection direction,
            final Unit<?> unit) throws FactoryException
    {
        final DefaultCoordinateSystemAxis axis;
        try {
            axis = new DefaultCoordinateSystemAxis(complete(properties), abbreviation, direction, unit);
        } catch (IllegalArgumentException exception) {
            throw new InvalidGeodeticParameterException(exception);
        }
        return unique("createCoordinateSystemAxis", axis);
    }

    /**
     * Creates a coordinate reference system object from a XML string.
     * Note that the given argument is the XML document itself,
     * not a URL to a XML document.
     *
     *
The default implementation delegates to {@link XML#unmarshal(String)}

     *
     * @param  xml Coordinate reference system encoded in XML format.
     * @throws FactoryException if the object creation failed.
     *
     * @see XML#unmarshal(String)
     * @see org.apache.sis.referencing.CRS#fromXML(String)
     */
    @Override
    public CoordinateReferenceSystem createFromXML(final String xml) throws FactoryException {
        final Object object;
        try {
            object = XML.unmarshal(xml);
        } catch (JAXBException e) {
            throw new FactoryException(e.getLocalizedMessage(), e);
        }
        if (object instanceof CoordinateReferenceSystem) {
            return (CoordinateReferenceSystem) object;
        } else {
            throw new FactoryException(Errors.getResources(defaultProperties).getString(
                    Errors.Keys.IllegalClass_2, CoordinateReferenceSystem.class, object.getClass()));
        }
    }

    /**
     * Creates a Coordinate Reference System object from a Well Known Text (WKT).
     * This method understands both version 1 (a.k.a. OGC 01-009) and version 2 (a.k.a. ISO 19162)
     * of the WKT format.
     *
     *
Example: below is a slightly simplified WKT 2 string for a Mercator projection.
     * For making this example smaller, some optional {@code UNIT[…]} and {@code ORDER[…]} elements have been omitted.
     *
     * {@preformat wkt
     *   ProjectedCRS["SIRGAS 2000 / Brazil Mercator",
     *     BaseGeodCRS["SIRGAS 2000",
     *       Datum["Sistema de Referencia Geocentrico para las Americas 2000",
     *         Ellipsoid["GRS 1980", 6378137, 298.257222101]]],
     *     Conversion["Petrobras Mercator",
     *       Method["Mercator (variant B)", Id["EPSG",9805]],
     *       Parameter["Latitude of 1st standard parallel", -2],
     *       Parameter["Longitude of natural origin", -43],
     *       Parameter["False easting", 5000000],
     *       Parameter["False northing", 10000000]],
     *     CS[cartesian,2],
     *       Axis["easting (E)", east],
     *       Axis["northing (N)", north],
     *       LengthUnit["metre", 1],
     *     Id["EPSG",5641]]
     * }
     *

     *
     *
Usage and performance considerations

     * The default implementation uses a shared instance of {@link org.apache.sis.io.wkt.WKTFormat}
     * with the addition of thread-safety. This is okay for occasional use,
     * but is sub-optimal if this method is extensively used in a multi-thread environment.
     * Furthermore this method offers no control on the WKT {@linkplain org.apache.sis.io.wkt.Convention conventions}
     * in use and on the handling of {@linkplain org.apache.sis.io.wkt.Warnings warnings}.
     * Applications which need to parse a large amount of WKT strings should consider to use
     * the {@link org.apache.sis.io.wkt.WKTFormat} class instead than this method.
     *
     * @param  text Coordinate system encoded in Well-Known Text format (version 1 or 2).
     * @throws FactoryException if the object creation failed.
     *
     * @see org.apache.sis.io.wkt
     * @see org.apache.sis.referencing.CRS#fromWKT(String)
     * @see WKT 2 specification
     * @see Legacy WKT 1
     */
    @Override
    public CoordinateReferenceSystem createFromWKT(final String text) throws FactoryException {
        Parser p = parser.getAndSet(null);
        if (p == null) try {
            Constructor<? extends Parser> c = parserConstructor;
            if (c == null) {
                c = Class.forName("org.apache.sis.io.wkt.GeodeticObjectParser").asSubclass(Parser.class)
                         .getConstructor(Map.class, ObjectFactory.class, MathTransformFactory.class);
                final Constructor<?> cp = c;     // For allowing use in inner class or lambda expression.
                AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
                    cp.setAccessible(true);
                    return null;
                });
                parserConstructor = c;
            }
            p = c.newInstance(defaultProperties, this, getMathTransformFactory());
        } catch (ReflectiveOperationException e) {
            throw new FactoryException(e);
        }
        final Object object;
        try {
            object = p.createFromWKT(text);
        } catch (FactoryException e) {
            /*
             * In the case of map projection, the parsing may fail because a projection parameter is not known to SIS.
             * If this happen, replace the generic exception thrown be the parser (which is FactoryException) by a
             * more specific one. Note that InvalidGeodeticParameterException is defined only in this sis-referencing
             * module, so we could not throw it from the sis-metadata module that contain the parser.
             */
            Throwable cause = e.getCause();
            while (cause != null) {
                if (cause instanceof ParameterNotFoundException) {
                    throw new InvalidGeodeticParameterException(e.getMessage(), cause);     // More accurate exception.
                }
                cause = cause.getCause();
            }
            throw e;
        }
        parser.set(p);
        if (object instanceof CoordinateReferenceSystem) {
            return (CoordinateReferenceSystem) object;
        } else {
            throw new FactoryException(Errors.getResources(defaultProperties).getString(
                    Errors.Keys.IllegalClass_2, CoordinateReferenceSystem.class, object.getClass()));
        }
    }
}


text:
module.exports = function(kernelP) {
  return (function() {
    var Utils = require('../../utils.js');

    var Model = require('../Model')();

    var gKernelP = kernelP;

    /**
     * @classdesc
     * Model fitted by {@link module:eclairjs/ml/clustering.LDA}.
     *
     * @class
     * @extends module:eclairjs/ml.Model
     * @memberof module:eclairjs/ml/clustering
     */
    function LDAModel() {
      Utils.handleConstructor(this, arguments, gKernelP);
    }

    LDAModel.prototype = Object.create(Model.prototype);

    LDAModel.prototype.constructor = LDAModel;

    /**
     * The features for LDA should be a {@link Vector} representing the word counts in a document.
     * The vector should be of length vocabSize, with counts for each term (word).
     * @param {string} value
     * @returns {module:eclairjs/mllib/clustering.LDAModel}
     */
    LDAModel.prototype.setFeaturesCol = function(value) {
      var args = {
        target: this,
        method: 'setFeaturesCol',
        args: Utils.wrapArguments(arguments),
        returnType: LDAModel
      };

      return Utils.generate(args);
    };

    /**
     * @param {number} value
     * @returns {module:eclairjs/mllib/clustering.LDAModel}
     */
    LDAModel.prototype.setSeed = function(value) {
      var args = {
        target: this,
        method: 'setSeed',
        args: Utils.wrapArguments(arguments),
        returnType: LDAModel
      };

      return Utils.generate(args);
    };

    /**
     * Transforms the input dataset.
     *
     * WARNING: If this model is an instance of [[DistributedLDAModel]] (produced when {@link optimizer}
     *          is set to "em"), this involves collecting a large {@link topicsMatrix} to the driver.
     *          This implementation may be changed in the future.
     * @param {module:eclairjs/sql.Dataset} dataset
     * @returns {module:eclairjs/sql.Dataset}
     */
    LDAModel.prototype.transform = function(dataset) {
      var Dataset = require('../../sql/Dataset');

      var args = {
        target: this,
        method: 'transform',
        args: Utils.wrapArguments(arguments),
        returnType: Dataset
      };

      return Utils.generate(args);
    };

    /**
     * @param {module:eclairjs/sql/types.StructType} schema
     * @returns {module:eclairjs/sql/types.StructType}
     */
    LDAModel.prototype.transformSchema = function(schema) {
      var StructType = require('../../sql/types/StructType')();

      var args = {
        target: this,
        method: 'transformSchema',
        args: Utils.wrapArguments(arguments),
        returnType: StructType
      };

      return Utils.generate(args);
    };

    /**
     * Value for {@link docConcentration} estimated from data.
     * If Online LDA was used and {@link optimizeDocConcentration} was set to false,
     * then this returns the fixed (given) value for the {@link docConcentration} parameter.
     * @returns {module:eclairjs/mllib/linalg.Vector}
     */
    LDAModel.prototype.estimatedDocConcentration = function() {
      var Vector = require('../../mllib/linalg/Vector');

      var args = {
        target: this,
        method: 'estimatedDocConcentration',
        args: Utils.wrapArguments(arguments),
        returnType: Vector
      };

      return Utils.generate(args);
    };

    /**
     * Inferred topics, where each topic is represented by a distribution over terms.
     * This is a matrix of size vocabSize x k, where each column is a topic.
     * No guarantees are given about the ordering of the topics.
     *
     * WARNING: If this model is actually a {@link DistributedLDAModel} instance produced by
     *          the Expectation-Maximization ("em") {@link optimizer}, then this method could involve
     *          collecting a large amount of data to the driver (on the order of vocabSize x k).
     * @returns {module:eclairjs/mllib/linalg.Matrix}
     */
    LDAModel.prototype.topicsMatrix = function() {
      var Matrix = require('../../mllib/linalg/Matrix');

      var args = {
        target: this,
        method: 'topicsMatrix',
        args: Utils.wrapArguments(arguments),
        returnType: Matrix
      };

      return Utils.generate(args);
    };

    /**
     *  Indicates whether this instance is of type {@link DistributedLDAModel}
     * @returns {Promise.<boolean>}
     */
    LDAModel.prototype.isDistributed = function() {
      var args = {
        target: this,
        method: 'isDistributed',
        args: Utils.wrapArguments(arguments),
        returnType: Boolean
      };

      return Utils.generate(args);
    };

    /**
     * Calculates a lower bound on the log likelihood of the entire corpus.
     *
     * See Equation (16) in the Online LDA paper (Hoffman et al., 2010).
     *
     * WARNING: If this model is an instance of [[DistributedLDAModel]] (produced when {@link optimizer}
     *          is set to "em"), this involves collecting a large {@link topicsMatrix} to the driver.
     *          This implementation may be changed in the future.
     *
     * @param {module:eclairjs/sql.Dataset} dataset   test corpus to use for calculating log likelihood
     * @returns {Promise.<number>}  variational lower bound on the log likelihood of the entire corpus
     */
    LDAModel.prototype.logLikelihood = function(dataset) {
      var args = {
        target: this,
        method: 'logLikelihood',
        args: Utils.wrapArguments(arguments),
        returnType: Number
      };

      return Utils.generate(args);
    };

    /**
     * Calculate an upper bound bound on perplexity.  (Lower is better.)
     * See Equation (16) in the Online LDA paper (Hoffman et al., 2010).
     *
     * WARNING: If this model is an instance of [[DistributedLDAModel]] (produced when {@link optimizer}
     *          is set to "em"), this involves collecting a large {@link topicsMatrix} to the driver.
     *          This implementation may be changed in the future.
     *
     * @param {module:eclairjs/sql.Dataset} dataset  test corpus to use for calculating perplexity
     * @returns {Promise.<number>}  Variational upper bound on log perplexity per token.
     */
    LDAModel.prototype.logPerplexity = function(dataset) {
      var args = {
        target: this,
        method: 'logPerplexity',
        args: Utils.wrapArguments(arguments),
        returnType: Number
      };

      return Utils.generate(args);
    };

    /**
     * Return the topics described by their top-weighted terms.
     *
     * @param {number} [maxTermsPerTopic]   Maximum number of terms to collect for each topic.
     *                          Default value of 10.
     *           - "topic": IntegerType: topic index
     *           - "termIndices": ArrayType(IntegerType): term indices, sorted in order of decreasing
     *                            term importance
     *           - "termWeights": ArrayType(DoubleType): corresponding sorted term weights
     * @returns {module:eclairjs/sql.Dataset}   Local Dataset with one topic per Row, with columns:
     */
    LDAModel.prototype.describeTopics = function(maxTermsPerTopic) {
      var Dataset = require('../../sql/Dataset');

      var args = {
        target: this,
        method: 'describeTopics',
        args: Utils.wrapArguments(arguments),
        returnType: Dataset
      };

      return Utils.generate(args);
    };

    LDAModel.moduleLocation = '/ml/clustering/LDAModel';

    return LDAModel;
  })();
};

redpajama_set_name: RedPajamaGithub


text:
'use strict';

var CountryHandler = require('../handlers/country');
var country = new CountryHandler(require('../services/country'));
var Router = require('express').Router;

module.exports = function (app) {
    app.route('/countries')
        .get(country.getAll.bind(country));
};


text:
pub mod problem1;
pub mod problem2;
pub mod problem3;
pub mod problem4;

mod tests_provided;
mod tests_student;


text:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
import selenium.webdriver.chrome.service as service
import inspect
import time
import imp
import os
from colorama import deinit
MODULE_EXTENSIONS = ('.py', '.pyc', '.pyo')

def package_contents(package_name):
    file, pathname, description = imp.find_module(package_name)
    if file:
        raise ImportError('Not a package: %r', package_name)
    # Use a set because some may be both source and compiled.
    return set([os.path.splitext(module)[0]
        for module in os.listdir(pathname)
        if module.endswith(MODULE_EXTENSIONS)])

def run_all():
    print "Start running tests\n"
    modules = package_contents("pmtests")

    # Runs all tests on import
    for module in modules:
        __import__("pmtests." + module)

def run():
    #from pmtests.postman_tests_broadcasts import PostmanTestsBroadcasts
    from pmtests.postman_tests_helpers import PostmanTestsHelpers

def main():
    run_all()
    #run()
    deinit()

if __name__ == "__main__":
    main()


text:
(function($) {
  var beautify = require('js-beautify');

  $.fn.beautify = function(options) {
    options = options || {};

    return this.each(function() {
      var beautified = beautify($(this).text().trim(), options);
      $(this).text(beautified);
    });
  };
}(window.$));


text:
import './embedded.html';
import './favicon.ico';
import './index.html';
require('mol-plugin-ui/skin/light.scss');
export * from './app';


text:
dotfiles
========

Configuration files for various software


text:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/fNewContainer"
    tools:context=".NewGiftActivity">

</FrameLayout>


text:
using System;
using System.Collections.Generic;
using System.Linq;
using NJsonSchema;
using NJsonSchema.CodeGeneration;

namespace NSwag.CodeGeneration.Models
{
    /// The Swagger operation template model.
    public abstract class OperationModelBase<TParameterModel, TResponseModel> : IOperationModel
        where TParameterModel : ParameterModelBase
        where TResponseModel : ResponseModelBase
    {
        private readonly OpenApiOperation _operation;
        private readonly TypeResolverBase _resolver;
        private readonly IClientGenerator _generator;
        private readonly ClientGeneratorBaseSettings _settings;

        /// Initializes a new instance of the <see cref="OperationModelBase{TParameterModel, TResponseModel}"/> class.
        /// <param name="exceptionSchema">The exception schema.</param>
        /// <param name="operation">The operation.</param>
        /// <param name="resolver">The resolver.</param>
        /// <param name="generator">The generator.</param>
        /// <param name="settings">The settings.</param>
        protected OperationModelBase(JsonSchema exceptionSchema, OpenApiOperation operation, TypeResolverBase resolver, IClientGenerator generator, ClientGeneratorBaseSettings settings)
        {
            _operation = operation;
            _resolver = resolver;
            _generator = generator;
            _settings = settings;

            var responses = _operation.ActualResponses
                .Select(response => CreateResponseModel(operation, response.Key, response.Value, exceptionSchema, generator, resolver, settings))
                .ToList();

            var defaultResponse = responses.SingleOrDefault(r => r.StatusCode == "default");
            if (defaultResponse != null)
            {
                responses.Remove(defaultResponse);
            }

            Responses = responses;
            DefaultResponse = defaultResponse;
        }

        /// Creates the response model.
        /// <param name="operation">The operation.</param>
        /// <param name="statusCode">The status code.</param>
        /// <param name="response">The response.</param>
        /// <param name="exceptionSchema">The exception schema.</param>
        /// <param name="generator">The generator.</param>
        /// <param name="resolver">The resolver.</param>
        /// <param name="settings">The settings.</param>
        /// <returns>The response model.</returns>
        protected abstract TResponseModel CreateResponseModel(OpenApiOperation operation, string statusCode, OpenApiResponse response, JsonSchema exceptionSchema, IClientGenerator generator,
            TypeResolverBase resolver, ClientGeneratorBaseSettings settings);

        /// Gets the operation ID.
        public string Id => _operation.OperationId;

        /// Gets or sets the HTTP path (i.e. the absolute route).
        public string Path { get; set; }

        /// Gets or sets the HTTP method.
        public string HttpMethod { get; set; }

        /// Gets or sets the name of the operation.
        public string OperationName { get; set; }

        /// Gets the actual name of the operation (language specific).
        public abstract string ActualOperationName { get; }

        /// Gets the HTTP method in uppercase.
        public string HttpMethodUpper => ConversionUtilities.ConvertToUpperCamelCase(HttpMethod.ToString(), false);

        /// Gets the HTTP method in lowercase.
        public string HttpMethodLower => ConversionUtilities.ConvertToLowerCamelCase(HttpMethod.ToString(), false);

        /// Gets a value indicating whether the HTTP method is GET or DELETE or HEAD.
        public bool IsGetOrDeleteOrHead =>
            HttpMethod == OpenApiOperationMethod.Get ||
            HttpMethod == OpenApiOperationMethod.Delete ||
            HttpMethod == OpenApiOperationMethod.Head;

        /// Gets a value indicating whether the HTTP method is GET or HEAD.
        public bool IsGetOrHead => HttpMethod == OpenApiOperationMethod.Get || HttpMethod == OpenApiOperationMethod.Head;

        // TODO: Remove this (may not work correctly)
        /// Gets or sets a value indicating whether the operation has a result type (i.e. not void).
        public bool HasResultType => GetSuccessResponse().Value?.IsEmpty(_operation) == false;

        /// Gets or sets the type of the result.
        public abstract string ResultType { get; }

        /// Gets the type of the unwrapped result type (without Task).
        public string UnwrappedResultType
        {
            get
            {
                var response = GetSuccessResponse();
                if (response.Value == null || response.Value.IsEmpty(_operation))
                {
                    return "void";
                }

                if (response.Value.IsBinary(_operation) == true)
                {
                    return _generator.GetBinaryResponseTypeName();
                }

                var isNullable = response.Value.IsNullable(_settings.CodeGeneratorSettings.SchemaType);
                var schemaHasTypeNameTitle = response.Value.Schema?.HasTypeNameTitle;
                var hint = schemaHasTypeNameTitle != true ? "Response" : null;
                return _generator.GetTypeName(response.Value.Schema, isNullable, hint);
            }
        }

        /// Gets a value indicating whether the result has description.
        public bool HasResultDescription => !string.IsNullOrEmpty(ResultDescription);

        /// Gets or sets the result description.
        public string ResultDescription
        {
            get
            {
                var response = GetSuccessResponse();
                if (response.Value != null)
                {
                    return ConversionUtilities.TrimWhiteSpaces(response.Value.Description);
                }

                return null;
            }
        }

        /// Gets the name of the controller.
        public string ControllerName { get; set; }

        /// Gets or sets the type of the exception.
        public abstract string ExceptionType { get; }

        /// Gets or sets the responses.
        public List<TResponseModel> Responses { get; }

        /// Gets a value indicating whether the operation has default response.
        public bool HasDefaultResponse => DefaultResponse != null;

        /// Gets or sets the default response.
        public TResponseModel DefaultResponse { get; }

        /// Gets a value indicating whether the operation has an explicit success response defined.
        public bool HasSuccessResponse => Responses.Any(r => r.IsSuccess);

        /// Gets the success response.
        public TResponseModel SuccessResponse => Responses.FirstOrDefault(r => r.IsSuccess);

        /// Gets the responses.
        IEnumerable<ResponseModelBase> IOperationModel.Responses => Responses;

        /// Gets or sets the parameters.
        public IList<TParameterModel> Parameters { get; protected set; }

        /// Gets a value indicating whether the operation has only a default response.
        public bool HasOnlyDefaultResponse => Responses.Count == 0 && HasDefaultResponse;

        /// Gets a value indicating whether the operation has content parameter.
        public bool HasContent => ContentParameter != null;

        /// Gets a value indicating whether the the request has a body.
        public bool HasBody => HasContent || HasFormParameters;

        /// Gets the content parameter.
        /// <exception cref="InvalidOperationException" accessor="get">Multiple body parameters found in operation.</exception>
        public TParameterModel ContentParameter
        {
            get
            {
                if (Parameters.Count(p => p.Kind == OpenApiParameterKind.Body) > 1)
                {
                    throw new InvalidOperationException("Multiple body parameters found in operation '" + _operation.OperationId + "'.");
                }

                return Parameters.SingleOrDefault(p => p.Kind == OpenApiParameterKind.Body);
            }
        }

        /// Gets the path parameters.
        public IEnumerable<TParameterModel> PathParameters => Parameters.Where(p => p.Kind == OpenApiParameterKind.Path);

        /// Gets the query parameters.
        public IEnumerable<TParameterModel> QueryParameters => Parameters.Where(p => p.Kind == OpenApiParameterKind.Query || p.Kind == OpenApiParameterKind.ModelBinding);

        /// Gets a value indicating whether the operation has query parameters.
        public bool HasQueryParameters => QueryParameters.Any();

        /// Gets the header parameters.
        public IEnumerable<TParameterModel> HeaderParameters => Parameters.Where(p => p.Kind == OpenApiParameterKind.Header);

        /// Gets or sets a value indicating whether the accept header is defined in a parameter.
        public bool HasAcceptHeaderParameterParameter => HeaderParameters.Any(p => p.Name.ToLowerInvariant() == "accept");

        /// Gets a value indicating whether the operation has form parameters.
        public bool HasFormParameters => Parameters.Any(p => p.Kind == OpenApiParameterKind.FormData);

        /// Gets a value indicating whether the operation consumes 'application/x-www-form-urlencoded'.
        public bool ConsumesFormUrlEncoded =>
            _operation.ActualConsumes?.Any(c => c == "application/x-www-form-urlencoded") == true ||
            _operation.RequestBody?.Content.Any(mt => mt.Key == "application/x-www-form-urlencoded") == true;

        /// Gets the form parameters.
        public IEnumerable<TParameterModel> FormParameters => Parameters.Where(p => p.Kind == OpenApiParameterKind.FormData);

        /// Gets a value indicating whether the operation has summary.
        public bool HasSummary => !string.IsNullOrEmpty(Summary);

        /// Gets the summary text.
        public string Summary => ConversionUtilities.TrimWhiteSpaces(_operation.Summary);

        /// Gets a value indicating whether the operation has any documentation.
        public bool HasDocumentation => HasSummary || HasResultDescription || Parameters.Any(p => p.HasDescription) || _operation.IsDeprecated;

        /// Gets a value indicating whether the operation is deprecated.
        public bool IsDeprecated => _operation.IsDeprecated;

        /// Gets or sets a value indicating whether this operation has an XML body parameter.
        public bool HasXmlBodyParameter => Parameters.Any(p => p.IsXmlBodyParameter);

        /// Gets or sets a value indicating whether this operation has an binary body parameter.
        public bool HasBinaryBodyParameter => Parameters.Any(p => p.IsBinaryBodyParameter);

        /// Gets the mime type of the request body.
        public string Consumes
        {
            get
            {
                if (_operation.ActualConsumes?.Contains("application/json") == true)
                {
                    return "application/json";
                }

                return _operation.ActualConsumes?.FirstOrDefault() ??
                    _operation.RequestBody?.Content.Keys.FirstOrDefault() ??
                    "application/json";
            }
        }

        /// Gets the mime type of the response body.
        public string Produces
        {
            get
            {
                if (_operation.ActualProduces?.Contains("application/json") == true)
                {
                    return "application/json";
                }

                return _operation.ActualProduces?.FirstOrDefault() ??
                    SuccessResponse?.Produces ??
                    "application/json";
            }
        }

        /// Gets a value indicating whether a file response is expected from one of the responses.
        public bool IsFile => _operation.ActualResponses.Any(r => r.Value.IsBinary(_operation));

        /// Gets a value indicating whether to wrap the response of this operation.
        public bool WrapResponse => _settings.WrapResponses && (
                                    _settings.WrapResponseMethods == null ||
                                    _settings.WrapResponseMethods.Length == 0 ||
                                    _settings.WrapResponseMethods.Contains(_settings.GenerateControllerName(ControllerName) + "." + ActualOperationName));

        /// Gets the operation extension data.
        public IDictionary<string, object> ExtensionData => _operation.ExtensionData;

        /// Gets the success response.
        /// <returns>The response.</returns>
        protected KeyValuePair<string, OpenApiResponse> GetSuccessResponse()
        {
            if (_operation.ActualResponses.Any(r => r.Key == "200"))
            {
                return new KeyValuePair<string, OpenApiResponse>("200", _operation.ActualResponses.Single(r => r.Key == "200").Value);
            }

            var response = _operation.ActualResponses.FirstOrDefault(r => HttpUtilities.IsSuccessStatusCode(r.Key));
            if (response.Value != null)
            {
                return new KeyValuePair<string, OpenApiResponse>(response.Key, response.Value);
            }

            return new KeyValuePair<string, OpenApiResponse>("default", _operation.ActualResponses.FirstOrDefault(r => r.Key == "default").Value);
        }

        /// Gets the name of the parameter variable.
        /// <param name="parameter">The parameter.</param>
        /// <param name="allParameters">All parameters.</param>
        /// <returns>The parameter variable name.</returns>
        protected virtual string GetParameterVariableName(OpenApiParameter parameter, IEnumerable<OpenApiParameter> allParameters)
        {
            return _settings.ParameterNameGenerator.Generate(parameter, allParameters);
        }

        /// Resolves the type of the parameter.
        /// <param name="parameter">The parameter.</param>
        /// <returns>The parameter type name.</returns>
        protected virtual string ResolveParameterType(OpenApiParameter parameter)
        {
            var schema = parameter.ActualSchema;

            if (parameter.IsXmlBodyParameter)
            {
                return "string";
            }

            if (parameter.CollectionFormat == OpenApiParameterCollectionFormat.Multi && !schema.Type.HasFlag(JsonObjectType.Array))
            {
                schema = new JsonSchema { Type = JsonObjectType.Array, Item = schema };
            }

            var typeNameHint = !schema.HasTypeNameTitle ? ConversionUtilities.ConvertToUpperCamelCase(parameter.Name, true) : null;
            var isNullable = parameter.IsRequired == false || parameter.IsNullable(_settings.CodeGeneratorSettings.SchemaType);
            return _resolver.Resolve(schema, isNullable, typeNameHint);
        }

        /// Gets the actual parameters ignoring the excluded ones.
        /// <returns>The parameters.</returns>
        protected IList<OpenApiParameter> GetActualParameters()
        {
            var parameters = _operation.ActualParameters
                .Where(p => !_settings.ExcludedParameterNames.Contains(p.Name))
                .ToList();

            var formDataSchema =
                _operation?.RequestBody?.Content?.ContainsKey("multipart/form-data") == true ?
                _operation.RequestBody.Content["multipart/form-data"]?.Schema : null;

            if (formDataSchema != null && formDataSchema.ActualProperties.Count > 0)
            {
                var formDataProperties = formDataSchema.ActualProperties.ToList();
                return parameters.Where(p => !p.IsBinaryBodyParameter).Concat(formDataProperties.Select((p, i) => new OpenApiParameter
                {
                    Name = p.Key,
                    Kind = OpenApiParameterKind.FormData,
                    Schema = p.Value,
                    CollectionFormat = p.Value.Type.HasFlag(JsonObjectType.Array) && p.Value.Item != null ?
                        OpenApiParameterCollectionFormat.Multi : OpenApiParameterCollectionFormat.Undefined,
                    //Explode = p.Value.Type.HasFlag(JsonObjectType.Array) && p.Value.Item != null,
                    //Schema = p.Value.Type.HasFlag(JsonObjectType.Array) && p.Value.Item != null ? p.Value.Item : p.Value,
                    Position = parameters.Count + 100 + i
                })).ToList();
            }

            return parameters;
        }
    }
};