You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/07/29 20:33:42 UTC

[1/2] isis git commit: ISIS-1051: FacetMethodsBuilder uses new LayoutMetadataReader2 interface to ask reader whether to attempt to load metadata for class. In addition...

Repository: isis
Updated Branches:
  refs/heads/master ceddc2c5b -> c3d348088


ISIS-1051: FacetMethodsBuilder uses new LayoutMetadataReader2 interface to ask reader whether to attempt to load metadata for class.  In addition...

In addition, the LayoutMetadataReaderFromJson now remembers whether it was able to find a layout.json file for a given class, and won't attempt to in future.  Also doesn't use throw/catch of exceptions for control flow.


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

Branch: refs/heads/master
Commit: 405d0ddaf5eb71993822a9a66515ecdbb4b87e54
Parents: ceddc2c
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Jul 29 19:23:25 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed Jul 29 19:23:25 2015 +0100

----------------------------------------------------------------------
 .../layoutmetadata/LayoutMetadataReader2.java   | 100 +++++++++++++++++++
 .../json/LayoutMetadataReaderFromJson.java      |  70 +++++++++----
 .../LayoutMetadataReaderFromPropertyFile.java   |   9 +-
 .../runtimecontext/RuntimeContextAbstract.java  |   5 +
 .../services/ServicesInjectorDefault.java       |  35 +++++--
 .../metamodel/services/ServicesInjectorSpi.java |   2 +
 .../metamodel/spec/SpecificationLoader.java     |   4 +-
 .../spec/SpecificationLoaderDelegator.java      |   4 +
 .../specloader/ObjectReflectorDefault.java      |   4 +
 .../specimpl/FacetedMethodsBuilder.java         |  75 ++++++++++++--
 .../metamodel/facets/ProgrammableReflector.java |   5 +
 11 files changed, 276 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadataReader2.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadataReader2.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadataReader2.java
new file mode 100644
index 0000000..533d13a
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadataReader2.java
@@ -0,0 +1,100 @@
+/**
+ *  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.isis.core.metamodel.layoutmetadata;
+
+public interface LayoutMetadataReader2 extends LayoutMetadataReader {
+
+    public static class Support {
+
+        public static Support entitiesOnly() {
+            return new Support(false,false,false,false,false,false,false);
+        }
+
+        private final boolean interfaces;
+        private final boolean anonymous;
+        private final boolean synthetic;
+        private final boolean array;
+        private final boolean enums;
+        private final boolean applibValueTypes;
+        private final boolean services;
+
+        public Support(final boolean interfaces, final boolean anonymous, final boolean synthetic, final boolean array, final boolean enums, final boolean applibValueTypes, final boolean services) {
+            this.interfaces = interfaces;
+            this.anonymous = anonymous;
+            this.synthetic = synthetic;
+            this.array = array;
+            this.enums = enums;
+            this.applibValueTypes = applibValueTypes;
+            this.services = services;
+        }
+
+        /**
+         * Whether this implementation can provide metadata for interface types.
+         */
+        public boolean interfaces() {
+            return interfaces;
+        }
+
+        /**
+         * Whether this implementation can provide metadata for anonymous classes.
+         */
+        public boolean anonymous() {
+            return anonymous;
+        }
+
+        /**
+         * Whether this implementation can provide metadata for synthetic types.
+         */
+        public boolean synthetic() {
+            return synthetic;
+        }
+
+        /**
+         * Whether this implementation can provide metadata for arrays.
+         */
+        public boolean array() {
+            return array;
+        }
+
+        /**
+         * Whether this implementation can provide metadata for enums.
+         */
+        public boolean enums() {
+            return enums;
+        }
+
+        /**
+         * Whether this implementation can provide metadata for applib value types.
+         */
+        public boolean applibValueTypes() {
+            return applibValueTypes;
+        }
+
+        /**
+         * Whether this implementation can provide metadata for domain services.
+         */
+        public boolean services() {
+            return services;
+        }
+    }
+
+    /**
+     * What types of classes are supported by this implementation.
+     * @return
+     */
+    Support support();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
index eef3db6..4f8f2fa 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/json/LayoutMetadataReaderFromJson.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+
 import com.google.common.base.Function;
 import com.google.common.base.Joiner;
 import com.google.common.base.Strings;
@@ -32,6 +33,10 @@ import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.apache.isis.applib.annotation.MemberGroupLayout.ColumnSpans;
 import org.apache.isis.applib.annotation.Render;
 import org.apache.isis.applib.annotation.Render.Type;
@@ -49,8 +54,8 @@ import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
 import org.apache.isis.core.metamodel.facets.members.render.RenderFacet;
 import org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet;
 import org.apache.isis.core.metamodel.facets.object.paged.PagedFacet;
-import org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.multiline.MultiLineFacet;
+import org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet;
 import org.apache.isis.core.metamodel.layout.memberorderfacet.MemberOrderFacetComparator;
 import org.apache.isis.core.metamodel.layoutmetadata.ActionLayoutFacetRepr;
 import org.apache.isis.core.metamodel.layoutmetadata.ActionRepr;
@@ -62,7 +67,7 @@ import org.apache.isis.core.metamodel.layoutmetadata.DescribedAsFacetRepr;
 import org.apache.isis.core.metamodel.layoutmetadata.DisabledFacetRepr;
 import org.apache.isis.core.metamodel.layoutmetadata.HiddenFacetRepr;
 import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadata;
-import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader;
+import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader2;
 import org.apache.isis.core.metamodel.layoutmetadata.MemberGroupRepr;
 import org.apache.isis.core.metamodel.layoutmetadata.MemberRepr;
 import org.apache.isis.core.metamodel.layoutmetadata.MultiLineFacetRepr;
@@ -79,15 +84,21 @@ import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 
-public class LayoutMetadataReaderFromJson implements LayoutMetadataReader {
+public class LayoutMetadataReaderFromJson implements LayoutMetadataReader2 {
 
-        public Properties asProperties(final Class<?> domainClass) {
-        final LayoutMetadata metadata;
-        try {
-            metadata = readMetadata(domainClass);
-        } catch (final Exception e) {
-            throw new ReaderException("Failed to locate/parse " + domainClass.getName() + ".layout.json file (" + e.getMessage() + ")", e);
+    private static final Logger LOG = LoggerFactory.getLogger(LayoutMetadataReaderFromJson.class);
+
+    @Override
+    public Support support() {
+        return Support.entitiesOnly();
+    }
+
+    public Properties asProperties(final Class<?> domainClass) {
+        final LayoutMetadata metadata = readMetadata(domainClass);
+        if(metadata == null) {
+            return null;
         }
+
         if(metadata.getColumns() == null || metadata.getColumns().size() != 4) {
             throw new ReaderException("JSON metadata must have precisely 4 columns (prop/prop/prop/coll)");
         }
@@ -380,19 +391,42 @@ public class LayoutMetadataReaderFromJson implements LayoutMetadataReader {
         }
     }
 
-    public LayoutMetadata asLayoutMetadata(final Class<?> domainClass) throws ReaderException {
-        try {
-            return readMetadata(domainClass);
-        } catch (IOException | RuntimeException e) {
-            throw new ReaderException(e);
-        }
+    public LayoutMetadata asLayoutMetadata(final Class<?> domainClass)  {
+        return readMetadata(domainClass);
     }
 
     // //////////////////////////////////////
 
-    private LayoutMetadata readMetadata(final Class<?> domainClass) throws IOException {
-        final String content = ClassExtensions.resourceContent(domainClass, ".layout.json");
-        return readMetadata(content);
+    private final Set<Class<?>> blacklisted = Sets.newConcurrentHashSet();
+
+    private LayoutMetadata readMetadata(final Class<?> domainClass) {
+        final String content;
+
+        if(blacklisted.contains(domainClass)) {
+            return null;
+        }
+        try {
+            content = ClassExtensions.resourceContent(domainClass, ".layout.json");
+        } catch (IOException | IllegalArgumentException ex) {
+
+            blacklisted.add(domainClass);
+            final String message = "Failed to locate " + domainClass.getName() + ".layout.json file (" + ex.getMessage() + ")";
+
+            LOG.debug(message);
+            return null;
+        }
+
+        try {
+            return readMetadata(content);
+        } catch(Exception ex) {
+
+            // note that we don't blacklist if the file exists but couldn't be parsed;
+            // the developer might fix so we will want to retry.
+            final String message = "Failed to parse " + domainClass.getName() + ".layout.json file (" + ex.getMessage() + ")";
+            LOG.warn(message);
+
+            return null;
+        }
     }
 
     LayoutMetadata readMetadata(final String content) {

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java
index d00aed2..cdde18d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/propfile/LayoutMetadataReaderFromPropertyFile.java
@@ -19,9 +19,14 @@ package org.apache.isis.core.metamodel.layoutmetadata.propfile;
 import java.util.Properties;
 
 import org.apache.isis.core.commons.lang.ClassExtensions;
-import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader;
+import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader2;
 
-public class LayoutMetadataReaderFromPropertyFile implements LayoutMetadataReader {
+public class LayoutMetadataReaderFromPropertyFile implements LayoutMetadataReader2 {
+
+    @Override
+    public Support support() {
+        return Support.entitiesOnly();
+    }
 
     @Override
     public Properties asProperties(Class<?> domainClass) throws ReaderException {

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
index 93751bc..ea13704 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
@@ -140,6 +140,11 @@ public abstract class RuntimeContextAbstract implements RuntimeContext, Specific
             }
 
             @Override
+            public boolean isServiceClass(Class<?> cls) {
+                return specificationLoader.isServiceClass(cls);
+            }
+
+            @Override
             public void invalidateCache(Class<?> domainClass) {
                 specificationLoader.invalidateCache(domainClass);
             }

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
index 409f8c5..1fa3dcf 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
@@ -26,13 +26,17 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+
 import javax.inject.Inject;
+
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
 import org.apache.isis.core.commons.ensure.Assert;
 import org.apache.isis.core.commons.lang.ObjectExtensions;
 import org.apache.isis.core.commons.util.ToString;
@@ -53,10 +57,12 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
     private final List<Object> services = Lists.newArrayList();
 
     /**
-     * If no key, not yet searched for type; otherwise the {@link List} indicates
-     * whether a service was found.
+     * If no key, not yet searched for type; otherwise the corresponding value is a {@link List} of all
+     * services that are assignable to the type.  It's possible that this is an empty list.
      */
-    private final Map<Class<?>, List<Object>> servicesByType = Maps.newHashMap();
+    private final Map<Class<?>, List<Object>> servicesAssignableToType = Maps.newHashMap();
+
+    private final Map<Class<?>, Object> serviceByConcreteType = Maps.newHashMap();
 
     public ServicesInjectorDefault() {
         this(null);
@@ -110,12 +116,25 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
         }
 
         services.add(replacementService);
-        // invalidate cache
-        servicesByType.clear();
+
+        // invalidate
+        servicesAssignableToType.clear();
+        serviceByConcreteType.clear();
 
         autowireServicesAndContainer();
     }
 
+    @Override
+    public boolean isRegisteredService(final Class<?> cls) {
+        // lazily construct cache
+        if(serviceByConcreteType.isEmpty()) {
+            for (Object service : services) {
+                final Class<?> concreteType = service.getClass();
+                serviceByConcreteType.put(concreteType, service);
+            }
+        }
+        return serviceByConcreteType.containsKey(cls);
+    }
 
     @Override
     public List<Object> getRegisteredServices() {
@@ -308,18 +327,18 @@ public class ServicesInjectorDefault implements ServicesInjectorSpi, Specificati
     @Override
     public <T> List<T> lookupServices(final Class<T> serviceClass) {
         locateAndCache(serviceClass);
-        return (List<T>) servicesByType.get(serviceClass);
+        return (List<T>) servicesAssignableToType.get(serviceClass);
     };
 
     private void locateAndCache(final Class<?> serviceClass) {
-        if(servicesByType.containsKey(serviceClass)) {
+        if(servicesAssignableToType.containsKey(serviceClass)) {
            return; 
         }
 
         final List<Object> matchingServices = Lists.newArrayList();
         addAssignableTo(serviceClass, services, matchingServices);
 
-        servicesByType.put(serviceClass, matchingServices);
+        servicesAssignableToType.put(serviceClass, matchingServices);
     }
 
     private static void addAssignableTo(final Class<?> type, final List<Object> candidates, final List<Object> filteredServicesAndContainer) {

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
index e50e2b8..dd351cd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorSpi.java
@@ -51,4 +51,6 @@ public interface ServicesInjectorSpi extends ApplicationScopedComponent, Injecta
      * @param replacementService
      */
     <T> void replaceService(T originalService, T replacementService);
+
+    boolean isRegisteredService(Class<?> cls);
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
index 4bf99c1..9bfe890 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoader.java
@@ -67,7 +67,9 @@ public interface SpecificationLoader extends Injectable, InjectorMethodEvaluator
 
 
     List<Class<?>> getServiceClasses();
-    
+
+    boolean isServiceClass(Class<?> cls);
+
     /**
      * Whether this class has been loaded.
      */

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java
index 7418f17..7dec35b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderDelegator.java
@@ -84,6 +84,10 @@ public class SpecificationLoaderDelegator extends SpecificationLoaderAbstract {
     public List<Class<?>> getServiceClasses() {
         return specificationLoaderDelegate.getServiceClasses();
     }
+    @Override
+    public boolean isServiceClass(Class<?> cls) {
+        return specificationLoaderDelegate.isServiceClass(cls);
+    }
 
     @Override
     public void invalidateCache(Class<?> domainClass) {

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
index 20b247d..9cb6f24 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
@@ -634,6 +634,10 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App
         return Collections.unmodifiableList(Lists.newArrayList(serviceClasses));
     }
 
+    public boolean isServiceClass(Class<?> cls) {
+        return this.servicesInjector.isRegisteredService(cls);
+    }
+
     @Override
     public void setServiceInjector(final ServicesInjectorSpi services) {
         servicesInjector = services;

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/FacetedMethodsBuilder.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
index 80fa2db..9628a34 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
@@ -25,12 +25,16 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+
 import com.google.common.collect.Lists;
-import com.google.gson.JsonSyntaxException;
+import com.google.common.collect.Maps;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.lang.ListExtensions;
 import org.apache.isis.core.commons.lang.MethodUtil;
@@ -47,6 +51,7 @@ import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.isis.core.metamodel.facets.object.facets.FacetsFacet;
 import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader;
 import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader.ReaderException;
+import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader2;
 import org.apache.isis.core.metamodel.methodutils.MethodScope;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
@@ -128,6 +133,7 @@ public class FacetedMethodsBuilder {
     private final SpecificationLoaderSpi specificationLoader;
 
     private final List<LayoutMetadataReader> layoutMetadataReaders;
+    private final Map<LayoutMetadataReader, LayoutMetadataReader2.Support> supportByReader;
 
 
     // ////////////////////////////////////////////////////////////////////////////
@@ -149,6 +155,16 @@ public class FacetedMethodsBuilder {
         this.specificationLoader = facetedMethodsBuilderContext.specificationLoader;
 
         this.layoutMetadataReaders = facetedMethodsBuilderContext.layoutMetadataReaders;
+
+        this.supportByReader = Maps.newHashMap();
+        for (LayoutMetadataReader reader : layoutMetadataReaders) {
+
+            if(reader instanceof LayoutMetadataReader2) {
+                final LayoutMetadataReader2 reader2 = (LayoutMetadataReader2) reader;
+                final LayoutMetadataReader2.Support support = reader2.support();
+                supportByReader.put(reader, support);
+            }
+        }
     }
 
     @Override
@@ -206,22 +222,65 @@ public class FacetedMethodsBuilder {
     private Properties readMetadataProperties(final Class<?> domainClass) {
         for (final LayoutMetadataReader reader : layoutMetadataReaders) {
             try {
+                // ignore JDK, Joda and Guava classes
+                if(isPrimitiveOrJdkOrJodaOrGuava(domainClass)) {
+                    continue;
+                }
+
+                // skip class if the reader doesn't support it
+                final LayoutMetadataReader2.Support support = supportByReader.get(reader);
+                if(support != null) {
+
+                    if (!support.interfaces() && domainClass.isInterface()) {
+                        continue;
+                    }
+
+                    if (!support.anonymous() && domainClass.isAnonymousClass()) {
+                        continue;
+                    }
+
+                    if (!support.synthetic() && domainClass.isSynthetic()) {
+                        continue;
+                    }
+
+                    if (!support.array() && domainClass.isArray()) {
+                        continue;
+                    }
+
+                    if (!support.enums() && domainClass.isEnum()) {
+                        continue;
+                    }
+
+                    if (!support.applibValueTypes() && domainClass.getName().startsWith("org.apache.isis.applib.value")) {
+                        continue;
+                    }
+
+                    if(!support.services() &&
+                       getSpecificationLoader().isServiceClass(domainClass)) {
+                        continue;
+                    }
+
+                }
+
                 Properties properties = reader.asProperties(domainClass);
                 if(properties != null) {
                     return properties;
                 }
-            } catch(final ReaderException ex) {
-                final String message = reader.toString() +": unable to load layout metadata for " + domainClass.getName() + " (" + ex.getMessage() + ")";
-                if(ex.getCause() instanceof JsonSyntaxException) {
-                    LOG.warn(message);
-                } else {
-                    LOG.debug(message);
-                }
+            } catch(final ReaderException ignore) {
+                // ignore... it is now the responsibility of the reader to LOG any exceptions
             }
         }
         return null;
     }
 
+    private static boolean isPrimitiveOrJdkOrJodaOrGuava(final Class<?> cls) {
+        if(cls.isPrimitive()) {
+            return true;
+        }
+        final String className = cls.getName();
+        return className.startsWith("java.") || className.startsWith("javax.") || className.startsWith("org.joda") || className.startsWith("com.google.common");
+    }
+
     // ////////////////////////////////////////////////////////////////////////////
     // introspect associations
     // ////////////////////////////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/405d0dda/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
index 39fd850..e638f14 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java
@@ -136,6 +136,11 @@ public class ProgrammableReflector extends SpecificationLoaderAbstract implement
     }
 
     @Override
+    public boolean isServiceClass(final Class<?> cls) {
+        throw new NotYetImplementedException();
+    }
+
+    @Override
     public void invalidateCacheFor(Object domainObject) {
     }
     @Override


[2/2] isis git commit: ISIS-1051: updating doc for LayoutMetadataReader2.

Posted by da...@apache.org.
ISIS-1051: updating doc for LayoutMetadataReader2.


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

Branch: refs/heads/master
Commit: c3d348088b03f7399a630fb784706a53bc604fc9
Parents: 405d0dd
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Jul 29 19:32:05 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed Jul 29 19:32:05 2015 +0100

----------------------------------------------------------------------
 ...rogramming-model_layout-metadata-reader.adoc | 38 ++++++++++++++++++++
 1 file changed, 38 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/c3d34808/adocs/documentation/src/main/asciidoc/guides/_ug_extending_programming-model_layout-metadata-reader.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_ug_extending_programming-model_layout-metadata-reader.adoc b/adocs/documentation/src/main/asciidoc/guides/_ug_extending_programming-model_layout-metadata-reader.adoc
index 26f908e..a517dbe 100644
--- a/adocs/documentation/src/main/asciidoc/guides/_ug_extending_programming-model_layout-metadata-reader.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/_ug_extending_programming-model_layout-metadata-reader.adoc
@@ -28,6 +28,44 @@ The implementation "simply" returns a set of properties where the property key i
 
 See the implementation of the built-in `LayoutMetadataReaderFromJson` for more detail.
 
+Returning either `null` or throwing an exception indicates that the reader was unable to load any metadata for the specified class.
+
+
+=== Extended API
+
+Optionally the reader can implement the extended `LayoutMetadaReader2` API:
+
+[source,java]
+----
+public interface LayoutMetadataReader2 extends LayoutMetadataReader {
+    public static class Support {
+        public static Support entitiesOnly() {
+            return new Support(false,false,false,false,false,false,false);
+        }
+        ...
+        public boolean interfaces() { ... } // <1>
+        public boolean anonymous() { ... }  // <2>
+        public boolean synthetic() { ... }  // <3>
+        public boolean array() { ... }      // <4>
+        public boolean enums() { ... }      // <5>
+        public boolean applibValueTypes() { // <6>
+        public boolean services() { ... }   // <7>
+    }
+    Support support();
+}
+----
+<1> whether this implementation can provide metadata for interface types.
+<2> whether this implementation can provide metadata for anonymous classes.
+<3> whether this implementation can provide metadata for synthetic types.
+<4> whether this implementation can provide metadata for arrays.
+<5> whether this implementation can provide metadata for enums.
+<6> whether this implementation can provide metadata for applib value types.
+<7> whether this implementation can provide metadata for domain services.
+
+The `support()` method returns a struct class that describes the types of classes are supported by this implementation.
+
+The `LayoutMetadataReaderFromJson` implements this extended API.
+
 
 
 == Configuration