EXTSCRIPT-154: Code Rewrite/Refactoring adding facelet support now (finally)

git-svn-id: https://svn.apache.org/repos/asf/myfaces/extensions/scripting/trunk@1298761 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/BehaviorHandlerReloadingStrategy.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/BehaviorHandlerReloadingStrategy.java
new file mode 100644
index 0000000..5c9e645
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/BehaviorHandlerReloadingStrategy.java
@@ -0,0 +1,68 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.api.ScriptingWeaver;
+import org.apache.myfaces.extensions.scripting.core.reloading.SimpleReloadingStrategy;
+import org.apache.myfaces.extensions.scripting.core.util.Cast;
+import org.apache.myfaces.extensions.scripting.core.util.ReflectUtil;
+
+import javax.faces.view.facelets.BehaviorConfig;
+import javax.faces.view.facelets.BehaviorHandler;
+import javax.faces.view.facelets.ComponentHandler;
+
+/**
+ * The reloading strategy for our behavior tag handlers
+ * note since we do not have an official api we must
+ * enforce a getConverterConfig() method to allow
+ * the reloading of converter tag handlers
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class BehaviorHandlerReloadingStrategy extends SimpleReloadingStrategy {
+    public BehaviorHandlerReloadingStrategy(ScriptingWeaver weaver) {
+        super(weaver);
+    }
+
+    @Override
+    public Object reload(Object scriptingInstance, int artifactType) {
+        if (!(scriptingInstance instanceof ComponentHandler)) return scriptingInstance;
+        Class aclass = _weaver.reloadScriptingClass(scriptingInstance.getClass());
+        if (aclass.hashCode() == scriptingInstance.getClass().hashCode()) {
+            //class of this object has not changed although
+            // reload is enabled we can skip the rest now
+            return scriptingInstance;
+        }
+        BehaviorHandler oldHandler = (BehaviorHandler) scriptingInstance;
+        /**
+         *
+         */
+        BehaviorConfig config = (BehaviorConfig) ReflectUtil.executeMethod(oldHandler, "getBehaviorConfig");
+        BehaviorHandler newHandler = (BehaviorHandler) ReflectUtil.instantiate(aclass, new Cast(BehaviorConfig.class, config));
+
+        //save all pending non config related properties wherever possible
+        super.mapProperties(newHandler, oldHandler);
+
+        return newHandler;
+    }
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ComponentHandlerReloadingStrategy.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ComponentHandlerReloadingStrategy.java
new file mode 100644
index 0000000..d0ff115
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ComponentHandlerReloadingStrategy.java
@@ -0,0 +1,60 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.api.ScriptingWeaver;
+import org.apache.myfaces.extensions.scripting.core.reloading.SimpleReloadingStrategy;
+import org.apache.myfaces.extensions.scripting.core.util.Cast;
+import org.apache.myfaces.extensions.scripting.core.util.ReflectUtil;
+
+import javax.faces.view.facelets.ComponentConfig;
+import javax.faces.view.facelets.ComponentHandler;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class ComponentHandlerReloadingStrategy extends SimpleReloadingStrategy {
+
+    public ComponentHandlerReloadingStrategy(ScriptingWeaver weaver) {
+        super(weaver);
+    }
+
+    @Override
+    public Object reload(Object scriptingInstance, int artifactType) {
+        if (!(scriptingInstance instanceof ComponentHandler)) return scriptingInstance;
+        Class aclass = _weaver.reloadScriptingClass(scriptingInstance.getClass());
+        if (aclass.hashCode() == scriptingInstance.getClass().hashCode()) {
+            //class of this object has not changed although
+            // reload is enabled we can skip the rest now
+            return scriptingInstance;
+        }
+        ComponentHandler oldHandler = (ComponentHandler) scriptingInstance;
+        ComponentConfig config = oldHandler.getComponentConfig();
+        ComponentHandler newHandler = (ComponentHandler) ReflectUtil.instantiate(aclass, new Cast(ComponentConfig.class, config));
+
+        //save all pending non config related properties wherever possible
+        super.mapProperties(newHandler, oldHandler);
+
+        return newHandler;
+    }
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ConverterHandlerReloadingStrategy.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ConverterHandlerReloadingStrategy.java
new file mode 100644
index 0000000..692133d
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ConverterHandlerReloadingStrategy.java
@@ -0,0 +1,69 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.api.ScriptingWeaver;
+import org.apache.myfaces.extensions.scripting.core.reloading.SimpleReloadingStrategy;
+import org.apache.myfaces.extensions.scripting.core.util.Cast;
+import org.apache.myfaces.extensions.scripting.core.util.ReflectUtil;
+
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.ConverterConfig;
+import javax.faces.view.facelets.ConverterHandler;
+
+/**
+ * The reloading strategy for our converter tag handlers
+ * note since we do not have an official api we must
+ * enforce a getConverterConfig() method to allow
+ * the reloading of converter tag handlers
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+@SuppressWarnings("unused")//used dynamically
+public class ConverterHandlerReloadingStrategy extends SimpleReloadingStrategy {
+
+    public ConverterHandlerReloadingStrategy(ScriptingWeaver weaver) {
+        super(weaver);
+    }
+
+    @Override
+    public Object reload(Object scriptingInstance, int artifactType) {
+        if (!(scriptingInstance instanceof ComponentHandler)) return scriptingInstance;
+        Class aclass = _weaver.reloadScriptingClass(scriptingInstance.getClass());
+        if (aclass.hashCode() == scriptingInstance.getClass().hashCode()) {
+            //class of this object has not changed although
+            // reload is enabled we can skip the rest now
+            return scriptingInstance;
+        }
+        ConverterHandler oldHandler = (ConverterHandler) scriptingInstance;
+        /**
+         *
+         */
+        ConverterConfig config = (ConverterConfig) ReflectUtil.executeMethod(oldHandler, "getConverterConfig");
+        ConverterHandler newHandler = (ConverterHandler) ReflectUtil.instantiate(aclass, new Cast(ConverterConfig.class, config));
+
+        //save all pending non config related properties wherever possible
+        super.mapProperties(newHandler, oldHandler);
+
+        return newHandler;
+    }
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingBehaviorTagHandlerDelegate.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingBehaviorTagHandlerDelegate.java
new file mode 100644
index 0000000..deab937
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingBehaviorTagHandlerDelegate.java
@@ -0,0 +1,70 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.api.ScriptingConst;
+import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
+import org.apache.myfaces.view.facelets.tag.jsf.BehaviorTagHandlerDelegate;
+
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.BehaviorHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRuleset;
+import javax.faces.view.facelets.TagHandlerDelegate;
+import java.io.IOException;
+
+/**
+ * Behavior Tag Handler which introduces reloading behavior
+ *
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class ReloadingBehaviorTagHandlerDelegate extends TagHandlerDelegate {
+
+    BehaviorHandler _owner;
+    TagHandlerDelegate _delegate;
+
+    public ReloadingBehaviorTagHandlerDelegate(BehaviorHandler owner) {
+        applyOwner(owner);
+    }
+
+    private void applyOwner(BehaviorHandler owner) {
+        _owner = owner;
+        _delegate = new BehaviorTagHandlerDelegate(_owner);
+    }
+
+    @Override
+    public void apply(FaceletContext ctx, UIComponent comp) throws IOException {
+        if (WeavingContext.isDynamic(_owner.getClass())) {
+            BehaviorHandler newOwner = (BehaviorHandler) WeavingContext.getWeaver().reloadScriptingInstance(_owner, ScriptingConst.ARTIFACT_TYPE_BEHAVIOR_HANDLER);
+            if (!newOwner.getClass().equals(_owner.getClass())) {
+                applyOwner(newOwner);
+            }
+        }
+        _owner.apply(ctx, comp);
+    }
+
+    @Override
+    public MetaRuleset createMetaRuleset(Class type) {
+        return _delegate.createMetaRuleset(type);
+    }
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingComponentTagHandlerDelegate.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingComponentTagHandlerDelegate.java
new file mode 100644
index 0000000..488ea34
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingComponentTagHandlerDelegate.java
@@ -0,0 +1,105 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.api.ScriptingConst;
+import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
+import org.apache.myfaces.extensions.scripting.facelet.support.SwitchingMetarulesetImpl;
+import org.apache.myfaces.view.facelets.tag.jsf.*;
+
+import javax.faces.component.ActionSource;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.ValueHolder;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRuleset;
+import javax.faces.view.facelets.TagHandlerDelegate;
+import java.io.IOException;
+
+/**
+ * we provide our own component tag handler factory impl
+ * so that we can deal with refreshing of components
+ * on Facelets level without running into
+ * nasty type exceptions
+ */
+public class ReloadingComponentTagHandlerDelegate extends TagHandlerDelegate {
+
+    ComponentHandler _owner;
+    TagHandlerDelegate _delegate;
+
+    public ReloadingComponentTagHandlerDelegate(ComponentHandler owner) {
+        applyOwner(owner);
+    }
+
+    private void applyOwner(ComponentHandler owner) {
+        _owner = owner;
+        _delegate = new ComponentTagHandlerDelegate(_owner);
+    }
+
+    @Override
+    public void apply(FaceletContext ctx, UIComponent comp) throws IOException {
+        if (WeavingContext.isDynamic(_owner.getClass())) {
+            ComponentHandler newOwner = (ComponentHandler) WeavingContext.getWeaver().reloadScriptingInstance(_owner, ScriptingConst.ARTIFACT_TYPE_COMPONENT_HANDLER);
+            if (!newOwner.getClass().equals(_owner.getClass())) {
+                applyOwner(newOwner);
+            }
+        }
+        _delegate.apply(ctx, comp);
+    }
+
+    public MetaRuleset createMetaRuleset(Class type) {
+        //We have to create a different meta rule set for dynamic classes
+        //which have weaver instantiation criteria, the original meta rule set
+        //first applies the attributes and then calls BeanPropertyTagRule
+        //that one however caches the current method and does not take into consideration
+        //that classes can be changed on the fly
+
+        // if (WeavingContext.isDynamic(type)) {
+        MetaRuleset m = new SwitchingMetarulesetImpl(_owner.getTag(), type);
+        // ignore standard component attributes
+        m.ignore("binding").ignore("id");
+
+        // add auto wiring for attributes
+        m.addRule(ComponentRule.Instance);
+
+        // if it's an ActionSource
+        if (ActionSource.class.isAssignableFrom(type)) {
+            m.addRule(ActionSourceRule.INSTANCE);
+        }
+
+        // if it's a ValueHolder
+        if (ValueHolder.class.isAssignableFrom(type)) {
+            m.addRule(ValueHolderRule.INSTANCE);
+
+            // if it's an EditableValueHolder
+            if (EditableValueHolder.class.isAssignableFrom(type)) {
+                m.ignore("submittedValue");
+                m.ignore("valid");
+                m.addRule(EditableValueHolderRule.INSTANCE);
+            }
+        }
+
+        return m;
+        //}
+
+        //return _delegate.createMetaRuleset(type);
+    }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingConverterTagHandlerDelegate.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingConverterTagHandlerDelegate.java
new file mode 100644
index 0000000..c0eea69
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingConverterTagHandlerDelegate.java
@@ -0,0 +1,68 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.api.ScriptingConst;
+import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
+import org.apache.myfaces.view.facelets.tag.jsf.ConverterTagHandlerDelegate;
+
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.ConverterHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRuleset;
+import javax.faces.view.facelets.TagHandlerDelegate;
+import java.io.IOException;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class ReloadingConverterTagHandlerDelegate extends TagHandlerDelegate {
+
+        ConverterHandler _owner;
+        TagHandlerDelegate _delegate;
+
+        public ReloadingConverterTagHandlerDelegate(ConverterHandler owner) {
+            applyOwner(owner);
+        }
+
+    private void applyOwner(ConverterHandler owner) {
+        _owner = owner;
+        _delegate = new ConverterTagHandlerDelegate(_owner);
+    }
+
+    @Override
+        public void apply(FaceletContext ctx, UIComponent comp) throws IOException {
+            if (WeavingContext.isDynamic(_owner.getClass())) {
+                ConverterHandler newOwner = (ConverterHandler) WeavingContext.getWeaver().reloadScriptingInstance(_owner, ScriptingConst.ARTIFACT_TYPE_CONVERTER_HANDLER);
+                if(!newOwner.getClass().equals(_owner.getClass())) {
+                    applyOwner(newOwner);
+                }
+            }
+            _delegate.apply(ctx, comp);
+        }
+
+        @Override
+        public MetaRuleset createMetaRuleset(Class type) {
+            return _delegate.createMetaRuleset(type);
+        }
+
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingValidatorTagHandlerDelegate.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingValidatorTagHandlerDelegate.java
new file mode 100644
index 0000000..dcb0224
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReloadingValidatorTagHandlerDelegate.java
@@ -0,0 +1,67 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.api.ScriptingConst;
+import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
+import org.apache.myfaces.view.facelets.tag.jsf.ValidatorTagHandlerDelegate;
+
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRuleset;
+import javax.faces.view.facelets.TagHandlerDelegate;
+import javax.faces.view.facelets.ValidatorHandler;
+import java.io.IOException;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class ReloadingValidatorTagHandlerDelegate extends TagHandlerDelegate {
+
+    ValidatorHandler _owner;
+    TagHandlerDelegate _delegate;
+
+    public ReloadingValidatorTagHandlerDelegate(ValidatorHandler owner) {
+        applyOwner(owner);
+    }
+
+    private void applyOwner(ValidatorHandler owner) {
+        _owner = owner;
+        _delegate = new ValidatorTagHandlerDelegate(_owner);
+    }
+
+    @Override
+    public void apply(FaceletContext ctx, UIComponent comp) throws IOException {
+        if (WeavingContext.isDynamic(_owner.getClass())) {
+            ValidatorHandler newOwner = (ValidatorHandler) WeavingContext.getWeaver().reloadScriptingInstance(_owner, ScriptingConst.ARTIFACT_TYPE_VALIDATOR_HANDLER);
+            if (!newOwner.getClass().equals(_owner.getClass())) {
+                applyOwner(newOwner);
+            }
+        }
+        _owner.apply(ctx, comp);
+    }
+
+    @Override
+    public MetaRuleset createMetaRuleset(Class type) {
+        return _delegate.createMetaRuleset(type);
+    }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReroutingResourceResolver.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReroutingResourceResolver.java
new file mode 100644
index 0000000..74a0650
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ReroutingResourceResolver.java
@@ -0,0 +1,64 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
+import org.apache.myfaces.view.facelets.impl.DefaultResourceResolver;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * decorated Facelet resource resolver to reroute
+ * the resource requests to our source path if possible
+ */
+public class ReroutingResourceResolver extends DefaultResourceResolver {
+
+    DefaultResourceResolver _delegate = new DefaultResourceResolver();
+    volatile boolean _initiated = false;
+    List<String> _resourceDirs = null;
+
+    Logger log = Logger.getLogger(this.getClass().getName());
+
+    @Override
+    public URL resolveUrl(String path) {
+
+        if (!_initiated) {
+            _resourceDirs = WeavingContext.getConfiguration().getResourceDirs();
+            _initiated = true;
+        }
+
+        if (_resourceDirs != null && !_resourceDirs.isEmpty()) {
+            for (String resourceDir : _resourceDirs) {
+                File resource = new File(resourceDir + path);
+                if (resource.exists()) try {
+                    return resource.toURI().toURL();
+                } catch (MalformedURLException e) {
+                    log.log(Level.SEVERE, "",e);
+                }
+            }
+        }
+
+        return _delegate.resolveUrl(path);
+    }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/TagHandlerDelegateFactoryImpl.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/TagHandlerDelegateFactoryImpl.java
new file mode 100644
index 0000000..873c2d8
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/TagHandlerDelegateFactoryImpl.java
@@ -0,0 +1,71 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
+import org.apache.myfaces.view.facelets.tag.jsf.BehaviorTagHandlerDelegate;
+import org.apache.myfaces.view.facelets.tag.jsf.ConverterTagHandlerDelegate;
+import org.apache.myfaces.view.facelets.tag.jsf.ValidatorTagHandlerDelegate;
+
+import javax.faces.view.facelets.*;
+
+/**
+ * Tag handler delegate factory which injects reloading
+ * proxies for our facelet artifacts
+ */
+public class TagHandlerDelegateFactoryImpl extends TagHandlerDelegateFactory {
+
+    @Override
+    public TagHandlerDelegate createBehaviorHandlerDelegate(
+            BehaviorHandler owner) {
+        if (WeavingContext.isDynamic(owner.getClass())) {
+            return new ReloadingBehaviorTagHandlerDelegate(owner);
+        } else {
+            return new BehaviorTagHandlerDelegate(owner);
+        }
+    }
+
+    @Override
+    public TagHandlerDelegate createComponentHandlerDelegate(
+            ComponentHandler owner) {
+        return new ReloadingComponentTagHandlerDelegate(owner);
+    }
+
+    @Override
+    public TagHandlerDelegate createConverterHandlerDelegate(
+            ConverterHandler owner) {
+        if (WeavingContext.isDynamic(owner.getClass())) {
+            return new ReloadingConverterTagHandlerDelegate(owner);
+        } else {
+            return new ConverterTagHandlerDelegate(owner);
+        }
+    }
+
+    @Override
+    public TagHandlerDelegate createValidatorHandlerDelegate(
+            ValidatorHandler owner) {
+        if (WeavingContext.isDynamic(owner.getClass())) {
+            return new ReloadingValidatorTagHandlerDelegate(owner);
+        } else {
+            return new ValidatorTagHandlerDelegate(owner);
+        }
+    }
+}
+
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ValidatorHandlerReloadingStrategy.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ValidatorHandlerReloadingStrategy.java
new file mode 100644
index 0000000..68168bf
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/ValidatorHandlerReloadingStrategy.java
@@ -0,0 +1,62 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet;
+
+import org.apache.myfaces.extensions.scripting.api.ScriptingWeaver;
+import org.apache.myfaces.extensions.scripting.core.reloading.SimpleReloadingStrategy;
+import org.apache.myfaces.extensions.scripting.core.util.Cast;
+import org.apache.myfaces.extensions.scripting.core.util.ReflectUtil;
+
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.ValidatorConfig;
+import javax.faces.view.facelets.ValidatorHandler;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class ValidatorHandlerReloadingStrategy extends SimpleReloadingStrategy {
+
+    public ValidatorHandlerReloadingStrategy(ScriptingWeaver weaver) {
+        super(weaver);
+    }
+
+    @Override
+    public Object reload(Object scriptingInstance, int artifactType) {
+        if (!(scriptingInstance instanceof ComponentHandler)) return scriptingInstance;
+        Class aclass = _weaver.reloadScriptingClass(scriptingInstance.getClass());
+        if (aclass.hashCode() == scriptingInstance.getClass().hashCode()) {
+            //class of this object has not changed although
+            // reload is enabled we can skip the rest now
+            return scriptingInstance;
+        }
+        ValidatorHandler oldHandler = (ValidatorHandler) scriptingInstance;
+        ValidatorConfig config = oldHandler.getValidatorConfig();
+        ValidatorHandler newHandler = (ValidatorHandler) ReflectUtil.instantiate(aclass, new Cast(ValidatorConfig.class, config));
+
+        //save all pending non config related properties wherever possible
+        super.mapProperties(newHandler, oldHandler);
+
+        return newHandler;
+    }
+
+}
+
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/ComponentRule.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/ComponentRule.java
new file mode 100644
index 0000000..3089979
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/ComponentRule.java
@@ -0,0 +1,102 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet.support;
+
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * we have to re implement the component rule class here
+ * because it is declared private in the original
+ * implementation
+ */
+public final class ComponentRule extends MetaRule {
+
+    final class LiteralAttributeMetadata extends Metadata {
+        private final String _name;
+        private final String _value;
+
+        public LiteralAttributeMetadata(String name, String value) {
+            _name = name;
+            _value = value;
+        }
+
+        public void applyMetadata(FaceletContext ctx, Object instance) {
+            ((UIComponent) instance).getAttributes().put(_name, _value);
+        }
+    }
+
+    final static class ValueExpressionMetadata extends Metadata {
+        private final String _name;
+
+        private final TagAttribute _attr;
+
+        private final Class<?> _type;
+
+        public ValueExpressionMetadata(String name, Class<?> type, TagAttribute attr) {
+            _name = name;
+            _attr = attr;
+            _type = type;
+        }
+
+        public void applyMetadata(FaceletContext ctx, Object instance) {
+            ((UIComponent) instance).setValueExpression(_name, _attr.getValueExpression(ctx, _type));
+        }
+    }
+
+    //private final static Logger log = Logger.getLogger("facelets.tag.component");
+    private final static Logger log = Logger.getLogger(ComponentRule.class.getName());
+
+    public final static ComponentRule Instance = new ComponentRule();
+
+    public ComponentRule() {
+        super();
+    }
+
+    public Metadata applyRule(String name, TagAttribute attribute, MetadataTarget meta) {
+        if (meta.isTargetInstanceOf(UIComponent.class)) {
+            // if component and dynamic, then must set expression
+            if (!attribute.isLiteral()) {
+                Class<?> type = meta.getPropertyType(name);
+                if (type == null) {
+                    type = Object.class;
+                }
+
+                return new ValueExpressionMetadata(name, type, attribute);
+            } else if (meta.getWriteMethod(name) == null) {
+
+                // this was an attribute literal, but not property
+                warnAttr(attribute, meta.getTargetClass(), name);
+
+                return new LiteralAttributeMetadata(name, attribute.getValue());
+            }
+        }
+        return null;
+    }
+
+    private static void warnAttr(TagAttribute attr, Class<?> type, String n) {
+        if (log.isLoggable(Level.FINER)) {
+            log.finer(attr + " Property '" + n + "' is not on type: " + type.getName());
+        }
+    }
+
+}
+
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/InvokeDynamicBeanPropertyTagRule.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/InvokeDynamicBeanPropertyTagRule.java
new file mode 100644
index 0000000..a483cab
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/InvokeDynamicBeanPropertyTagRule.java
@@ -0,0 +1,106 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet.support;
+
+import org.apache.myfaces.extensions.scripting.core.util.ReflectUtil;
+
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+import java.lang.reflect.Method;
+
+/**
+ * We have to introduce a BeanPropertyTagRule
+ * which calls the setter of a given component
+ * on a weaker base than the original facelets component
+ * property tag rule does.
+ * By not enforcing a strict per object/class policy on calling
+ * the setter we are able to reload the classes on the fly
+ * <p/>
+ * the original approach was to cache the classes, and then
+ * call the invoke method on the existing class
+ * if we now exchange the classes we have a problem...
+ * By making the invocation of the method independend from the underlying
+ * class (sort of calling an invokedynamic) we can bypass this problem
+ * on facelets level.
+ */
+public class InvokeDynamicBeanPropertyTagRule {
+    public final static InvokeDynamicBeanPropertyTagRule Instance = new InvokeDynamicBeanPropertyTagRule();
+
+    public Metadata applyRule(String name, TagAttribute attribute, MetadataTarget meta) {
+        Method m = meta.getWriteMethod(name);
+
+        // if the property is writable
+        if (m != null) {
+            if (attribute.isLiteral()) {
+                return new LiteralPropertyMetadata(m, attribute);
+            } else {
+                return new DynamicPropertyMetadata(m, attribute);
+            }
+        }
+
+        return null;
+    }
+
+    final static class LiteralPropertyMetadata extends Metadata {
+
+        private final Method method;
+
+        private final TagAttribute attribute;
+
+        private Object[] value;
+
+        public LiteralPropertyMetadata(Method method, TagAttribute attribute) {
+            this.method = method;
+            this.attribute = attribute;
+        }
+
+        public void applyMetadata(FaceletContext ctx, Object instance) {
+            if (value == null) {
+                String str = this.attribute.getValue();
+                value = new Object[]{ctx.getExpressionFactory().coerceToType(str, method.getParameterTypes()[0])};
+            }
+            //What we do here is simply to call an invoke dynamic on the method with the same name
+            //but on the new instance of, that way we can bypass class problems
+            //because the method reference has stored the old class in our case
+            ReflectUtil.executeMethod(instance, method.getName(), this.value);
+        }
+
+    }
+
+    final static class DynamicPropertyMetadata extends Metadata {
+
+        private final Method method;
+
+        private final TagAttribute attribute;
+
+        private final Class<?> type;
+
+        public DynamicPropertyMetadata(Method method, TagAttribute attribute) {
+            this.method = method;
+            this.type = method.getParameterTypes()[0];
+            this.attribute = attribute;
+        }
+
+        public void applyMetadata(FaceletContext ctx, Object instance) {
+            ReflectUtil.executeMethod(instance, method.getName(), new Object[]{attribute.getObject(ctx, type)});
+        }
+    }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/SwitchingBeanPropertyTagRule.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/SwitchingBeanPropertyTagRule.java
new file mode 100644
index 0000000..5cf24ab
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/SwitchingBeanPropertyTagRule.java
@@ -0,0 +1,51 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet.support;
+
+import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
+import org.apache.myfaces.view.facelets.tag.BeanPropertyTagRule;
+
+import javax.faces.view.facelets.MetaRule;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+
+/**
+ * Bean property tag rule
+ * which switches between the fast static
+ * version and the slower invoke dynamic
+ * version depending on the class type of
+ * the incoming instance
+ */
+public class SwitchingBeanPropertyTagRule extends MetaRule {
+
+    InvokeDynamicBeanPropertyTagRule _invokeDynamic = InvokeDynamicBeanPropertyTagRule.Instance;
+    BeanPropertyTagRule _invokeStatic = BeanPropertyTagRule.INSTANCE;
+
+    public static volatile SwitchingBeanPropertyTagRule Instance = new SwitchingBeanPropertyTagRule();
+
+    @Override
+    public Metadata applyRule(String name, TagAttribute attribute, MetadataTarget meta) {
+        if (WeavingContext.isDynamic(meta.getTargetClass())) {
+            return _invokeDynamic.applyRule(name, attribute, meta);
+        } else {
+            return _invokeStatic.applyRule(name, attribute, meta);
+        }
+    }
+}
diff --git a/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/SwitchingMetarulesetImpl.java b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/SwitchingMetarulesetImpl.java
new file mode 100644
index 0000000..a61510d
--- /dev/null
+++ b/extscript-core-root/extscript-core/src/main/java/rewrite/org/apache/myfaces/extensions/scripting/jsf/facelet/support/SwitchingMetarulesetImpl.java
@@ -0,0 +1,179 @@
+/*
+ * 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 rewrite.org.apache.myfaces.extensions.scripting.jsf.facelet.support;
+
+import org.apache.myfaces.view.facelets.tag.MetaRulesetImpl;
+import org.apache.myfaces.view.facelets.tag.MetadataImpl;
+import org.apache.myfaces.view.facelets.tag.MetadataTargetImpl;
+import org.apache.myfaces.view.facelets.util.ParameterCheck;
+
+import javax.faces.view.facelets.*;
+import java.beans.IntrospectionException;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * we have to to do a full reimplementation of the rule set
+ * because otherwise we could not plant the switching bean reloading
+ * rule due to private props in the original code
+ */
+public class SwitchingMetarulesetImpl extends MetaRuleset {
+    private final static Metadata NONE = new NullMetadata();
+
+    //private final static Logger log = Logger.getLogger("facelets.tag.meta");
+    private final static Logger log = Logger.getLogger(MetaRulesetImpl.class.getName());
+
+    private final static WeakHashMap<String, MetadataTarget> _metadata = new WeakHashMap<String, MetadataTarget>();
+
+    private final Map<String, TagAttribute> _attributes;
+
+    private final List<Metadata> _mappers;
+
+    private final List<MetaRule> _rules;
+
+    private final Tag _tag;
+
+    private final Class<?> _type;
+
+    public SwitchingMetarulesetImpl(Tag tag, Class<?> type) {
+        _tag = tag;
+        _type = type;
+        _attributes = new HashMap<String, TagAttribute>();
+        _mappers = new ArrayList<Metadata>();
+        _rules = new ArrayList<MetaRule>();
+
+        // setup attributes
+        for (TagAttribute attribute : _tag.getAttributes().getAll()) {
+            _attributes.put(attribute.getLocalName(), attribute);
+        }
+
+        // add default rules
+        _rules.add(SwitchingBeanPropertyTagRule.Instance);
+    }
+
+    public MetaRuleset add(Metadata mapper) {
+        ParameterCheck.notNull("mapper", mapper);
+
+        if (!_mappers.contains(mapper)) {
+            _mappers.add(mapper);
+        }
+
+        return this;
+    }
+
+    public MetaRuleset addRule(MetaRule rule) {
+        ParameterCheck.notNull("rule", rule);
+
+        _rules.add(rule);
+
+        return this;
+    }
+
+    public MetaRuleset alias(String attribute, String property) {
+        ParameterCheck.notNull("attribute", attribute);
+        ParameterCheck.notNull("property", property);
+
+        TagAttribute attr = (TagAttribute) _attributes.remove(attribute);
+        if (attr != null) {
+            _attributes.put(property, attr);
+        }
+
+        return this;
+    }
+
+    public Metadata finish() {
+        assert !_rules.isEmpty();
+
+        if (!_attributes.isEmpty()) {
+            MetadataTarget target = this._getMetadataTarget();
+            int ruleEnd = _rules.size() - 1;
+
+            // now iterate over attributes
+            for (Map.Entry<String, TagAttribute> entry : _attributes.entrySet()) {
+                Metadata data = null;
+
+                int i = ruleEnd;
+
+                // First loop is always safe
+                do {
+                    MetaRule rule = _rules.get(i);
+                    data = rule.applyRule(entry.getKey(), entry.getValue(), target);
+                    i--;
+                } while (data == null && i >= 0);
+
+                if (data == null) {
+                    if (log.isLoggable(Level.SEVERE)) {
+                        log.severe(entry.getValue() + " Unhandled by MetaTagHandler for type " + _type.getName());
+                    }
+                } else {
+                    _mappers.add(data);
+                }
+            }
+        }
+
+        if (_mappers.isEmpty()) {
+            return NONE;
+        } else {
+            return new MetadataImpl(_mappers.toArray(new Metadata[_mappers.size()]));
+        }
+    }
+
+    public MetaRuleset ignore(String attribute) {
+        ParameterCheck.notNull("attribute", attribute);
+
+        _attributes.remove(attribute);
+
+        return this;
+    }
+
+    public MetaRuleset ignoreAll() {
+        _attributes.clear();
+
+        return this;
+    }
+
+    private final MetadataTarget _getMetadataTarget() {
+        String key = _type.getName();
+
+        MetadataTarget meta = _metadata.get(key);
+        if (meta == null) {
+            try {
+                meta = new MetadataTargetImpl(_type);
+            }
+            catch (IntrospectionException e) {
+                throw new TagException(_tag, "Error Creating TargetMetadata", e);
+            }
+
+            _metadata.put(key, meta);
+        }
+
+        return meta;
+    }
+
+    private static class NullMetadata extends Metadata {
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void applyMetadata(FaceletContext ctx, Object instance) {
+            // do nothing
+        }
+    }
+}