Author: desruisseaux
Date: Sun Mar 31 21:06:18 2013
New Revision: 1463051
URL: http://svn.apache.org/r1463051
Log:
Starting the enforcement of some ISO 19115 conditions, especially mutually
exclusive properties.
Added:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ExcludedSet.java
(with props)
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAggregateInformation.java
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultSource.java
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultDataQuality.java
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultScope.java
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeorectified.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
Added:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ExcludedSet.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ExcludedSet.java?rev=1463051&view=auto
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ExcludedSet.java
(added)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ExcludedSet.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -0,0 +1,95 @@
+/*
+ * 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.metadata;
+
+import java.util.AbstractSet;
+import java.util.Collections;
+import java.util.Iterator;
+import java.io.Serializable;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * A unmodifiable empty set with a customized exception message thrown by the
{@link #add(Object)}
+ * method. This set is used only for mutually exclusive properties, when a
collection can not have
+ * elements because the other property is set.
+ *
+ * @param <E> The type of elements that the collection would have if it was
non-empty.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.3
+ * @version 0.3
+ * @module
+ *
+ * @see Collections#emptySet()
+ */
+public final class ExcludedSet<E> extends AbstractSet<E> implements
Serializable {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -3882719616419776295L;
+
+ /**
+ * The name of the mutually exclusive properties.
+ */
+ private final String name1, name2;
+
+ /**
+ * Creates a new empty set.
+ *
+ * @param name1 The name of the first mutually exclusive property.
+ * @param name2 The name of the second mutually exclusive property.
+ */
+ public ExcludedSet(final String name1, final String name2) {
+ this.name1 = name1;
+ this.name2 = name2;
+ }
+
+ /**
+ * Returns {@code true} since this set is always empty.
+ */
+ @Override
+ public boolean isEmpty() {
+ return true;
+ }
+
+ /**
+ * Returns {@code 0} since this set is always empty.
+ */
+ @Override
+ public int size() {
+ return 0;
+ }
+
+ /**
+ * Returns the empty iterator.
+ */
+ @Override
+ public Iterator<E> iterator() {
+ return Collections.emptyIterator();
+ }
+
+ /**
+ * Unconditionally throws a {@link UnsupportedOperationException} with a
message
+ * saying which properties are mutually exclusive.
+ */
+ @Override
+ public boolean add(final E e) {
+ throw new UnsupportedOperationException(Errors.format(
+ Errors.Keys.CanNotAddToExclusiveSet_2, name1, name2));
+ }
+}
Propchange:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ExcludedSet.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ExcludedSet.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -27,11 +27,11 @@ import org.apache.sis.util.logging.Loggi
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.collection.CheckedHashSet;
import org.apache.sis.util.collection.CheckedArrayList;
-import org.apache.sis.internal.jaxb.MarshalContext;
import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
import static org.apache.sis.util.collection.CollectionsExt.isNullOrEmpty;
import static org.apache.sis.util.collection.CollectionsExt.hashMapCapacity;
+import static org.apache.sis.internal.jaxb.MarshalContext.isMarshaling;
/**
@@ -488,15 +488,6 @@ public abstract class ModifiableMetadata
}
/**
- * Returns {@code true} if the caller {@code nonNullCollection} method (or
list, or set)
- * is allowed to returns {@code null} instead than an empty list. This
happen mostly at
- * XML marshalling time.
- */
- private static boolean isMarshaling() {
- return MarshalContext.isFlagSet(MarshalContext.current(),
MarshalContext.MARSHALING);
- }
-
- /**
* Returns the specified list, or a new one if {@code c} is null.
* This is a convenience method for implementation of {@code getFoo()}
methods.
*
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAggregateInformation.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAggregateInformation.java?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAggregateInformation.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/identification/DefaultAggregateInformation.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -30,6 +30,13 @@ import org.apache.sis.metadata.iso.ISOMe
/**
* Aggregate dataset information.
*
+ * {@section Relationship between properties}
+ * According ISO 19115, the {@linkplain #getAggregateDataSetName() aggregate
dataset name} and
+ * {@linkplain #getAggregateDataSetIdentifier() aggregate dataset identifier}
properties are
+ * exclusive: setting one of those properties to a non-null value discard the
other one.
+ * See the {@linkplain #DefaultAggregateInformation(AggregateInformation)
constructor javadoc}
+ * for information about which property has precedence on copy operations.
+ *
* @author Guilhem Legal (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @since 0.3 (derived from geotk-3.00)
@@ -50,14 +57,9 @@ public class DefaultAggregateInformation
private static final long serialVersionUID = 5520234916010871192L;
/**
- * Citation information about the aggregate dataset.
- */
- private Citation aggregateDataSetName;
-
- /**
- * Identification information about aggregate dataset.
+ * The {@code aggregateDataSetName} or {@code aggregateDataSetIdentifier}
property.
*/
- private Identifier aggregateDataSetIdentifier;
+ private Object nameOrIdentifier;
/**
* Association type of the aggregate dataset.
@@ -80,16 +82,22 @@ public class DefaultAggregateInformation
* This is a <cite>shallow</cite> copy constructor, since the other
metadata contained in the
* given object are not recursively copied.
*
+ * <p>If both {@linkplain #getAggregateDataSetName() aggregate dataset
name} and
+ * {@linkplain #getAggregateDataSetIdentifier() aggregate dataset
identifier} are
+ * specified, then the name will have precedence and the identifier is
silently discarded.</p>
+ *
* @param object The metadata to copy values from.
*
* @see #castOrCopy(AggregateInformation)
*/
public DefaultAggregateInformation(final AggregateInformation object) {
super(object);
- aggregateDataSetName = object.getAggregateDataSetName();
- aggregateDataSetIdentifier = object.getAggregateDataSetIdentifier();
- associationType = object.getAssociationType();
- initiativeType = object.getInitiativeType();
+ nameOrIdentifier = object.getAggregateDataSetName();
+ if (nameOrIdentifier == null) {
+ nameOrIdentifier = object.getAggregateDataSetIdentifier();
+ }
+ associationType = object.getAssociationType();
+ initiativeType = object.getInitiativeType();
}
/**
@@ -118,6 +126,15 @@ public class DefaultAggregateInformation
}
/**
+ * Invoked every time the code needs to decide whether the provided
information
+ * is the name or the identifier. Defined as a method in order to have a
single
+ * word to search if we need to revisit the policy.
+ */
+ private boolean isName() {
+ return (nameOrIdentifier instanceof Citation);
+ }
+
+ /**
* Citation information about the aggregate dataset.
*
* @return Citation information about the aggregate dataset, or {@code
null}.
@@ -125,17 +142,23 @@ public class DefaultAggregateInformation
@Override
@XmlElement(name = "aggregateDataSetName")
public synchronized Citation getAggregateDataSetName() {
- return aggregateDataSetName;
+ return isName() ? (Citation) nameOrIdentifier : null;
}
/**
* Sets the citation information about the aggregate dataset.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-null, then this method
automatically
+ * discards the {@linkplain #setAggregateDataSetIdentifier aggregate
dataset identifier}.
+ *
* @param newValue The new citation.
*/
public synchronized void setAggregateDataSetName(final Citation newValue) {
checkWritePermission();
- aggregateDataSetName = newValue;
+ if (newValue != null || isName()) {
+ nameOrIdentifier = newValue;
+ }
}
/**
@@ -146,16 +169,23 @@ public class DefaultAggregateInformation
@Override
@XmlElement(name = "aggregateDataSetIdentifier")
public synchronized Identifier getAggregateDataSetIdentifier() {
- return aggregateDataSetIdentifier;
+ return isName() ? null : (Identifier) nameOrIdentifier;
}
/**
* Sets the identification information about aggregate dataset.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-null, then this method
automatically
+ * discards the {@linkplain #setAggregateDataSetName aggregate dataset
name}.
+ *
* @param newValue The new identifier.
*/
public synchronized void setAggregateDataSetIdentifier(final Identifier
newValue) {
- aggregateDataSetIdentifier = newValue;
+ checkWritePermission();
+ if (newValue != null || !isName()) {
+ nameOrIdentifier = newValue;
+ }
}
/**
@@ -175,6 +205,7 @@ public class DefaultAggregateInformation
* @param newValue The new association type.
*/
public synchronized void setAssociationType(final AssociationType
newValue) {
+ checkWritePermission();
associationType = newValue;
}
@@ -195,6 +226,7 @@ public class DefaultAggregateInformation
* @param newValue The new initiative.
*/
public synchronized void setInitiativeType(final InitiativeType newValue) {
+ checkWritePermission();
initiativeType = newValue;
}
}
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultSource.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultSource.java?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultSource.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/lineage/DefaultSource.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -33,11 +33,21 @@ import org.opengis.util.InternationalStr
import org.apache.sis.metadata.iso.ISOMetadata;
import org.apache.sis.util.iso.Types;
import org.apache.sis.xml.Namespaces;
+import org.apache.sis.internal.metadata.ExcludedSet;
+
+import static org.apache.sis.internal.jaxb.MarshalContext.isMarshaling;
+import static org.apache.sis.util.collection.CollectionsExt.isNullOrEmpty;
/**
* Information about the source data used in creating the data specified by
the scope.
*
+ * {@section Relationship between properties}
+ * According ISO 19115, the {@linkplain #getDescription() description} and
{@linkplain #getSourceExtents()
+ * source extents} properties are exclusive: setting one of those properties
to a non-empty value discard
+ * the other one. See the {@linkplain #DefaultSource(Source) constructor
javadoc} for information about
+ * which property has precedence on copy operations.
+ *
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Touraïvane (IRD)
* @author Cédric Briançon (Geomatys)
@@ -63,9 +73,9 @@ public class DefaultSource extends ISOMe
private static final long serialVersionUID = 6277132009549470021L;
/**
- * Detailed description of the level of the source data.
+ * The {@code description} or the {@code sourceExtents} property.
*/
- private InternationalString description;
+ private Object descriptionOrExtents;
/**
* Denominator of the representative fraction on a source map.
@@ -83,11 +93,6 @@ public class DefaultSource extends ISOMe
private Citation sourceCitation;
/**
- * Information about the spatial, vertical and temporal extent of the
source data.
- */
- private Collection<Extent> sourceExtents;
-
- /**
* Information about an event in the creation process for the source data.
*/
private Collection<ProcessStep> sourceSteps;
@@ -115,7 +120,7 @@ public class DefaultSource extends ISOMe
* @param description A detailed description of the level of the source
data, or {@code null}.
*/
public DefaultSource(final CharSequence description) {
- this.description = Types.toInternationalString(description);
+ descriptionOrExtents = Types.toInternationalString(description);
}
/**
@@ -123,20 +128,26 @@ public class DefaultSource extends ISOMe
* This is a <cite>shallow</cite> copy constructor, since the other
metadata contained in the
* given object are not recursively copied.
*
+ * <p>If both {@linkplain #getSourceExtents() source extents} and
{@linkplain #getDescription()
+ * description} are specified, then the source extents will have
precedence and the description
+ * is silently discarded.</p>
+ *
* @param object The metadata to copy values from.
*
* @see #castOrCopy(Source)
*/
public DefaultSource(final Source object) {
super(object);
- description = object.getDescription();
+ descriptionOrExtents = object.getDescription();
scaleDenominator = object.getScaleDenominator();
sourceCitation = object.getSourceCitation();
- sourceExtents = copyCollection(object.getSourceExtents(),
Extent.class);
sourceSteps = copyCollection(object.getSourceSteps(),
ProcessStep.class);
processedLevel = object.getProcessedLevel();
resolution = object.getResolution();
sourceReferenceSystem = object.getSourceReferenceSystem();
+ if (descriptionOrExtents == null) {
+ descriptionOrExtents = copyCollection(object.getSourceExtents(),
Extent.class);
+ }
}
/**
@@ -165,22 +176,37 @@ public class DefaultSource extends ISOMe
}
/**
+ * Invoked every time the code needs to decide whether the provided
information
+ * is description or source extents. Defined as a method in order to have
a single
+ * word to search if we need to revisit the policy.
+ */
+ private boolean isDescription() {
+ return (descriptionOrExtents instanceof InternationalString);
+ }
+
+ /**
* Returns a detailed description of the level of the source data.
*/
@Override
@XmlElement(name = "description")
public synchronized InternationalString getDescription() {
- return description;
+ return isDescription() ? (InternationalString) descriptionOrExtents :
null;
}
/**
* Sets a detailed description of the level of the source data.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-null, then this method
automatically
+ * discards the {@linkplain #setSourceExtents source extents} collection.
+ *
* @param newValue The new description.
*/
public synchronized void setDescription(final InternationalString
newValue) {
checkWritePermission();
- description = newValue;
+ if (newValue != null || isDescription()) {
+ descriptionOrExtents = newValue;
+ }
}
/**
@@ -242,22 +268,40 @@ public class DefaultSource extends ISOMe
}
/**
- * Returns tiInformation about the spatial, vertical and temporal extent
- * of the source data.
+ * Returns the information about the spatial, vertical and temporal extent
of the source data.
+ *
+ * {@section Conditions}
+ * This method returns a modifiable collection only if the {@linkplain
#getDescription()
+ * description} is not set. Otherwise, this method returns an unmodifiable
empty collection.
*/
@Override
@XmlElement(name = "sourceExtent")
public synchronized Collection<Extent> getSourceExtents() {
- return sourceExtents = nonNullCollection(sourceExtents, Extent.class);
+ if (isDescription()) {
+ return isMarshaling() ? null : new
ExcludedSet<Extent>("sourceExtent", "description");
+ }
+ @SuppressWarnings("unchecked")
+ Collection<Extent> sourceExtents = (Collection<Extent>)
descriptionOrExtents;
+ sourceExtents = nonNullCollection(sourceExtents, Extent.class);
+ descriptionOrExtents = sourceExtents;
+ return sourceExtents;
}
/**
* Information about the spatial, vertical and temporal extent of the
source data.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-null, then this method
automatically
+ * discards the {@linkplain #setDescription description}.
+ *
* @param newValues The new source extents.
*/
public synchronized void setSourceExtents(final Collection<? extends
Extent> newValues) {
- sourceExtents = writeCollection(newValues, sourceExtents,
Extent.class);
+ @SuppressWarnings("unchecked")
+ final Collection<Extent> sourceExtents = isDescription() ? null :
(Collection<Extent>) descriptionOrExtents;
+ if (sourceExtents != null || !isNullOrEmpty(newValues)) {
+ descriptionOrExtents = writeCollection(newValues, sourceExtents,
Extent.class);
+ }
}
/**
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -24,11 +24,23 @@ import org.opengis.feature.type.Attribut
import org.opengis.feature.type.FeatureType;
import org.opengis.metadata.maintenance.ScopeDescription;
import org.apache.sis.metadata.iso.ISOMetadata;
+import org.apache.sis.internal.metadata.ExcludedSet;
+import org.apache.sis.util.collection.CheckedContainer;
+
+import static org.apache.sis.internal.jaxb.MarshalContext.isMarshaling;
+import static org.apache.sis.util.collection.CollectionsExt.isNullOrEmpty;
/**
* Description of the class of information covered by the information.
*
+ * {@section Relationship between properties}
+ * ISO 19115 defines {@code ScopeDescription} as an <cite>union</cite> (in the
C/C++ sense):
+ * only one of the properties in this class can be set to a non-empty value.
+ * Setting any property to a non-empty value discard all the other ones.
+ * See the {@linkplain #DefaultScopeDescription(ScopeDescription) constructor
javadoc}
+ * for information about which property has precedence on copy operations.
+ *
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Touraïvane (IRD)
* @author Cédric Briançon (Geomatys)
@@ -48,35 +60,41 @@ public class DefaultScopeDescription ext
private static final long serialVersionUID = -5671299759930976286L;
/**
- * The attributes to which the information applies.
- */
- private Set<AttributeType> attributes;
-
- /**
- * The features to which the information applies.
+ * Enumeration of possible values for {@link #property}.
*/
- private Set<FeatureType> features;
+ private static final byte ATTRIBUTES=1, FEATURES=2, FEATURE_INSTANCES=3,
ATTRIBUTE_INSTANCES=4, DATASET=5, OTHER=6;
/**
- * The feature instances to which the information applies.
+ * The names of the mutually exclusive properties. The index of each name
shall be the
+ * value of the above {@code byte} constants minus one.
*/
- private Set<FeatureType> featureInstances;
+ private static final String[] NAMES = {
+ "attributes",
+ "features",
+ "featureInstances",
+ "attributeInstances",
+ "dataset",
+ "other"
+ };
/**
- * The attribute instances to which the information applies.
+ * Specifies which property is set, or 0 if none.
*/
- private Set<AttributeType> attributeInstances;
+ private byte property;
/**
- * Dataset to which the information applies.
- */
- private String dataset;
-
- /**
- * Class of information that does not fall into the other categories to
- * which the information applies.
+ * The value, as one of the following types:
+ *
+ * <ul>
+ * <li>{@code Set<AttributeType>} for the {@code attributes}
property</li>
+ * <li>{@code Set<FeatureType>} for the {@code features} property</li>
+ * <li>{@code Set<FeatureType>} for the {@code featureInstances}
property</li>
+ * <li>{@code Set<AttributeType>} for the {@code attributeInstances}
property</li>
+ * <li>{@code String} for the {@code dataset} property</li>
+ * <li>{@code String} for the {@code other} property</li>
+ * </ul>
*/
- private String other;
+ private Object value;
/**
* Creates an initially empty scope description.
@@ -89,18 +107,48 @@ public class DefaultScopeDescription ext
* This is a <cite>shallow</cite> copy constructor, since the other
metadata contained in the
* given object are not recursively copied.
*
+ * <p>If the given object contains more than one value, then the first
non-null element in the
+ * following list has precedence: {@linkplain #getAttributes() attributes},
+ * {@linkplain #getFeatures() features}, {@linkplain
#getFeatureInstances() feature instances},
+ * {@linkplain #getAttributeInstances() attribute instances}, {@linkplain
#getDataset() dataset}
+ * and {@linkplain #getOther() other}.</p>
+ *
* @param object The metadata to copy values from.
*
* @see #castOrCopy(ScopeDescription)
*/
+ @SuppressWarnings("unchecked")
public DefaultScopeDescription(final ScopeDescription object) {
super(object);
- dataset = object.getDataset();
- other = object.getOther();
- attributeInstances = copySet(object.getAttributeInstances(),
AttributeType.class);
- attributes = copySet(object.getAttributes(),
AttributeType.class);
- featureInstances = copySet(object.getFeatureInstances(),
FeatureType.class);
- features = copySet(object.getFeatures(), FeatureType.class);
+ for (byte i=ATTRIBUTES; i<=OTHER; i++) {
+ Object candidate;
+ switch (i) {
+ case ATTRIBUTES: candidate = object.getAttributes();
break;
+ case FEATURES: candidate = object.getFeatures();
break;
+ case FEATURE_INSTANCES: candidate =
object.getFeatureInstances(); break;
+ case ATTRIBUTE_INSTANCES: candidate =
object.getAttributeInstances(); break;
+ case DATASET: candidate = object.getDataset();
break;
+ case OTHER: candidate = object.getOther();
break;
+ default: throw new AssertionError(i);
+ }
+ if (candidate != null) {
+ switch (i) {
+ case ATTRIBUTES:
+ case ATTRIBUTE_INSTANCES: {
+ candidate = copySet((Set<AttributeType>) candidate,
AttributeType.class);
+ break;
+ }
+ case FEATURES:
+ case FEATURE_INSTANCES: {
+ candidate = copySet((Set<FeatureType>) candidate,
FeatureType.class);
+ break;
+ }
+ }
+ value = candidate;
+ property = i;
+ break;
+ }
+ }
}
/**
@@ -129,71 +177,149 @@ public class DefaultScopeDescription ext
}
/**
+ * Returns the given value casted to a {@code Set} of elements of the
given type.
+ * It is caller responsibility to ensure that the cast is valid, as
element type
+ * is verified only when assertions are enabled.
+ */
+ @SuppressWarnings("unchecked")
+ private static <E> Set<E> cast(final Object value, final Class<E> type) {
+ assert ((CheckedContainer<?>) value).getElementType() == type;
+ return (Set<E>) value;
+ }
+
+ /**
+ * Returns the set of properties identified by the {@code code} argument,
+ * or an unmodifiable empty set if another value is defined.
+ */
+ private <E> Set<E> getProperty(final Class<E> type, final byte code) {
+ final Object value = this.value;
+ if (value != null) {
+ if (property == code) {
+ return cast(value, type);
+ } else if (!(value instanceof Set) || !((Set<?>) value).isEmpty())
{
+ return isMarshaling() ? null : new
ExcludedSet<E>(NAMES[code-1], NAMES[property-1]);
+ }
+ }
+ // Unconditionally create a new set, because the
+ // user may hold a reference to the previous one.
+ final Set<E> c = nonNullSet(null, type);
+ property = code;
+ this.value = c;
+ return c;
+ }
+
+ /**
+ * Sets the properties identified by the {@code code} argument, if
non-null and non-empty.
+ * This discards any other properties.
+ */
+ private <E> void setProperty(final Set<? extends E> newValue, final
Class<E> type, final byte code) {
+ Set<E> c = null;
+ if (property == code) {
+ c = cast(value, type);
+ } else if (isNullOrEmpty(newValue)) {
+ return;
+ }
+ value = writeSet(newValue, c, type);
+ }
+
+ /**
* Returns the attributes to which the information applies.
+ *
+ * {@section Conditions}
+ * This method returns a modifiable collection only if no other property
is set.
+ * Otherwise, this method returns an unmodifiable empty collection.
*/
@Override
public synchronized Set<AttributeType> getAttributes() {
- return attributes = nonNullSet(attributes, AttributeType.class);
+ return getProperty(AttributeType.class, ATTRIBUTES);
}
/**
* Sets the attributes to which the information applies.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-empty, then this method
automatically
+ * discards the all other properties.
+ *
* @param newValues The new attributes.
*/
public synchronized void setAttributes(final Set<? extends AttributeType>
newValues) {
- attributes = writeSet(newValues, attributes, AttributeType.class);
+ setProperty(newValues, AttributeType.class, ATTRIBUTES);
}
/**
* Returns the features to which the information applies.
+ *
+ * {@section Conditions}
+ * This method returns a modifiable collection only if no other property
is set.
+ * Otherwise, this method returns an unmodifiable empty collection.
*/
@Override
public synchronized Set<FeatureType> getFeatures() {
- return features = nonNullSet(features, FeatureType.class);
+ return getProperty(FeatureType.class, FEATURES);
}
/**
* Sets the features to which the information applies.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-empty, then this method
automatically
+ * discards the all other properties.
+ *
* @param newValues The new features.
*/
public synchronized void setFeatures(final Set<? extends FeatureType>
newValues) {
- features = writeSet(newValues, features, FeatureType.class);
+ setProperty(newValues, FeatureType.class, FEATURES);
}
/**
* Returns the feature instances to which the information applies.
+ *
+ * {@section Conditions}
+ * This method returns a modifiable collection only if no other property
is set.
+ * Otherwise, this method returns an unmodifiable empty collection.
*/
@Override
public synchronized Set<FeatureType> getFeatureInstances() {
- return featureInstances = nonNullSet(featureInstances,
FeatureType.class);
+ return getProperty(FeatureType.class, FEATURE_INSTANCES);
}
/**
* Sets the feature instances to which the information applies.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-empty, then this method
automatically
+ * discards the all other properties.
+ *
* @param newValues The new feature instances.
*/
public synchronized void setFeatureInstances(final Set<? extends
FeatureType> newValues) {
- featureInstances = writeSet(newValues, featureInstances,
FeatureType.class);
+ setProperty(newValues, FeatureType.class, FEATURE_INSTANCES);
}
/**
* Returns the attribute instances to which the information applies.
+ *
+ * {@section Conditions}
+ * This method returns a modifiable collection only if no other property
is set.
+ * Otherwise, this method returns an unmodifiable empty collection.
*/
@Override
public synchronized Set<AttributeType> getAttributeInstances() {
- return attributeInstances = nonNullSet(attributeInstances,
AttributeType.class);
+ return getProperty(AttributeType.class, ATTRIBUTE_INSTANCES);
}
/**
* Sets the attribute instances to which the information applies.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-empty, then this method
automatically
+ * discards the all other properties.
+ *
* @param newValues The new attribute instances.
*/
public synchronized void setAttributeInstances(final Set<? extends
AttributeType> newValues) {
- attributeInstances = writeSet(newValues, attributeInstances,
AttributeType.class);
+ setProperty(newValues, AttributeType.class, ATTRIBUTE_INSTANCES);
}
/**
@@ -202,17 +328,23 @@ public class DefaultScopeDescription ext
@Override
@XmlElement(name = "dataset")
public synchronized String getDataset() {
- return dataset;
+ return (property == DATASET) ? (String) value : null;
}
/**
* Sets the dataset to which the information applies.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-null, then this method
automatically
+ * discards the all other properties.
+ *
* @param newValue The new dataset.
*/
public synchronized void setDataset(final String newValue) {
checkWritePermission();
- dataset = newValue;
+ if (newValue != null || property == DATASET) {
+ value = newValue;
+ }
}
/**
@@ -222,17 +354,23 @@ public class DefaultScopeDescription ext
@Override
@XmlElement(name = "other")
public synchronized String getOther() {
- return other;
+ return (property == OTHER) ? (String) value : null;
}
/**
* Sets the class of information that does not fall into the other
categories to
* which the information applies.
*
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-null, then this method
automatically
+ * discards the all other properties.
+ *
* @param newValue Other class of information.
*/
public synchronized void setOther(final String newValue) {
checkWritePermission();
- other = newValue;
+ if (newValue != null || property == OTHER) {
+ value = newValue;
+ }
}
}
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultDataQuality.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultDataQuality.java?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultDataQuality.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultDataQuality.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -24,12 +24,22 @@ import org.opengis.metadata.lineage.Line
import org.opengis.metadata.quality.DataQuality;
import org.opengis.metadata.quality.Element;
import org.opengis.metadata.quality.Scope;
+import org.apache.sis.internal.metadata.ExcludedSet;
import org.apache.sis.metadata.iso.ISOMetadata;
+import static org.apache.sis.internal.jaxb.MarshalContext.isMarshaling;
+import static org.apache.sis.util.collection.CollectionsExt.isNullOrEmpty;
+
/**
* Quality information for the data specified by a data quality scope.
*
+ * {@section Relationship between properties}
+ * According ISO 19115, the {@linkplain #getLineage() lineage} and {@linkplain
#getReports() reports}
+ * properties are exclusive: setting one of those properties to a non-empty
value discard the other one.
+ * See the {@linkplain #DefaultDataQuality(DataQuality) constructor javadoc}
for information about
+ * which property has precedence on copy operations.
+ *
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Touraïvane (IRD)
* @since 0.3 (derived from geotk-2.1)
@@ -54,18 +64,10 @@ public class DefaultDataQuality extends
private Scope scope;
/**
- * Quantitative quality information for the data specified by the scope.
- * Should be provided only if {@linkplain Scope#getLevel scope level} is
- * {@linkplain org.opengis.metadata.maintenance.ScopeCode#DATASET dataset}.
- */
- private Collection<Element> reports;
-
- /**
- * Non-quantitative quality information about the lineage of the data
specified by the scope.
- * Should be provided only if {@linkplain Scope#getLevel scope level} is
- * {@linkplain org.opengis.metadata.maintenance.ScopeCode#DATASET dataset}.
+ * Either the lineage as a {@link Lineage} instance or the reports
+ * as a {@code Collection<Element>} instance.
*/
- private Lineage lineage;
+ private Object lineageOrReports;
/**
* Constructs an initially empty data quality.
@@ -87,15 +89,21 @@ public class DefaultDataQuality extends
* This is a <cite>shallow</cite> copy constructor, since the other
metadata contained in the
* given object are not recursively copied.
*
+ * <p>If both {@linkplain #getLineage() lineage} and {@linkplain
#getReports() reports} are
+ * specified, then the reports will have precedence and the lineage is
silently discarded.</p>
+ *
* @param object The metadata to copy values from.
*
* @see #castOrCopy(DataQuality)
*/
public DefaultDataQuality(final DataQuality object) {
super(object);
- scope = object.getScope();
- reports = copyCollection(object.getReports(), Element.class);
- lineage = object.getLineage();
+ scope = object.getScope();
+ lineageOrReports = copyCollection(object.getReports(), Element.class);
+ if (lineageOrReports == null) {
+ // Give precedence to quantitative information.
+ lineageOrReports = object.getLineage();
+ }
}
/**
@@ -143,47 +151,78 @@ public class DefaultDataQuality extends
}
/**
- * Returns the quantitative quality information for the data specified by
the
- * scope. Should be provided only if {@linkplain Scope#getLevel scope
level}
- * is {@linkplain org.opengis.metadata.maintenance.ScopeCode#DATASET
dataset}.
+ * Invoked every time the code needs to decide whether the provided
information
+ * is lineage or the reports. Defined as a method in order to have a
single word
+ * to search if we need to revisit the policy.
+ */
+ private boolean isLineage() {
+ return (lineageOrReports instanceof Lineage);
+ }
+
+ /**
+ * Returns the quantitative quality information for the data specified by
the scope.
+ *
+ * {@section Conditions}
+ * This method returns a modifiable collection only if the {@linkplain
#getLineage() lineage}
+ * is not set. Otherwise, this method returns an unmodifiable empty
collection.
+ *
+ * @return The quantitative quality information.
*/
@Override
@XmlElement(name = "report")
public synchronized Collection<Element> getReports() {
- return reports = nonNullCollection(reports, Element.class);
+ if (isLineage()) {
+ return isMarshaling() ? null : new ExcludedSet<Element>("report",
"lineage");
+ }
+ @SuppressWarnings("unchecked")
+ Collection<Element> reports = (Collection<Element>) lineageOrReports;
+ reports = nonNullCollection(reports, Element.class);
+ lineageOrReports = reports;
+ return reports;
}
/**
* Sets the quantitative quality information for the data specified by the
scope.
- * Should be provided only if {@linkplain Scope#getLevel scope level} is
- * {@linkplain org.opengis.metadata.maintenance.ScopeCode#DATASET dataset}.
+ *
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-empty, then this method
automatically
+ * discards the {@linkplain #setLineage lineage}.
*
* @param newValues The new reports.
*/
public synchronized void setReports(final Collection<? extends Element>
newValues) {
- reports = writeCollection(newValues, reports, Element.class);
+ @SuppressWarnings("unchecked")
+ final Collection<Element> reports = isLineage() ? null :
(Collection<Element>) lineageOrReports;
+ if (reports != null || !isNullOrEmpty(newValues)) {
+ lineageOrReports = writeCollection(newValues, reports,
Element.class);
+ }
}
/**
* Returns non-quantitative quality information about the lineage of the
data specified
- * by the scope. Should be provided only if {@linkplain Scope#getLevel
scope level} is
- * {@linkplain org.opengis.metadata.maintenance.ScopeCode#DATASET dataset}.
+ * by the scope. Note that the lineage and the {@linkplain #getReports()
reports} are
+ * mutually exclusive properties.
*/
@Override
@XmlElement(name = "lineage")
public synchronized Lineage getLineage() {
- return lineage;
+ return isLineage() ? (Lineage) lineageOrReports : null;
}
/**
* Sets the non-quantitative quality information about the lineage of the
data specified
- * by the scope. Should be provided only if {@linkplain Scope#getLevel
scope level} is
- * {@linkplain org.opengis.metadata.maintenance.ScopeCode#DATASET dataset}.
+ * by the scope.
+ *
+ * {@section Effect on other properties}
+ * If and only if the {@code newValue} is non-null, then this method
automatically
+ * discards the {@linkplain #setReports reports} collection.
*
* @param newValue The new lineage.
*/
public synchronized void setLineage(final Lineage newValue) {
checkWritePermission();
- lineage = newValue;
+ if (newValue != null || isLineage()) {
+ lineageOrReports = newValue;
+ }
}
}
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultScope.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultScope.java?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultScope.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultScope.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -54,8 +54,7 @@ public class DefaultScope extends ISOMet
private ScopeCode level;
/**
- * Information about the spatial, vertical and temporal extent of the data
specified by the
- * scope.
+ * Information about the spatial, vertical and temporal extent of the data
specified by the scope.
*/
private Extent extent;
@@ -141,8 +140,6 @@ public class DefaultScope extends ISOMet
/**
* Returns detailed descriptions about the level of the data specified by
the scope.
- * Should be defined only if the {@linkplain #getLevel level} is not equal
- * to {@link ScopeCode#DATASET DATASET} or {@link ScopeCode#SERIES SERIES}.
*/
@Override
@XmlElement(name = "levelDescription")
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeorectified.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeorectified.java?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeorectified.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/iso/spatial/DefaultGeorectified.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -36,6 +36,11 @@ import org.apache.sis.xml.Namespaces;
* in the grid can be geolocated given its grid coordinate and the grid
origin, cell spacing,
* and orientation indication of whether or not geographic.
*
+ * {@section Relationship between properties}
+ * According ISO 19115, the {@linkplain #getCheckPointDescription() check
point description}
+ * can be provided only if the {@linkplain #isCheckPointAvailable() check
point availability}
+ * is {@code true}. The setter methods will ensure that this condition is not
violated.
+ *
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Touraïvane (IRD)
* @author Cédric Briançon (Geomatys)
@@ -126,9 +131,6 @@ public class DefaultGeorectified extends
*/
public DefaultGeorectified(final Georectified object) {
super(object);
- if (object.isCheckPointAvailable()) {
- booleans |= CHECK_POINT_MASK;
- }
checkPointDescription = object.getCheckPointDescription();
cornerPoints =
copyList(object.getCornerPoints(), Point.class);
centerPoint = object.getCenterPoint();
@@ -136,6 +138,11 @@ public class DefaultGeorectified extends
transformationDimensionDescription =
object.getTransformationDimensionDescription();
transformationDimensionMapping =
copyCollection(object.getTransformationDimensionMapping(),
InternationalString.class);
checkPoints =
copyCollection(object.getCheckPoints(), GCP.class);
+
+ // checkPointAvailability is required to be 'true' if there is a
description.
+ if (checkPointDescription != null || object.isCheckPointAvailable()) {
+ booleans |= CHECK_POINT_MASK;
+ }
}
/**
@@ -177,6 +184,10 @@ public class DefaultGeorectified extends
* Sets an indication of whether or not geographic position points are
available to test the
* accuracy of the georeferenced grid data.
*
+ * {@section Effect on other properties}
+ * If and only if the given {@code newValue} is {@code false}, then this
method automatically sets
+ * the {@linkplain #setCheckPointDescription check point description}
property to {@code null}.
+ *
* @param newValue {@code true} if check points are available.
*/
public synchronized void setCheckPointAvailable(final boolean newValue) {
@@ -185,12 +196,14 @@ public class DefaultGeorectified extends
booleans |= CHECK_POINT_MASK;
} else {
booleans &= ~CHECK_POINT_MASK;
+ checkPointDescription = null;
}
}
/**
* Returns a description of geographic position points used to test the
accuracy of the
- * georeferenced grid data.
+ * georeferenced grid data. This value is non-null only if {@link
#isCheckPointAvailable()}
+ * returns {@code true}.
*/
@Override
@XmlElement(name = "checkPointDescription")
@@ -202,11 +215,18 @@ public class DefaultGeorectified extends
* Sets the description of geographic position points used to test the
accuracy of the
* georeferenced grid data.
*
+ * {@section Effect on other properties}
+ * If and only if the given {@code newValue} is non-null, then this method
automatically sets
+ * the {@linkplain #setCheckPointAvailable check point availability}
property to {@code true}.
+ *
* @param newValue The new check point description.
*/
public synchronized void setCheckPointDescription(final
InternationalString newValue) {
checkWritePermission();
checkPointDescription = newValue;
+ if (newValue != null) {
+ booleans |= CHECK_POINT_MASK;
+ }
}
/**
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/jaxb/MarshalContext.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -219,6 +219,23 @@ public final class MarshalContext extend
}
/**
+ * Returns {@code true} if XML marshalling is under progress.
+ * This convenience method is implemented by:
+ *
+ * {@preformat java
+ * return isFlagSet(current(), MARSHALING);
+ * }
+ *
+ * Callers should use the {@link #isFlagSet(MarshalContext, int)} method
instead if the
+ * {@code MarshalContext} instance is known, for avoiding a call to {@link
#current()}.
+ *
+ * @return {@code true} if XML marshalling is under progress.
+ */
+ public static boolean isMarshaling() {
+ return isFlagSet(current(), MARSHALING);
+ }
+
+ /**
* Returns {@code true} if the given flag is set.
*
* @param context The current context, or {@code null} if none.
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] Sun Mar 31 21:06:18 2013
@@ -63,6 +63,12 @@ public final class Errors extends Indexe
}
/**
+ * No element can be added to this set because properties ‘{0}’ and
‘{1}’ are mutually
+ * exclusive.
+ */
+ public static final int CanNotAddToExclusiveSet_2 = 87;
+
+ /**
* Can not compute the derivative.
*/
public static final int CanNotComputeDerivative = 44;
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] (original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] Sun Mar 31 21:06:18 2013
@@ -24,6 +24,7 @@
# programmatic parameters do not have to be last in the formatted text, since
each localized message
# can reorder the parameters as they want.
#
+CanNotAddToExclusiveSet_2 = No element can be added to this set because
properties \u2018{0}\u2019 and \u2018{1}\u2019 are mutually exclusive.
CanNotConvertFromType_2 = Can not convert from type \u2018{0}\u2019 to
type \u2018{1}\u2019.
CanNotConvertValue_2 = Can not convert value \u201c{0}\u201d to
type \u2018{1}\u2019.
CanNotComputeDerivative = Can not compute the derivative.
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1463051&r1=1463050&r2=1463051&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] (original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] Sun Mar 31 21:06:18 2013
@@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+CanNotAddToExclusiveSet_2 = Aucun \u00e9l\u00e9ment ne peut \u00eatre
ajout\u00e9 \u00e0 cet ensemble car les propri\u00e9t\u00e9s \u2018{0}\u2019 et
\u2018{1}\u2019 sont mutuellement exclusives.
CanNotConvertFromType_2 = Ne peut pas convertir du type
\u2018{0}\u2019 vers le type \u2018{1}\u2019.
CanNotConvertValue_2 = La valeur \u201c{0}\u201d ne peut pas
\u00eatre convertie vers le type \u2018{1}\u2019.
CanNotComputeDerivative = La d\u00e9riv\u00e9 ne peut pas \u00eatre
calcul\u00e9e.