blob: 8d17c83855509f346cc3bfc8480fac445d1c81ec [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.internal.converter;
import java.util.Set;
import java.util.EnumSet;
import org.apache.sis.util.ObjectConverter;
import org.apache.sis.math.FunctionProperty;
/**
* An object converter which returns the source unchanged.
*
* <h2>Immutability and thread safety</h2>
* This class is immutable and thus inherently thread-safe.
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @version 0.3
*
* @param <S> the base type of source objects.
* @param <T> the base type of converted objects.
*
* @see org.apache.sis.util.ObjectConverters#identity(Class)
*
* @since 0.3
* @module
*/
public final class IdentityConverter<S extends T, T> extends SystemConverter<S,T> {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = -4410848323263094741L;
/**
* The inverse converter specified at construction time, or {@code null} if none.
*/
private final ObjectConverter<T, S> inverse;
/**
* Creates a new identity converter.
*
* @param sourceClass the {@linkplain #getSourceClass() source class}.
* @param targetClass the {@linkplain #getTargetClass() target class}.
* @param inverse the inverse converter, or {@code null} if none.
*/
@SuppressWarnings("unchecked")
public IdentityConverter(final Class<S> sourceClass, final Class<T> targetClass,
ObjectConverter<T, S> inverse)
{
super(sourceClass, targetClass);
if (inverse == null && sourceClass == targetClass) {
inverse = (ObjectConverter<T,S>) this;
}
this.inverse = inverse;
}
/**
* Returns the properties of this converter.
* This method returns a new {@link EnumSet} instead than returning a constant, because
* creating {@code EnumSet} is cheap and the standard JDK implementation has optimizations
* for bulk operations between {@code EnumSet} instances. Those optimizations are lost (at
* least on JDK6) is we wrap the {@code EnumSet} in a {@code Collections.unmodifiableSet} view.
*
* @return the manners in which source values are mapped to target values.
*/
@Override
public Set<FunctionProperty> properties() {
final EnumSet<FunctionProperty> properties = EnumSet.allOf(FunctionProperty.class);
if (inverse == null) {
properties.remove(FunctionProperty.INVERTIBLE);
}
return properties;
}
/**
* Returns the inverse converter, if any.
*
* @return a converter for converting instances of <var>T</var> back to instances of <var>S</var>.
*/
@Override
public ObjectConverter<T,S> inverse() throws UnsupportedOperationException {
return (inverse != null) ? inverse : super.inverse();
}
/**
* Returns the given object unchanged.
*
* @param source the value to convert.
* @return the given value unchanged.
*/
@Override
public T apply(final S source) {
return source;
}
}