use of org.apache.sis.io.wkt.FormattableObject in project sis by apache.
the class AbstractParameterDescriptor method formatTo.
/**
* Formats this descriptor as a pseudo-<cite>Well Known Text</cite> element. The WKT specification
* does not define any representation of parameter descriptors. Apache SIS fallback on a list of
* {@linkplain DefaultParameterDescriptor#formatTo(Formatter) descriptors}.
* The text formatted by this method is {@linkplain Formatter#setInvalidWKT flagged as invalid WKT}.
*
* @param formatter the formatter where to format the inner content of this WKT element.
* @return {@code "Parameter"} or {@code "ParameterGroup"}.
*/
@Override
protected String formatTo(final Formatter formatter) {
super.formatTo(formatter);
formatter.setInvalidWKT(this, null);
if (this instanceof ParameterDescriptorGroup) {
for (GeneralParameterDescriptor parameter : ((ParameterDescriptorGroup) this).descriptors()) {
if (!(parameter instanceof FormattableObject)) {
if (parameter instanceof ParameterDescriptor<?>) {
parameter = new DefaultParameterDescriptor<>((ParameterDescriptor<?>) parameter);
} else if (parameter instanceof ParameterDescriptorGroup) {
parameter = new DefaultParameterDescriptorGroup((ParameterDescriptorGroup) parameter);
} else {
continue;
}
}
formatter.newLine();
formatter.append((FormattableObject) parameter);
}
return WKTKeywords.ParameterGroup;
} else if (this instanceof ParameterDescriptor<?>) {
final Object defaultValue = ((ParameterDescriptor<?>) this).getDefaultValue();
if (defaultValue != null) {
formatter.appendAny(defaultValue);
}
formatter.append(((ParameterDescriptor<?>) this).getUnit());
}
return WKTKeywords.Parameter;
}
use of org.apache.sis.io.wkt.FormattableObject in project sis by apache.
the class ServicesForMetadata method toFormattableObject.
/**
* Converts the given object in a {@code FormattableObject} instance. Callers should verify that the given
* object is not already an instance of {@code FormattableObject} before to invoke this method. This method
* returns {@code null} if it can not convert the object.
*
* @param object the object to wrap.
* @param internal {@code true} if the formatting convention is {@code Convention.INTERNAL}.
* @return the given object converted to a {@code FormattableObject} instance, or {@code null}.
*
* @since 0.6
*/
@Override
public FormattableObject toFormattableObject(final MathTransform object, boolean internal) {
Matrix matrix;
final ParameterValueGroup parameters;
if (internal && (matrix = MathTransforms.getMatrix(object)) != null) {
parameters = Affine.parameters(matrix);
} else if (object instanceof Parameterized) {
parameters = ((Parameterized) object).getParameterValues();
} else {
matrix = MathTransforms.getMatrix(object);
if (matrix == null) {
return null;
}
parameters = Affine.parameters(matrix);
}
return new FormattableObject() {
@Override
protected String formatTo(final Formatter formatter) {
WKTUtilities.appendParamMT(parameters, formatter);
return WKTKeywords.Param_MT;
}
};
}
use of org.apache.sis.io.wkt.FormattableObject in project sis by apache.
the class GeocentricAffine method asDatumShift.
/**
* Given a transformation chain, conditionally replaces the affine transform elements by an alternative object
* showing the Bursa-Wolf parameters. The replacement is applied if and only if the affine transform is a scale,
* translation or rotation in the geocentric domain.
*
* <p>This method is invoked only by {@code ConcatenatedTransform.getPseudoSteps()} for the need of WKT formatting.
* The purpose of this method is very similar to the purpose of {@code AbstractMathTransform.beforeFormat(List, int,
* boolean)} except that we need to perform the {@code forDatumShift(…)} work only after {@code beforeFormat(…)}
* finished its work for all {@code ContextualParameters}, including the {@code EllipsoidToCentricTransform}'s one.</p>
*
* @param transforms the full chain of concatenated transforms.
*/
public static void asDatumShift(final List<Object> transforms) {
for (int i = transforms.size() - 2; --i >= 0; ) {
if (isOperation(GeographicToGeocentric.NAME, transforms.get(i)) && isOperation(GeocentricToGeographic.NAME, transforms.get(i + 2))) {
final Object step = transforms.get(i + 1);
if (step instanceof LinearTransform) {
final BursaWolfParameters parameters = new BursaWolfParameters(null, null);
try {
parameters.setPositionVectorTransformation(((LinearTransform) step).getMatrix(), BURSAWOLF_TOLERANCE);
} catch (IllegalArgumentException e) {
/*
* Should not occur, except sometime on inverse transform of relatively complex datum shifts
* (more than just translation terms). We can fallback on formatting the full matrix.
*/
log(Loggers.WKT, "asDatumShift", e);
continue;
}
final boolean isTranslation = parameters.isTranslation();
final Parameters values = createParameters(isTranslation ? GeocentricTranslation.PARAMETERS : PositionVector7Param.PARAMETERS, parameters, isTranslation);
transforms.set(i + 1, new FormattableObject() {
@Override
protected String formatTo(final Formatter formatter) {
WKTUtilities.appendParamMT(values, formatter);
return WKTKeywords.Param_MT;
}
});
}
}
}
}
use of org.apache.sis.io.wkt.FormattableObject in project sis by apache.
the class ImmutableIdentifier method formatTo.
/**
* Formats this identifier as a <cite>Well Known Text</cite> {@code Id[…]} element.
* See class javadoc for more information on the WKT format.
*
* @param formatter the formatter where to format the inner content of this WKT element.
* @return {@code "Id"} (WKT 2) or {@code "Authority"} (WKT 1).
*
* @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#33">WKT 2 specification §7.3.4</a>
*/
@Override
protected String formatTo(final Formatter formatter) {
String keyword = null;
/*
* The code, codeSpace, authority and version local variables in this method usually have the exact same
* value than the fields of the same name in this class. But we get those values by invoking the public
* methods in order to give to users a chance to override those properties. The intent is also to use a
* consistent approach for all 'formatTo' implementations, since some other classes have no choice other
* than using the public methods.
*/
final String code = getCode();
if (code != null) {
final String codeSpace = getCodeSpace();
final Citation authority = getAuthority();
final String cs = (codeSpace != null) ? codeSpace : org.apache.sis.internal.util.Citations.getIdentifier(authority, true);
if (cs != null) {
final Convention convention = formatter.getConvention();
if (convention.majorVersion() == 1) {
keyword = WKTKeywords.Authority;
formatter.append(cs, ElementKind.IDENTIFIER);
formatter.append(code, ElementKind.IDENTIFIER);
} else {
keyword = WKTKeywords.Id;
formatter.append(cs, ElementKind.IDENTIFIER);
appendCode(formatter, code);
final String version = getVersion();
if (version != null) {
appendCode(formatter, version);
}
/*
* In order to simplify the WKT, format the citation only if it is different than the code space.
* We will also omit the citation if this identifier is for a parameter value, because parameter
* values are handled in a special way by the international standard:
*
* - ISO 19162 explicitely said that we shall format the identifier for the root element only,
* and omit the identifier for all inner elements EXCEPT parameter values and operation method.
* - Exclusion of identifier for inner elements is performed by the Formatter class, so it does
* not need to be checked here.
* - Parameter values are numerous, while operation methods typically appear only once in a WKT
* document. So we will simplify the parameter values only (not the operation methods) except
* if the parameter value is the root element (in which case we will format full identifier).
*/
final FormattableObject enclosing = formatter.getEnclosingElement(1);
final boolean isRoot = formatter.getEnclosingElement(2) == null;
if (isRoot || !(enclosing instanceof ParameterValue<?>)) {
final String citation = org.apache.sis.internal.util.Citations.getIdentifier(authority, false);
if (citation != null && !citation.equals(cs)) {
formatter.append(new Cite(citation));
}
}
/*
* Do not format the optional URI element for internal convention,
* because this property is currently computed rather than stored.
* Other conventions format only for the ID[…] of root element.
*/
if (isRoot && enclosing != null && convention != Convention.INTERNAL) {
final String urn = NameMeaning.toURN(enclosing.getClass(), cs, version, code);
if (urn != null) {
formatter.append(new FormattableObject() {
@Override
protected String formatTo(final Formatter formatter) {
formatter.append(urn, null);
return WKTKeywords.URI;
}
});
}
}
}
}
}
return keyword;
}
use of org.apache.sis.io.wkt.FormattableObject in project sis by apache.
the class DefaultOperationMethod method formatTo.
/**
* Formats this operation as a <cite>Well Known Text</cite> {@code Method[…]} element.
*
* @return {@code "Method"} (WKT 2) or {@code "Projection"} (WKT 1).
*
* @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#118">WKT 2 specification §17.2.3</a>
*/
@Override
protected String formatTo(final Formatter formatter) {
final boolean isWKT1 = formatter.getConvention().majorVersion() == 1;
/*
* The next few lines below are basically a copy of the work done by super.formatTo(formatter),
* which search for the name to write inside METHOD["name"]. The difference is in the fallback
* executed if we do not find a name for the given authority.
*/
final Citation authority = formatter.getNameAuthority();
String name = IdentifiedObjects.getName(this, authority);
ElementKind kind = ElementKind.METHOD;
if (name == null) {
/*
* No name found for the given authority. We may use the primary name as a fallback.
* But before doing that, maybe we can find the name that we are looking for in the
* hard-coded values in the 'org.apache.sis.internal.referencing.provider' package.
* The typical use case is when this DefaultOperationMethod has been instantiated
* by the EPSG factory using only the information found in the EPSG database.
*
* We can find the hard-coded names by looking at the ParameterDescriptorGroup of the
* enclosing ProjectedCRS or DerivedCRS. This is because that parameter descriptor was
* typically provided by the 'org.apache.sis.internal.referencing.provider' package in
* order to create the MathTransform associated with the enclosing CRS. The enclosing
* CRS is either the immediate parent in WKT 1, or the parent of the parent in WKT 2.
*/
final FormattableObject parent = formatter.getEnclosingElement(isWKT1 ? 1 : 2);
if (parent instanceof GeneralDerivedCRS) {
final Conversion conversion = ((GeneralDerivedCRS) parent).getConversionFromBase();
if (conversion != null) {
// Should never be null, but let be safe.
final ParameterDescriptorGroup descriptor;
if (conversion instanceof Parameterized) {
// Usual case in SIS implementation.
descriptor = ((Parameterized) conversion).getParameterDescriptors();
} else {
descriptor = conversion.getParameterValues().getDescriptor();
}
name = IdentifiedObjects.getName(descriptor, authority);
}
}
if (name == null) {
name = IdentifiedObjects.getName(this, null);
if (name == null) {
name = Vocabulary.getResources(formatter.getLocale()).getString(Vocabulary.Keys.Unnamed);
// Because the "Unnamed" string is not a real OperationMethod name.
kind = ElementKind.NAME;
}
}
}
formatter.append(name, kind);
if (isWKT1) {
/*
* The WKT 1 keyword is "PROJECTION", which imply that the operation method should be of type
* org.opengis.referencing.operation.Projection. So strictly speaking only the first check in
* the following 'if' statement is relevant.
*
* Unfortunately in many cases we do not know the operation type, because the method that we
* invoked - getOperationType() - is not a standard OGC/ISO property, so this information is
* usually not provided in XML documents for example. The user could also have instantiated
* DirectOperationMethod directly without creating a subclass. Consequently we also accept to
* format the keyword as "PROJECTION" if the operation type *could* be a projection. This is
* the second check in the following 'if' statement.
*
* In other words, the combination of those two checks exclude the following operation types:
* Transformation, ConcatenatedOperation, PassThroughOperation, or any user-defined type that
* do not extend Projection. All other operation types are accepted.
*/
final Class<? extends SingleOperation> type = getOperationType();
if (Projection.class.isAssignableFrom(type) || type.isAssignableFrom(Projection.class)) {
return WKTKeywords.Projection;
}
formatter.setInvalidWKT(this, null);
}
return WKTKeywords.Method;
}
Aggregations