You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/03/03 11:55:44 UTC

[isis] branch master updated: ISIS-1736 make all property access unmodifiable

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 624300e  ISIS-1736 make all property access unmodifiable
     new e80901a  Merge branch 'master' of https://github.com/apache/isis
624300e is described below

commit 624300e402512a8074aa357e84153e2f083b3ffc
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Mar 3 12:43:04 2018 +0100

    ISIS-1736 make all property access unmodifiable
---
 .../isis/applib/internal/collections/_Sets.java    | 21 ++++++
 .../config/ConfigurationServiceDefault.java        | 76 ++++++++++++++++++----
 2 files changed, 84 insertions(+), 13 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java
index c8067fc..9abbc1e 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java
@@ -116,6 +116,27 @@ public final class _Sets {
 		return keySetView;
 	}
 	
+	// -- SET OPERATIONS
+
+	/**
+	 * Returns the intersection (set theory) of two given sets, not retaining any order.
+	 * @param a
+	 * @param b
+	 * @return non null, unmodifiable
+	 */
+	public static <T> Set<T> intersect(@Nullable Set<T> a, @Nullable Set<T> b) {
+		if(a==null && b==null) {
+			return Collections.emptySet();
+		}
+		if(a==null || b==null) {
+			return Collections.emptySet();
+		}
+		return Collections.unmodifiableSet(
+				a.stream()
+				.filter(b::contains)
+				.collect(Collectors.toSet()) );
+	}
+	
 	// -- 
 
 	
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/config/ConfigurationServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/config/ConfigurationServiceDefault.java
index 2d18a2e..bf21966 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/config/ConfigurationServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/config/ConfigurationServiceDefault.java
@@ -21,7 +21,9 @@ package org.apache.isis.core.metamodel.services.config;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
+import java.util.SortedSet;
 import java.util.TreeSet;
 
 import javax.annotation.PostConstruct;
@@ -29,10 +31,15 @@ import javax.annotation.PostConstruct;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.internal.collections._Lists;
+import org.apache.isis.applib.internal.collections._Maps;
+import org.apache.isis.applib.internal.collections._Sets;
 import org.apache.isis.applib.services.config.ConfigurationProperty;
 import org.apache.isis.applib.services.config.ConfigurationService;
 import org.apache.isis.core.commons.config.IsisConfigurationDefault;
 import org.apache.isis.core.metamodel.services.configinternal.ConfigurationServiceInternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * This is the implementation of the applib's {@link ConfigurationService}, different from the internal
@@ -45,29 +52,68 @@ import org.apache.isis.core.metamodel.services.configinternal.ConfigurationServi
         menuOrder = "" + Integer.MAX_VALUE
 )
 public class ConfigurationServiceDefault implements ConfigurationService {
+	
+	private final Logger LOG = LoggerFactory.getLogger(ConfigurationServiceDefault.class);
 
-    private Map<String, String> properties;
+    private final Map<String, String> properties = _Maps.newHashMap();
 
     @Programmatic
     @PostConstruct
     public void init(final Map<String,String> properties) {
-        this.properties = properties;
+    	Objects.requireNonNull(properties);
+    	Objects.requireNonNull(configurationServiceInternal);
+    	
+    	// [ahuber] not sure which of the two to has precedence ...
+    	final Map<String, String> a = properties;
+    	final Map<String, String> b = configurationServiceInternal.asMap();
+        
+        // ... so we report if there is a clash in configured values
+        {
+        	Set<String> potentialClashKeys = _Sets.intersect(a.keySet(), b.keySet());
+        	
+        	long clashCount = potentialClashKeys.stream()
+        	.filter(key->{
+        		if(!Objects.equals(a.get(key), b.get(key))){
+        			
+        			LOG.warn(String.format("config value clash, having two versions for key '%s': '%s' <--> '%s'", 
+        					key, ""+a.get(key), ""+b.get(key)	));
+        		
+        			return true;
+        		}
+        		return false;
+        	})
+        	.count();
+        	
+        	if(clashCount>0) {
+        		LOG.error("===================================================================");
+        		LOG.error(" config clashes detected, likely a framework bug");
+        		LOG.error("===================================================================");
+        	}
+        	
+        }
+        
+        this.properties.putAll(a);
+        this.properties.putAll(b);
+        
+                
     }
 
     @Programmatic
-    public Set<ConfigurationProperty> allProperties() {
-        final Set<ConfigurationProperty> kv = new TreeSet<>();
-        for (Map.Entry<String, String> propertyPair : properties.entrySet()) {
-            kv.add(new ConfigurationProperty(propertyPair.getKey(),propertyPair.getValue()));
-
-        }
-        return kv;
+    @Override
+    public SortedSet<ConfigurationProperty> allProperties() {
+        final SortedSet<ConfigurationProperty> kv = new TreeSet<>();
+        
+        properties.entrySet().stream()
+        .map(this::toConfigurationProperty)
+        .forEach(kv::add);
+        
+        return java.util.Collections.unmodifiableSortedSet(kv);
     }
 
     @Programmatic
     @Override
     public String getProperty(final String name) {
-        return configurationServiceInternal.getProperty(name);
+        return properties.get(name);
     }
 
     @Programmatic
@@ -80,12 +126,16 @@ public class ConfigurationServiceDefault implements ConfigurationService {
     @Programmatic
     @Override
     public List<String> getPropertyNames() {
-        return configurationServiceInternal.getPropertyNames();
+        return _Lists.unmodifiable(properties.keySet());
     }
 
-
-
     @javax.inject.Inject
     ConfigurationServiceInternal configurationServiceInternal;
+    
+    // -- HELPER
+    
+    private ConfigurationProperty toConfigurationProperty(Map.Entry<String, String> entry) {
+    	return new ConfigurationProperty(entry.getKey(), entry.getValue());
+    }
 
 }

-- 
To stop receiving notification emails like this one, please contact
ahuber@apache.org.