blob: 9241980d570705097e80c55f2d3dff77ca8c54e4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sis.referencing.operation;
import java.util.Objects;
import java.io.Serializable;
import org.opengis.util.InternationalString;
import org.opengis.metadata.citation.Citation;
import org.opengis.referencing.operation.Formula;
import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.io.wkt.ElementKind;
import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.iso.Types;
/**
* Specification of the coordinate operation method formula.
* A formula may be {@linkplain #getFormula() given textually},
* or may be a {@linkplain #getCitation() reference to a publication}.
*
* <p>{@code Formula} is for human reading.
* The object that actually does the work of applying formula to coordinate values is
* {@link org.opengis.referencing.operation.MathTransform}.</p>
*
* @author Martin Desruisseaux (Geomatys)
* @version 0.5
*
* @see DefaultOperationMethod
* @see org.apache.sis.referencing.operation.transform.AbstractMathTransform
* @see org.apache.sis.referencing.operation.transform.MathTransformProvider
*
* @since 0.5
*/
public class DefaultFormula extends FormattableObject implements Formula, Serializable {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = 1929966748615362698L;
/**
* Formula(s) or procedure used by the operation method.
*/
@SuppressWarnings("serial") // Most SIS implementations are serializable.
private final InternationalString formula;
/**
* Reference to a publication giving the formula(s) or procedure used by the coordinate operation method.
*/
@SuppressWarnings("serial") // Most SIS implementations are serializable.
private final Citation citation;
/**
* Creates a new formula. This constructor is not public because of {@code Formula} object should not have
* both the formula literal and the citation. But we use this constructor an unmarshalling time if the XML
* document have both. Having both is not valid GML, but SIS is tolerant to this situation.
*/
DefaultFormula(final InternationalString formula, final Citation citation) {
this.formula = formula;
this.citation = citation;
}
/**
* Creates a new formula from the given string.
*
* @param formula the formula.
*/
public DefaultFormula(final CharSequence formula) {
ArgumentChecks.ensureNonEmpty("formula", formula);
this.formula = Types.toInternationalString(formula);
this.citation = null;
}
/**
* Creates a new formula from the given citation.
*
* @param citation the citation.
*/
public DefaultFormula(final Citation citation) {
this.citation = Objects.requireNonNull(citation);
this.formula = null;
}
/**
* Creates a new formula with the same values as the specified one.
* This copy constructor provides a way to convert an arbitrary implementation into a SIS one
* or a user-defined one (as a subclass), usually in order to leverage some implementation-specific API.
*
* <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
*
* @param formula the formula to copy.
*
* @see #castOrCopy(Formula)
*/
protected DefaultFormula(final Formula formula) {
this.citation = formula.getCitation();
this.formula = formula.getFormula();
}
/**
* Returns a SIS formula implementation with the same values as the given arbitrary implementation.
* If the given object is {@code null}, then this method returns {@code null}.
* Otherwise if the given object is already a SIS implementation, then the given object is returned unchanged.
* Otherwise a new SIS implementation is created and initialized to the attribute values of the given object.
*
* @param object the object to get as a SIS implementation, or {@code null} if none.
* @return a SIS implementation containing the values of the given object (may be the
* given object itself), or {@code null} if the argument was null.
*/
public static DefaultFormula castOrCopy(final Formula object) {
return (object == null) || (object instanceof DefaultFormula)
? (DefaultFormula) object : new DefaultFormula(object);
}
/**
* Returns the formula(s) or procedure used by the operation method, or {@code null} if none.
*/
@Override
public InternationalString getFormula() {
return formula;
}
/**
* Returns the reference to a publication giving the formula(s) or procedure used by the
* coordinate operation method, or {@code null} if none.
*/
@Override
public Citation getCitation() {
return citation;
}
/**
* Returns a hash code value for this formula.
*/
@Override
public int hashCode() {
int code = (int) serialVersionUID;
if (formula != null) code += formula .hashCode();
if (citation != null) code += citation.hashCode() * 31;
return code;
}
/**
* Compares this formula with the given object for equality.
*
* @param object the object to compare with this formula.
* @return {@code true} if both objects are equal.
*/
@Override
public boolean equals(final Object object) {
if (object == this) {
return true;
}
if (object != null && object.getClass() == getClass()) {
final DefaultFormula that = (DefaultFormula) object;
return Objects.equals(this.formula, that.formula) &&
Objects.equals(this.citation, that.citation);
}
return false;
}
/**
* Formats this formula as a pseudo-<i>Well Known Text</i> element.
*
* <h4>Compatibility note</h4>
* ISO 19162 does not define a WKT representation for {@code Formula} objects.
* The text formatted by this method is SIS-specific and causes the text to be
* flagged as {@linkplain Formatter#setInvalidWKT(Class, Exception) invalid WKT}.
* The WKT content of this element may change in any future SIS version.
*
* @return {@code "Formula"}.
*/
@Override
protected String formatTo(final Formatter formatter) {
InternationalString text = null;
final Citation citation = getCitation(); // Gives to users a chance to override properties.
if (citation != null) {
text = citation.getTitle();
}
if (text == null) {
text = getFormula();
}
if (text != null) {
formatter.append(text.toString(formatter.getLocale()), ElementKind.REMARKS);
}
formatter.setInvalidWKT(Formula.class, null);
return WKTKeywords.Formula;
}
}