Repository: bval
Updated Branches:
  refs/heads/bv2 313512196 -> 7b915ca2a


ValueExtractors work for TCK and spec compliance


Project: http://git-wip-us.apache.org/repos/asf/bval/repo
Commit: http://git-wip-us.apache.org/repos/asf/bval/commit/b2b1b246
Tree: http://git-wip-us.apache.org/repos/asf/bval/tree/b2b1b246
Diff: http://git-wip-us.apache.org/repos/asf/bval/diff/b2b1b246

Branch: refs/heads/bv2
Commit: b2b1b246133b8cb6636fa273575794e42541b802
Parents: 3135121
Author: Matt Benson <[email protected]>
Authored: Mon Mar 26 17:44:09 2018 -0500
Committer: Matt Benson <[email protected]>
Committed: Mon Mar 26 17:44:09 2018 -0500

----------------------------------------------------------------------
 .../apache/bval/jsr/ApacheValidatorFactory.java |   3 +-
 .../org/apache/bval/jsr/ConfigurationImpl.java  |   4 +-
 .../jsr/valueextraction/ValueExtractors.java    | 109 ++++++++++++-------
 .../main/java/org/apache/bval/util/Lazy.java    |   6 +
 4 files changed, 78 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/bval/blob/b2b1b246/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
----------------------------------------------------------------------
diff --git 
a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java 
b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
index 40849ac..5e5118f 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ApacheValidatorFactory.java
@@ -45,6 +45,7 @@ import org.apache.bval.jsr.metadata.MetadataBuilders;
 import org.apache.bval.jsr.metadata.MetadataSource;
 import org.apache.bval.jsr.util.AnnotationsManager;
 import org.apache.bval.jsr.valueextraction.ValueExtractors;
+import 
org.apache.bval.jsr.valueextraction.ValueExtractors.OnDuplicateContainerElementKey;
 import org.apache.bval.util.CloseableAble;
 import org.apache.bval.util.reflection.Reflection;
 import org.apache.commons.weaver.privilizer.Privilizing;
@@ -87,7 +88,7 @@ public class ApacheValidatorFactory implements 
ValidatorFactory, Cloneable {
     }
 
     private static ValueExtractors 
createBaseValueExtractors(ParticipantFactory participantFactory) {
-        final ValueExtractors result = new ValueExtractors();
+        final ValueExtractors result = new 
ValueExtractors(OnDuplicateContainerElementKey.OVERWRITE);
         
participantFactory.loadServices(ValueExtractor.class).forEach(result::add);
         return result;
     }

http://git-wip-us.apache.org/repos/asf/bval/blob/b2b1b246/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java 
b/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
index d726d4c..20ac2f8 100644
--- a/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
+++ b/bval-jsr/src/main/java/org/apache/bval/jsr/ConfigurationImpl.java
@@ -135,7 +135,7 @@ public class ConfigurationImpl implements 
ApacheValidatorConfiguration, Configur
 
     private final LazyParticipant<ClockProvider> clockProvider = new 
LazyParticipant<>(this::getDefaultClockProvider);
 
-    private final ValueExtractors bootstrapValueExtractors = new 
ValueExtractors();
+    private final ValueExtractors bootstrapValueExtractors = 
ValueExtractors.EMPTY.createChild();
     private final ValueExtractors valueExtractors = 
bootstrapValueExtractors.createChild();
 
     private final Lazy<BootstrapConfiguration> bootstrapConfiguration = new 
Lazy<>(this::createBootstrapConfiguration);
@@ -371,7 +371,7 @@ public class ConfigurationImpl implements 
ApacheValidatorConfiguration, Configur
 
     @Override
     public Set<ValueExtractor<?>> getValueExtractors() {
-        return Collections.unmodifiableSet(new 
LinkedHashSet<>(valueExtractors.getLocalValueExtractors().values()));
+        return Collections.unmodifiableSet(new 
LinkedHashSet<>(valueExtractors.getValueExtractors().values()));
     }
 
     public void deferBootstrapOverrides() {

http://git-wip-us.apache.org/repos/asf/bval/blob/b2b1b246/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java
----------------------------------------------------------------------
diff --git 
a/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java
 
b/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java
index 00577e3..a99cd3d 100644
--- 
a/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java
+++ 
b/bval-jsr/src/main/java/org/apache/bval/jsr/valueextraction/ValueExtractors.java
@@ -26,7 +26,9 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
@@ -52,38 +54,39 @@ import org.apache.bval.util.reflection.TypeUtils;
  * {@link ValueExtractor} collection of some level of a bean validation 
hierarchy.
  */
 public class ValueExtractors {
-    public static final ValueExtractors DEFAULT;
+    public enum OnDuplicateContainerElementKey {
+        EXCEPTION, OVERWRITE;
+    }
+
+    public static final ValueExtractors EMPTY =
+        new ValueExtractors(null, OnDuplicateContainerElementKey.EXCEPTION, 
Collections.emptyMap());
 
+    public static final ValueExtractors DEFAULT;
     static {
-        DEFAULT = new ValueExtractors(null) {
-            {
-                final Properties defaultExtractors = new Properties();
-                try {
-                    
defaultExtractors.load(ValueExtractors.class.getResourceAsStream("DefaultExtractors.properties"));
-                } catch (IOException e) {
-                    throw new IllegalStateException(e);
-                }
-                
split(defaultExtractors.getProperty(ValueExtractor.class.getName())).map(cn -> {
-                    try {
-                        @SuppressWarnings("unchecked")
-                        final Class<? extends ValueExtractor<?>> result =
-                            (Class<? extends ValueExtractor<?>>) 
Reflection.toClass(cn)
-                                .asSubclass(ValueExtractor.class);
-                        return result;
-                    } catch (Exception e) {
-                        throw new IllegalStateException(e);
-                    }
-                }).map(ValueExtractors::newInstance).forEach(super::add);
-
-                
split(defaultExtractors.getProperty(ValueExtractor.class.getName() + 
".container"))
-                    
.flatMap(ValueExtractors::loadValueExtractors).forEach(super::add);
+        final Properties defaultExtractors = new Properties();
+        try {
+            
defaultExtractors.load(ValueExtractors.class.getResourceAsStream("DefaultExtractors.properties"));
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+        final Map<ContainerElementKey, ValueExtractor<?>> m = new TreeMap<>();
+        final Consumer<ValueExtractor<?>> put = ve -> 
m.put(ContainerElementKey.forValueExtractor(ve), ve);
+
+        
split(defaultExtractors.getProperty(ValueExtractor.class.getName())).map(cn -> {
+            try {
+                @SuppressWarnings("unchecked")
+                final Class<? extends ValueExtractor<?>> result =
+                    (Class<? extends ValueExtractor<?>>) 
Reflection.toClass(cn).asSubclass(ValueExtractor.class);
+                return result;
+            } catch (Exception e) {
+                throw new IllegalStateException(e);
             }
+        }).map(ValueExtractors::newInstance).forEach(put);
 
-            @Override
-            public void add(ValueExtractor<?> extractor) {
-                throw new UnsupportedOperationException();
-            }
-        };
+        split(defaultExtractors.getProperty(ValueExtractor.class.getName() + 
".container"))
+            .flatMap(ValueExtractors::loadValueExtractors).forEach(put);
+
+        DEFAULT = new ValueExtractors(null, 
OnDuplicateContainerElementKey.EXCEPTION, Collections.unmodifiableMap(m));
     }
 
     public static Class<?> getExtractedType(ValueExtractor<?> extractor, Type 
target) {
@@ -152,32 +155,56 @@ public class ValueExtractors {
         return c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1);
     }
 
-    private final Lazy<Map<ContainerElementKey, ValueExtractor<?>>> 
valueExtractors = new Lazy<>(HashMap::new);
     private final ValueExtractors parent;
+    private final Lazy<Map<ContainerElementKey, ValueExtractor<?>>> 
valueExtractors = new Lazy<>(TreeMap::new);
+    private final OnDuplicateContainerElementKey 
onDuplicateContainerElementKey;
 
     public ValueExtractors() {
-        this(DEFAULT);
+        this(OnDuplicateContainerElementKey.EXCEPTION);
+    }
+
+    public ValueExtractors(OnDuplicateContainerElementKey 
onDuplicateContainerElementKey) {
+        this(DEFAULT, Validate.notNull(onDuplicateContainerElementKey));
     }
 
-    private ValueExtractors(ValueExtractors parent) {
+    private ValueExtractors(ValueExtractors parent, 
OnDuplicateContainerElementKey onDuplicateContainerElementKey) {
         this.parent = parent;
+        this.onDuplicateContainerElementKey = onDuplicateContainerElementKey;
+    }
+
+    private ValueExtractors(ValueExtractors parent, 
OnDuplicateContainerElementKey onDuplicateContainerElementKey,
+        Map<ContainerElementKey, ValueExtractor<?>> backingMap) {
+        this(parent, onDuplicateContainerElementKey);
+        this.valueExtractors.reset(backingMap);
     }
 
     public ValueExtractors createChild() {
-        return new ValueExtractors(this);
+        return createChild(OnDuplicateContainerElementKey.EXCEPTION);
     }
 
-    public void add(ValueExtractor<?> extractor) {
-        Validate.notNull(extractor);
-        
valueExtractors.get().compute(ContainerElementKey.forValueExtractor(extractor), 
(k, v) -> {
-            Exceptions.raiseIf(v != null, 
ValueExtractorDeclarationException::new,
-                "Multiple context-level %ss specified for %s", f -> 
f.args(ValueExtractor.class.getSimpleName(), k));
-            return extractor;
-        });
+    public ValueExtractors createChild(OnDuplicateContainerElementKey 
onDuplicateContainerElementKey) {
+        return new ValueExtractors(this, onDuplicateContainerElementKey);
     }
 
-    public Map<ContainerElementKey, ValueExtractor<?>> 
getLocalValueExtractors() {
-        return 
valueExtractors.optional().map(Collections::unmodifiableMap).orElseGet(Collections::emptyMap);
+    public void add(ValueExtractor<?> extractor) {
+        Validate.notNull(extractor);
+        final ContainerElementKey key = 
ContainerElementKey.forValueExtractor(extractor);
+        if (key == null) {
+            Exceptions.raise(IllegalStateException::new, "Computed null %s for 
%s",
+                ContainerElementKey.class.getSimpleName(), extractor);
+        }
+        final Map<ContainerElementKey, ValueExtractor<?>> m = 
valueExtractors.get();
+        if (onDuplicateContainerElementKey == 
OnDuplicateContainerElementKey.EXCEPTION) {
+            synchronized (this) {
+                if (m.containsKey(key)) {
+                    Exceptions.raise(ValueExtractorDeclarationException::new,
+                        "Multiple context-level %ss specified for %s", 
ValueExtractor.class.getSimpleName(), key);
+                }
+                m.put(key, extractor);
+            }
+        } else {
+            m.put(key, extractor);
+        }
     }
 
     public Map<ContainerElementKey, ValueExtractor<?>> getValueExtractors() {

http://git-wip-us.apache.org/repos/asf/bval/blob/b2b1b246/bval-jsr/src/main/java/org/apache/bval/util/Lazy.java
----------------------------------------------------------------------
diff --git a/bval-jsr/src/main/java/org/apache/bval/util/Lazy.java 
b/bval-jsr/src/main/java/org/apache/bval/util/Lazy.java
index 4796de3..fbc885b 100644
--- a/bval-jsr/src/main/java/org/apache/bval/util/Lazy.java
+++ b/bval-jsr/src/main/java/org/apache/bval/util/Lazy.java
@@ -39,6 +39,12 @@ public class Lazy<T> implements Supplier<T> {
         return this;
     }
 
+    public synchronized Lazy<T> reset(T value) {
+        this.value = value;
+        this.init = null;
+        return this;
+    }
+
     @Override
     public T get() {
         if (init != null) {

Reply via email to