You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2016/01/26 23:46:33 UTC
svn commit: r1726916 - in /sis/branches/JDK8/core:
sis-referencing/src/main/java/org/apache/sis/referencing/
sis-referencing/src/main/java/org/apache/sis/referencing/factory/
sis-referencing/src/test/java/org/apache/sis/referencing/
sis-utility/src/mai...
Author: desruisseaux
Date: Tue Jan 26 22:46:33 2016
New Revision: 1726916
URL: http://svn.apache.org/viewvc?rev=1726916&view=rev
Log:
Log a warning when no factory is available specifically for the requested version.
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java?rev=1726916&r1=1726915&r2=1726916&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java [UTF-8] Tue Jan 26 22:46:33 2016
@@ -62,6 +62,10 @@ final class AuthorityFactories<T extends
new AuthorityFactories<>(DatumAuthorityFactory.class),
new AuthorityFactories<>(CoordinateOperationAuthorityFactory.class))
{
+ /** Anonymous constructor */ {
+ setLenient(true);
+ }
+
@Override
public void reload() {
EPSG(null);
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1726916&r1=1726915&r2=1726916&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] Tue Jan 26 22:46:33 2016
@@ -23,6 +23,7 @@ import java.util.Collections;
import javax.measure.unit.NonSI;
import org.opengis.util.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
@@ -38,6 +39,7 @@ import org.opengis.referencing.crs.Proje
import org.opengis.referencing.crs.TemporalCRS;
import org.opengis.referencing.crs.VerticalCRS;
import org.opengis.referencing.crs.EngineeringCRS;
+import org.opengis.metadata.citation.Citation;
import org.opengis.metadata.extent.Extent;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.apache.sis.internal.metadata.AxisDirections;
@@ -129,6 +131,9 @@ public final class CRS extends Static {
* <li>{@code "http://www.opengis.net/gml/srs/epsg.xml#4326"}</li>
* </ul>
*
+ * The {@link IdentifiedObjects#lookupURN(IdentifiedObject, Citation)} method can be seen
+ * as a converse of this method.
+ *
* @param code The authority code.
* @return The Coordinate Reference System for the given authority code.
* @throws NoSuchAuthorityCodeException If there is no known CRS associated to the given code.
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java?rev=1726916&r1=1726915&r2=1726916&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java [UTF-8] Tue Jan 26 22:46:33 2016
@@ -388,6 +388,8 @@ public final class IdentifiedObjects ext
* String urn = toURN(object.getClass(), getIdentifier(object, authority));
* }
*
+ * This method can be seen as a converse of {@link CRS#forCode(String)}.
+ *
* @param object The object (usually a {@linkplain org.apache.sis.referencing.crs.AbstractCRS
* coordinate reference system}) whose identifier is to be found, or {@code null}.
* @param authority The authority for the identifier to return, or {@code null} for
@@ -433,6 +435,8 @@ public final class IdentifiedObjects ext
* String code = toString(getIdentifier(object, Citations.EPSG));
* }
*
+ * This method can be seen as a converse of {@link CRS#forCode(String)}.
+ *
* @param object The object (usually a {@linkplain org.apache.sis.referencing.crs.AbstractCRS
* coordinate reference system}) whose EPSG code is to be found, or {@code null}.
* @return The EPSG code, or {@code null} if none was found without ambiguity or if the given object was null.
@@ -583,6 +587,8 @@ public final class IdentifiedObjects ext
* The reason why the authorities are restricted to the above white list is because this method formats a URN
* in the OGC namespace. Consequently the URN should use only components recognized by the OGC Naming Authority.
*
+ * <p>The above tables may be expanded in any future SIS version.</p>
+ *
* @param type A type assignable to one of the types listed in above table.
* @param identifier The identifier for which to format a URN, or {@code null}.
* @return The URN for the given identifier, or {@code null} if the given identifier was null
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java?rev=1726916&r1=1726915&r2=1726916&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryIdentifier.java [UTF-8] Tue Jan 26 22:46:33 2016
@@ -124,20 +124,6 @@ final class AuthorityFactoryIdentifier {
private String version;
/**
- * {@code true} if {@code MultiAuthoritiesFactory} found more than one factory for this identifier.
- * This is rarely needed, unless there is a configuration problem. This information is ignored by
- * all methods in this class except {@link #conflict(AuthorityFactory)}, which use this field only
- * for avoiding to log the same message twice.
- *
- * <p>This field does not need to be declared {@code volatile} because {@code MultiAuthoritiesFactory}
- * will read and write this field (indirectly, though a call to {@code logConflictWarning(…)} only in
- * a {@code synchronized} block.</p>
- *
- * @see #logConflictWarning(AuthorityFactory)
- */
- private boolean hasLoggedWarning;
-
- /**
* Creates a new identifier for a factory of the given type, authority and version.
* The given authority shall be already in upper cases and the version in lower cases
* (this is not verified by this constructor).
@@ -187,7 +173,7 @@ final class AuthorityFactoryIdentifier {
* Creates a new identifier for the same type and authority than this identifier, but a different version
* extracted from the given authority.
*
- * @param factory The factory's authority.
+ * @param factory The factory's authority, or {@code null} for creating an identifier without version.
* @return An identifier for the version of the given authority, or {@code this} if the version is the same.
*/
AuthorityFactoryIdentifier versionOf(final Citation factory) {
@@ -252,7 +238,7 @@ final class AuthorityFactoryIdentifier {
/**
* Returns the authority with the version, if any.
*/
- CharSequence getAuthority() {
+ CharSequence getAuthorityAndVersion() {
CharSequence name = authority;
if (hasVersion()) {
name = Vocabulary.formatInternational(Vocabulary.Keys.Version_2, name, version);
@@ -270,19 +256,31 @@ final class AuthorityFactoryIdentifier {
/**
* Logs a message reporting a conflict between the factory identified by this {@code AuthorityFactoryIdentifier}
* and another factory, if this instance has not already logged a warning. This method assumes that it is invoked
- * by the {@code MultiAuthoritiesFactory.getAuthorityFactory(…)} method in a synchronized block.
+ * by the {@code MultiAuthoritiesFactory.getAuthorityFactory(…)} method.
*
* @param used The factory which will be used.
*/
- void logConflictWarning(final AuthorityFactory used) {
- if (!hasLoggedWarning) {
- hasLoggedWarning = true;
- final LogRecord record = Messages.getResources(null).getLogRecord(Level.WARNING,
- Messages.Keys.IgnoredServiceProvider_3, TYPES[type], getAuthority(), Classes.getClass(used));
- record.setLoggerName(Loggers.CRS_FACTORY);
- // MultiAuthoritiesFactory.getAuthorityFactory(…) is the nearest public API.
- Logging.log(MultiAuthoritiesFactory.class, "getAuthorityFactory", record);
- }
+ void logConflict(final AuthorityFactory used) {
+ log(Messages.getResources(null).getLogRecord(Level.WARNING, Messages.Keys.IgnoredServiceProvider_3,
+ TYPES[type], getAuthorityAndVersion(), Classes.getClass(used)));
+ }
+
+ /**
+ * Logs a warning about a factory not found for the requested version, in which case
+ * {@code AuthorityFactoryIdentifier} fallback on a default version.
+ */
+ void logFallback() {
+ log(Messages.getResources(null).getLogRecord(Level.WARNING, Messages.Keys.FallbackDefaultFactoryVersion_2,
+ authority, version));
+ }
+
+ /**
+ * Do the logging of the warning prepared by the above methods.
+ */
+ private void log(final LogRecord record) {
+ record.setLoggerName(Loggers.CRS_FACTORY);
+ // MultiAuthoritiesFactory.getAuthorityFactory(…) is the nearest public API.
+ Logging.log(MultiAuthoritiesFactory.class, "getAuthorityFactory", record);
}
/**
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java?rev=1726916&r1=1726915&r2=1726916&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] Tue Jan 26 22:46:33 2016
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.IdentityHashMap;
@@ -159,6 +160,20 @@ public class MultiAuthoritiesFactory ext
private volatile Set<String> codeSpaces;
/**
+ * Whether this factory should relax some rules when processing a given authority code.
+ * See {@link #isLenient()} javadoc for a description of relaxed rules.
+ *
+ * @see #isLenient()
+ */
+ private volatile boolean isLenient;
+
+ /**
+ * The factories for which we have logged a warning. This is used in order to avoid logging the same
+ * warnings many time. We do not bother using a concurrent map here since this map should be rarely used.
+ */
+ private final Map<AuthorityFactoryIdentifier, Boolean> warnings;
+
+ /**
* Creates a new multi-factories instance using the given lists of factories.
* Calls to {@code createFoo(String)} methods will scan the supplied factories in their iteration order when first needed.
* The first factory having the requested {@linkplain GeodeticAuthorityFactory#getCodeSpaces() namespace} will be used.
@@ -210,10 +225,39 @@ public class MultiAuthoritiesFactory ext
}
providers = ArraysExt.resize(p, length);
factories = new ConcurrentHashMap<>();
+ warnings = new HashMap<>();
isIterationCompleted = new AtomicInteger(nullMask);
}
/**
+ * Returns whether this factory should relax some rules when processing a given authority code.
+ * If this value is {@code true}, then the behavior of this {@code MultiAuthoritiesFactory}
+ * is changed as below:
+ *
+ * <ul>
+ * <li>If a version is specified in a URN but there is no factory for that specific version,
+ * then fallback on a factory for the same authority but the default version.</li>
+ * </ul>
+ *
+ * The default value is {@code false}, which means that an exception will be thrown
+ * if there is no factory specifically for the requested version.
+ *
+ * @return Whether this factory should relax some rules when processing a given authority code.
+ */
+ public boolean isLenient() {
+ return isLenient;
+ }
+
+ /**
+ * Sets whether this factory should relax some rules when processing a given code.
+ *
+ * @param lenient Whether this factory should relax some rules when processing a given authority code.
+ */
+ public void setLenient(final boolean lenient) {
+ isLenient = lenient;
+ }
+
+ /**
* Returns the database or specification that defines the codes recognized by this factory.
* The default implementation returns {@code null} since {@code MultiAuthoritiesFactory} is not
* about a particular authority.
@@ -593,19 +637,10 @@ public class MultiAuthoritiesFactory ext
}
/*
* If there is a conflict, log a warning provided that we did not already reported
- * that conflict. The flag telling us if we already logged a warning is in the key,
- * so we have to find that key in the loop below. This is inefficient, but conflict
- * should not happen in a sane environment.
+ * that conflict.
*/
- if (factory != cached) {
- for (final AuthorityFactoryIdentifier identifier : factories.keySet()) {
- if (identifier.equals(versioned)) {
- synchronized (provider) {
- identifier.logConflictWarning(cached);
- }
- break;
- }
- }
+ if (factory != cached && canLog(versioned)) {
+ versioned.logConflict(cached);
}
if (request.equals(versioned)) {
return cached;
@@ -654,11 +689,34 @@ public class MultiAuthoritiesFactory ext
doneMask = isIterationCompleted.get();
}
}
- final String authority = request.getAuthority().toString();
+ /*
+ * No factory found. Before to fail, search for a factory for the default version if we are allowed to.
+ */
+ if (request.hasVersion() && isLenient) {
+ factory = getAuthorityFactory(request.versionOf(null));
+ if (canLog(request)) {
+ request.logFallback();
+ }
+ return factory;
+ }
+ final String authority = request.getAuthorityAndVersion().toString();
throw new NoSuchAuthorityFactoryException(Errors.format(Errors.Keys.UnknownAuthority_1, authority), authority);
}
/**
+ * Returns {@code true} if this {@code MultiAuthoritiesFactory} can log a warning for the given factory.
+ */
+ private boolean canLog(AuthorityFactoryIdentifier identifier) {
+ synchronized (warnings) {
+ if (warnings.containsKey(identifier)) {
+ return false;
+ }
+ // Invoke identifier.intern() only if needed.
+ return warnings.putIfAbsent(identifier.intern(), Boolean.TRUE) == null;
+ }
+ }
+
+ /**
* Creates an object from a code using the given proxy.
*
* @param <T> The type of the object to be returned.
Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java?rev=1726916&r1=1726915&r2=1726916&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java [UTF-8] Tue Jan 26 22:46:33 2016
@@ -19,7 +19,11 @@ package org.apache.sis.referencing;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.util.FactoryException;
+import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.test.LoggingWatcher;
import org.apache.sis.test.TestCase;
+import org.apache.sis.util.logging.Logging;
+import org.junit.Rule;
import org.junit.Test;
import static org.apache.sis.test.Assert.*;
@@ -35,6 +39,29 @@ import static org.apache.sis.test.Assert
*/
public final strictfp class AuthorityFactoriesTest extends TestCase {
/**
+ * A JUnit {@linkplain Rule rule} for listening to log events. This field is public because JUnit requires
+ * us to do so, but should be considered as an implementation details (it should have been a private field).
+ */
+ @Rule
+ public final LoggingWatcher listener = new Listener();
+
+ /**
+ * Implementation of the {@link AuthorityFactoriesTest#listener} rule.
+ */
+ private static final class Listener extends LoggingWatcher {
+ /** The logged message. */
+ String message;
+
+ /** Creates a new log listener. */
+ Listener() {super(Logging.getLogger(Loggers.CRS_FACTORY));}
+
+ /** Stores the log message. */
+ @Override protected void verifyMessage(final String message) {
+ this.message = message;
+ }
+ }
+
+ /**
* Tests creation of {@code CRS:84} from various codes.
*
* @throws FactoryException if a CRS:84 creation failed.
@@ -58,4 +85,35 @@ public final strictfp class AuthorityFac
assertNotDeepEquals(crs, CRS.forCode("CRS:83"));
}
+
+ /**
+ * Tests creation of {@code EPSG:4326} from codes for various versions of the EPSG database.
+ * This test verifies the logged messages.
+ *
+ * @throws FactoryException if an EPSG:4326 creation failed.
+ */
+ @Test
+ public void testVersionedEPSG() throws FactoryException {
+ final CRSAuthorityFactory factory = AuthorityFactories.ALL;
+ final GeographicCRS crs = factory.createGeographicCRS("EPSG:4326");
+
+ listener.maximumLogCount = 1;
+ assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG:6.11.2:4326"));
+ assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG:6.11.2:4326"));
+ String message = ((Listener) listener).message;
+ assertTrue(message, message.contains("6.11.2"));
+
+ listener.maximumLogCount = 1;
+ assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG:7.04:4326"));
+ message = ((Listener) listener).message;
+ assertTrue(message, message.contains("7.04"));
+
+ listener.maximumLogCount = 1;
+ assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG:7.10:4326"));
+ message = ((Listener) listener).message;
+ assertTrue(message, message.contains("7.10"));
+
+ assertEquals(0, listener.maximumLogCount);
+ assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG::4326"));
+ }
}
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java?rev=1726916&r1=1726915&r2=1726916&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java [UTF-8] Tue Jan 26 22:46:33 2016
@@ -166,6 +166,12 @@ public final class Messages extends Inde
public static final short DiscardedExclusiveProperty_2 = 2;
/**
+ * There is no factory for version {1} of “{0}” authority. Fallback on default version for
+ * objects creation.
+ */
+ public static final short FallbackDefaultFactoryVersion_2 = 38;
+
+ /**
* Ignored properties after the first occurrence of ‘{0}’.
*/
public static final short IgnoredPropertiesAfterFirst_1 = 6;
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties?rev=1726916&r1=1726915&r2=1726916&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties [ISO-8859-1] Tue Jan 26 22:46:33 2016
@@ -36,6 +36,7 @@ DataDirectoryNotSpecified_1 = The \
DataDirectoryNotWritable_2 = Apache SIS can not write in the \u201c{1}\u201d directory given by the {0} environment variable.
DeprecatedCode_3 = Code \u201c{0}\u201d is deprecated and replaced by code {1}. Reason is: {2}
DiscardedExclusiveProperty_2 = Property \u201c{0}\u201d has been discarded in favor of \u201c{1}\u201d, because those two properties are mutually exclusive.
+FallbackDefaultFactoryVersion_2 = There is no factory for version {1} of \u201c{0}\u201d authority. Fallback on default version for objects creation.
IgnoredPropertiesAfterFirst_1 = Ignored properties after the first occurrence of \u2018{0}\u2019.
IgnoredPropertyAssociatedTo_1 = Ignored property associated to \u2018{0}\u2019.
IgnoredServiceProvider_3 = More than one service provider of type \u2018{0}\u2019 are declared for \u201c{1}\u201d. Only the first provider (an instance of \u2018{2}\u2019) will be used.
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties?rev=1726916&r1=1726915&r2=1726916&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties [ISO-8859-1] Tue Jan 26 22:46:33 2016
@@ -43,6 +43,7 @@ DataDirectoryNotSpecified_1 = La va
DataDirectoryNotWritable_2 = Apache SIS ne peut pas \u00e9crire dans le r\u00e9pertoire \u00ab\u202f{1}\u202f\u00bb sp\u00e9cifi\u00e9e par la variable environnementale {0}.
DeprecatedCode_3 = Le code \u00ab\u202f{0}\u202f\u00bb est d\u00e9pr\u00e9ci\u00e9 et remplac\u00e9 par le code {1}. La raison est\u00a0: {2}
DiscardedExclusiveProperty_2 = La propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb a \u00e9t\u00e9 \u00e9cart\u00e9e en faveur de \u00ab\u202f{1}\u202f\u00bb, parce que ces deux propri\u00e9t\u00e9s sont mutuellement exclusives.
+FallbackDefaultFactoryVersion_2 = Il n\u2019y a pas de fabrique pour la version {1} de l\u2019autorit\u00e9 \u00ab\u202f{0}\u202f\u00bb. Les objets seront cr\u00e9\u00e9s avec la version par d\u00e9faut.
IgnoredPropertiesAfterFirst_1 = Des propri\u00e9t\u00e9s ont \u00e9t\u00e9 ignor\u00e9es apr\u00e8s la premi\u00e8re occurrence de \u2018{0}\u2019.
IgnoredPropertyAssociatedTo_1 = Une propri\u00e9t\u00e9 associ\u00e9e \u00e0 \u2018{0}\u2019 a \u00e9t\u00e9 ignor\u00e9e.
IgnoredServiceProvider_3 = Plusieurs fournisseurs de service de type \u2018{0}\u2019 sont d\u00e9clar\u00e9s pour \u00ab\u202f{1}\u202f\u00bb. Seul le premier fournisseur (une instance de \u2018{2}\u2019) sera utilis\u00e9.