blob: ae81bbff255db36b1245234cc32e09a5f79083f7 [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.jaxb.cat;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.opengis.util.CodeList;
import org.apache.sis.util.iso.Types;
import org.apache.sis.internal.jaxb.Context;
import org.apache.sis.internal.jaxb.FilterByVersion;
/**
* An adapter for {@link CodeList}, in order to implement the ISO 19115-3 standard.
* This object wraps a {@link CodeListUID}, which contain {@link CodeListUID#codeList codeList}
* and {@link CodeListUID#codeListValue codeListValue} attributes. The result looks like below:
*
* {@preformat xml
* <dateType>
* <CI_DateTypeCode codeList="../Codelist/ML_gmxCodelists.xml#CI_DateTypeCode" codeListValue="revision" codeSpace="fra">
* révision
* </CI_DateTypeCode>
* </dateType>
* }
*
* A subclass must exist for each code list, with a {@link #getElement()} method having a
* {@code @XmlElement} annotation.
*
* @author Cédric Briançon (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @version 1.0
*
* @param <ValueType> The subclass implementing this adapter.
* @param <BoundType> The code list being adapted.
*
* @since 0.3
* @module
*/
public abstract class CodeListAdapter<ValueType extends CodeListAdapter<ValueType,BoundType>,
BoundType extends CodeList<BoundType>> extends XmlAdapter<ValueType,BoundType>
{
/**
* The value of the {@link CodeList}.
*/
protected CodeListUID identifier;
/**
* Empty constructor for subclasses only.
*/
protected CodeListAdapter() {
}
/**
* Creates a wrapper for a {@link CodeList}, in order to handle the format specified in ISO 19115-3.
*
* @param value the value of {@link CodeList} to be marshalled.
*/
protected CodeListAdapter(final CodeListUID value) {
identifier = value;
}
/**
* Wraps the given value.
* Most implementations will be like below:
*
* {@preformat java
* return new ValueType(value);
* }
*
* However is some cases, the {@code value} argument may be inspected.
* For example {@link org.apache.sis.internal.jaxb.code.MD_RestrictionCode}
* replaces {@code "licence"} by {@code "license"} for ISO 19115:2003 compatibility.
*
* @param value the value of {@link CodeList}, to be marshalled.
* @return the wrapper for the code list value.
*/
protected abstract ValueType wrap(CodeListUID value);
/**
* Returns the class of code list wrapped by this adapter.
*
* @return the code list class.
*/
protected abstract Class<BoundType> getCodeListClass();
/**
* Returns {@code true} if a {@code Since2014} subclasses should return a non-null value.
* This is a convenience method for {@code FilterByVersion.CURRENT_METADATA.accept()}.
*
* @return whether {@code Since2014} subclasses should return a non-null value.
*/
protected final boolean accept2014() {
return FilterByVersion.CURRENT_METADATA.accept();
}
/**
* Substitutes the adapter value read from an XML stream by the object which will
* contain the value. JAXB calls automatically this method at unmarshalling time.
*
* @param adapter the adapter for this metadata value.
* @return a code list which represents the metadata value.
*/
@Override
public final BoundType unmarshal(final ValueType adapter) {
return (adapter != null) ? Types.forCodeName(getCodeListClass(), adapter.identifier.toString(), true) : null;
}
/**
* Substitutes the code list by the adapter to be marshalled into an XML file
* or stream. JAXB calls automatically this method at marshalling time.
*
* @param code the code list value.
* @return the adapter for the given code list.
*/
@Override
public final ValueType marshal(final BoundType code) {
if (code == null) {
return null;
}
final CodeListUID p;
if (isEnum()) {
// To be removed after GEO-199 resolution.
p = new CodeListUID();
p.value = Types.getCodeName(code);
} else {
p = new CodeListUID(Context.current(), code);
}
return wrap(p);
}
/**
* Returns {@code true} if this code list is actually an enum. The default implementation
* returns {@code false} in every cases, since there is very few enums in ISO 19115.
*
* @return {@code true} if this code list is actually an enum.
*
* @todo Remove this method after we refactored enum wrappers as {@code EnumAdapter} subclasses
* instead of {@code CodeListAdapter}. This requires the resolution of GEO-199 first.
*
* @see <a href="http://jira.codehaus.org/browse/GEO-199">GEO-199</a>
*/
protected boolean isEnum() {
return false;
}
/**
* Invoked by JAXB on marshalling. Subclasses must override this
* method with the appropriate {@code @XmlElement} annotation.
*
* @return the {@code CodeList} value to be marshalled.
*/
public abstract CodeListUID getElement();
/*
* We do not define setter method (even abstract) since it seems to confuse JAXB.
* It is subclasses responsibility to define the setter method. The existence of
* this setter will be tested by MetadataAnnotationsTest.
*/
}