You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by gp...@apache.org on 2015/04/21 23:07:33 UTC

[2/2] deltaspike git commit: DELTASPIKE-877 allow to inherit dynamically changed metadata

DELTASPIKE-877 allow to inherit dynamically changed metadata


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

Branch: refs/heads/master
Commit: 0752f78aac43451cc043258340c0e7789ba83d1a
Parents: aaa5526
Author: gpetracek <gp...@apache.org>
Authored: Tue Apr 21 22:54:21 2015 +0200
Committer: gpetracek <gp...@apache.org>
Committed: Tue Apr 21 23:01:34 2015 +0200

----------------------------------------------------------------------
 .../config/view/DefaultConfigNodeConverter.java | 57 ++++++++++++-
 .../DefaultViewConfigInheritanceStrategy.java   | 90 +++++++++++++++++++-
 2 files changed, 143 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/0752f78a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultConfigNodeConverter.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultConfigNodeConverter.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultConfigNodeConverter.java
index 6655699..c25d742 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultConfigNodeConverter.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultConfigNodeConverter.java
@@ -27,6 +27,7 @@ import org.apache.deltaspike.core.api.config.view.metadata.ConfigDescriptor;
 import org.apache.deltaspike.core.spi.config.view.ConfigNodeConverter;
 import org.apache.deltaspike.core.spi.config.view.ConfigPreProcessor;
 import org.apache.deltaspike.core.spi.config.view.ViewConfigNode;
+import org.apache.deltaspike.core.util.AnnotationUtils;
 import org.apache.deltaspike.core.util.ClassUtils;
 import org.apache.deltaspike.core.util.ExceptionUtils;
 import org.apache.deltaspike.core.util.metadata.AnnotationInstanceProvider;
@@ -38,7 +39,9 @@ import javax.enterprise.inject.Stereotype;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -250,7 +253,17 @@ public class DefaultConfigNodeConverter implements ConfigNodeConverter
                     }
                 }
                 ConfigPreProcessor preProcessor = ClassUtils.tryToInstantiateClass(preProcessorClass);
-                result.add(preProcessor.beforeAddToConfig(annotation, node));
+
+                Annotation resultToAdd = preProcessor.beforeAddToConfig(annotation, node);
+
+                //it isn't possible to detect changed annotations
+                if (resultToAdd != annotation) //check if the annotation(-instance) was changed
+                {
+                    validateAnnotationChange(annotation);
+                    rewriteMetaDataOfNode(node.getMetaData(), annotation, resultToAdd);
+                    rewriteMetaDataOfNode(node.getInheritedMetaData(), annotation, resultToAdd);
+                }
+                result.add(resultToAdd);
             }
             else
             {
@@ -288,4 +301,46 @@ public class DefaultConfigNodeConverter implements ConfigNodeConverter
 
         return result;
     }
+
+    protected void validateAnnotationChange(Annotation annotation)
+    {
+        Class<? extends Annotation> annotationType = annotation.annotationType();
+
+        if (Folder.class.equals(annotationType) || View.class.equals(annotationType))
+        {
+            return;
+        }
+
+        ViewMetaData viewMetaData = annotationType.getAnnotation(ViewMetaData.class);
+        if (viewMetaData == null)
+        {
+            return;
+        }
+
+        Aggregated aggregated = viewMetaData.annotationType().getAnnotation(Aggregated.class);
+        if (aggregated != null && aggregated.value())
+        {
+            throw new IllegalStateException("it isn't supported to change aggregated meta-data," +
+                "because inheritance won't work correctly");
+        }
+    }
+
+    protected void rewriteMetaDataOfNode(Collection<Annotation> metaData,
+                                         Annotation oldMetaData, Annotation newMetaData)
+    {
+        Iterator<Annotation> metaDataIterator = metaData.iterator();
+
+        while (metaDataIterator.hasNext())
+        {
+            Annotation currentMetaData = metaDataIterator.next();
+
+            if (AnnotationUtils.getQualifierHashCode(currentMetaData) ==
+                AnnotationUtils.getQualifierHashCode(oldMetaData))
+            {
+                metaDataIterator.remove();
+                metaData.add(newMetaData);
+                break;
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/0752f78a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigInheritanceStrategy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigInheritanceStrategy.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigInheritanceStrategy.java
index 77e4a0a..e1b1c29 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigInheritanceStrategy.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/config/view/DefaultViewConfigInheritanceStrategy.java
@@ -19,14 +19,18 @@
 package org.apache.deltaspike.jsf.impl.config.view;
 
 import org.apache.deltaspike.core.api.config.view.ViewConfig;
+import org.apache.deltaspike.core.api.config.view.metadata.Aggregated;
 import org.apache.deltaspike.core.api.config.view.metadata.ViewMetaData;
 import org.apache.deltaspike.core.spi.config.view.ViewConfigInheritanceStrategy;
 import org.apache.deltaspike.core.spi.config.view.ViewConfigNode;
+import org.apache.deltaspike.jsf.api.config.view.Folder;
+import org.apache.deltaspike.jsf.api.config.view.View;
 import org.apache.deltaspike.jsf.impl.util.ViewConfigUtils;
 
 import javax.enterprise.inject.Stereotype;
 import java.lang.annotation.Annotation;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -61,7 +65,7 @@ public class DefaultViewConfigInheritanceStrategy implements ViewConfigInheritan
             //don't add the annotations of the final view-config class itself (we just need the inherited annotations)
             if (ViewConfigUtils.isFolderConfig(currentClass))
             {
-                inheritedAnnotations.addAll(addViewMetaData(currentClass));
+                inheritedAnnotations.addAll(findViewMetaData(currentClass, viewConfigNode));
             }
 
             Class nextClass = currentClass.getSuperclass();
@@ -75,13 +79,19 @@ public class DefaultViewConfigInheritanceStrategy implements ViewConfigInheritan
         }
 
         //add meta-data inherited via stereotypes on the node itself
-        inheritedAnnotations.addAll(addViewMetaData(viewConfigNode.getSource()));
+        inheritedAnnotations.addAll(findViewMetaData(viewConfigNode.getSource(), viewConfigNode));
 
         return inheritedAnnotations;
     }
 
-    protected List<Annotation> addViewMetaData(Class currentClass)
+    protected List<Annotation> findViewMetaData(Class currentClass, ViewConfigNode viewConfigNode)
     {
+        //don't include meta-data from the node itself, because it would be stored as inherited meta-data
+        if (currentClass.equals(viewConfigNode.getSource()))
+        {
+            return Collections.emptyList();
+        }
+
         List<Annotation> result = new ArrayList<Annotation>();
 
         for (Annotation annotation : currentClass.getAnnotations())
@@ -95,9 +105,83 @@ public class DefaultViewConfigInheritanceStrategy implements ViewConfigInheritan
 
             addViewMetaData(annotation, result);
         }
+
+        result = tryToReplaceWithMergedMetaDataFromAncestor(currentClass, viewConfigNode.getParent(), result);
+        return result;
+    }
+
+    //only supported for meta-data which isn't aggregated
+    protected List<Annotation> tryToReplaceWithMergedMetaDataFromAncestor(
+        Class currentClass, ViewConfigNode parentViewConfigNode, List<Annotation> foundResult)
+    {
+        ViewConfigNode ancestorNode = findNodeWithClass(currentClass, parentViewConfigNode);
+        if (ancestorNode == null)
+        {
+            return foundResult;
+        }
+
+        List<Annotation> result = new ArrayList<Annotation>(foundResult.size());
+
+        //only replace the meta-data found for the node and don't add all meta-data from the ancestor-node
+        for (Annotation annotation : foundResult)
+        {
+            Annotation finalMetaData = getFinalMetaDataFromNode(ancestorNode, annotation);
+            result.add(finalMetaData);
+        }
+
         return result;
     }
 
+    //the meta-data returned by this method is merged and potentially customized by a ConfigPreProcessor
+    private Annotation getFinalMetaDataFromNode(ViewConfigNode viewConfigNode, Annotation annotation)
+    {
+        Class<? extends Annotation> targetType = annotation.annotationType();
+
+        //skip @View and @Folder, because they get created dynamically to support their optional usage
+        //the dynamic generation depends on the level and if it is a synthetic information
+        if (View.class.equals(targetType) || Folder.class.equals(targetType))
+        {
+            return annotation;
+        }
+
+        //skip aggregated meta-data, because it can't be replaced
+        //(there is no info available about the instance which replaced the original one
+        // which might be equivalent to the annotation passed to this method)
+        ViewMetaData viewMetaData = annotation.annotationType().getAnnotation(ViewMetaData.class);
+        if (viewMetaData == null)
+        {
+            return annotation;
+        }
+        Aggregated aggregated = viewMetaData.annotationType().getAnnotation(Aggregated.class);
+        if (aggregated == null || aggregated.value())
+        {
+            return annotation;
+        }
+
+        for (Annotation nodeMetaData : viewConfigNode.getMetaData())
+        {
+            if (targetType.equals(nodeMetaData.annotationType()))
+            {
+                return nodeMetaData;
+            }
+        }
+        return annotation;
+    }
+
+    private ViewConfigNode findNodeWithClass(Class nodeClass, ViewConfigNode viewConfigNode)
+    {
+        if (viewConfigNode == null || nodeClass == null)
+        {
+            return null;
+        }
+
+        if (nodeClass.equals(viewConfigNode.getSource()))
+        {
+            return viewConfigNode;
+        }
+        return findNodeWithClass(nodeClass, viewConfigNode.getParent());
+    }
+
     protected void addViewMetaData(Annotation currentAnnotation, List<Annotation> metaDataList)
     {
         Class<? extends Annotation> annotationClass = currentAnnotation.annotationType();