blob: efeab4a5a6c5c14d8bbfcf66e61b0c883d13c448 [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.style.se1;
import java.util.Optional;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.XmlElement;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.filter.Expression;
/**
* Information about a channel to use in a multi-spectral source.
* Channels are identified by data-dependent character identifiers.
* Commonly, channels will be labelled as "1", "2", <i>etc</i>.
* A set of selected channels is contained in {@link ChannelSelection}.
*
* <!-- Following list of authors contains credits to OGC GeoAPI 2 contributors. -->
* @author Ian Turton (CCG)
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
*
* @param <R> the type of data to style, such as {@code Feature} or {@code Coverage}.
*/
@XmlType(name = "SelectedChannelType", propOrder = {
"sourceChannelName",
"contrastEnhancement"
})
// No root element is specified in OGC 05-077r4.
public class SelectedChannel<R> extends StyleElement<R> {
/**
* The channel's name, or {@code null} if unspecified.
*
* @see #getSourceChannelName()
* @see #setSourceChannelName(Expression)
*
* @todo Needs an adapter from expression to plain string.
*/
@XmlElement(name = "SourceChannelName", required = true)
protected Expression<R,String> sourceChannelName;
/**
* Contrast enhancement applied to the selected channel in isolation, or {@code null} if none.
*
* @see #getContrastEnhancement()
* @see #setContrastEnhancement(ContrastEnhancement)
*/
@XmlElement(name = "ContrastEnhancement")
protected ContrastEnhancement<R> contrastEnhancement;
/**
* For JAXB unmarshalling only.
*/
private SelectedChannel() {
// Thread-local factory will be used.
}
/**
* Creates an initially empty selected channel.
*
* @param factory the factory to use for creating expressions and child elements.
*/
public SelectedChannel(final StyleFactory<R> factory) {
super(factory);
}
/**
* Creates a shallow copy of the given object.
* For a deep copy, see {@link #clone()} instead.
*
* @param source the object to copy.
*/
public SelectedChannel(final SelectedChannel<R> source) {
super(source);
sourceChannelName = source.sourceChannelName;
contrastEnhancement = source.contrastEnhancement;
}
/**
* Returns the channel's name.
*
* @return the channel's name, or {@code null} if unspecified.
*
* @todo Shall never be {@code null}. We need to think about some default value.
*/
public Expression<R,String> getSourceChannelName() {
return sourceChannelName;
}
/**
* Sets the channel's name.
*
* @param value the channel's name, or {@code null} if unspecified.
*/
public void setSourceChannelName(final Expression<R,String> value) {
sourceChannelName = value;
}
/**
* Returns the contrast enhancement applied to the selected channel in isolation.
* The returned object is <em>live</em>:
* changes in the returned instance will be reflected in this stroke, and conversely.
*
* @return contrast enhancement for the selected channel.
*
* @see RasterSymbolizer#getContrastEnhancement()
*/
public Optional<ContrastEnhancement<R>> getContrastEnhancement() {
return Optional.ofNullable(contrastEnhancement);
}
/**
* Sets the contrast enhancement applied to the selected channel in isolation.
* The given instance is stored by reference, it is not cloned.
* If this method is never invoked, then the default value is absence.
*
* @param value new contrast enhancement, or {@code null} if none.
*
* @see RasterSymbolizer#setContrastEnhancement(ContrastEnhancement)
*/
public void setContrastEnhancement(final ContrastEnhancement<R> value) {
contrastEnhancement = value;
}
/**
* Returns all properties contained in this class.
* This is used for {@link #equals(Object)} and {@link #hashCode()} implementations.
*/
@Override
final Object[] properties() {
return new Object[] {sourceChannelName, contrastEnhancement};
}
/**
* Returns a deep clone of this object. All style elements are cloned,
* but expressions are not on the assumption that they are immutable.
*
* @return deep clone of all style elements.
*/
@Override
public SelectedChannel<R> clone() {
final var clone = (SelectedChannel<R>) super.clone();
clone.selfClone();
return clone;
}
/**
* Clones the mutable style fields of this element.
*/
private void selfClone() {
if (contrastEnhancement != null) {
contrastEnhancement = contrastEnhancement.clone();
}
}
}