Author: gvanmatre Date: Fri Mar 30 17:13:39 2007 New Revision: 524333 URL: http://svn.apache.org/viewvc?view=rev&rev=524333 Log: Added a new reserved clay configuration attribute to declare that a definition cannot be extended (SHALE-353).
Added: shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final-config.xml (with props) shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final.html (with props) Modified: shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignChildrenCommand.java shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignPropertiesCommand.java shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/Globals.java shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentBean.java shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java shale/framework/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties shale/framework/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/ConfigTestCase.java Modified: shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignChildrenCommand.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignChildrenCommand.java?view=diff&rev=524333&r1=524332&r2=524333 ============================================================================== --- shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignChildrenCommand.java (original) +++ shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignChildrenCommand.java Fri Mar 30 17:13:39 2007 @@ -99,12 +99,12 @@ ++childIndex; } } - + //clay manages its own subtree; components that //renders children still do not build their own //composition. clay does both, build its own subtree //and renders its own children. - + if (!(parent instanceof Clay)) { // remove any components not represented by the metadata graph for (int i = parent.getChildCount() - 1; i > -1; i--) { @@ -118,8 +118,7 @@ } } } - - + return isFinal; } Modified: shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignPropertiesCommand.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignPropertiesCommand.java?view=diff&rev=524333&r1=524332&r2=524333 ============================================================================== --- shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignPropertiesCommand.java (original) +++ shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/component/chain/AssignPropertiesCommand.java Fri Mar 30 17:13:39 2007 @@ -94,6 +94,12 @@ continue next; } + //skip past any assignments of the reserved attribute "org.apache.shale.clay.final" + //used to specify that a component definition cannot be extended. + if (a.getName().equals(Globals.CLAY_ALLOW_OVERRIDE_ATTRIBUTE)) { + continue next; + } + Command command = null; //look for a command override in the customization catalog first if (customizationCatalog != null) { Modified: shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/Globals.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/Globals.java?view=diff&rev=524333&r1=524332&r2=524333 ============================================================================== --- shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/Globals.java (original) +++ shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/Globals.java Fri Mar 30 17:13:39 2007 @@ -281,5 +281,14 @@ * map.</p> */ public static final String CLAY_JSPID_ATTRIBUTE = "org.apache.shale.clay.jspid"; + + /** + * <p>This constant is the name of a reserved [EMAIL PROTECTED] AttributeBean} name that is contained in + * a [EMAIL PROTECTED] ComponentBean}. This attribute is used to specify that the component cannot be + * extended by an inheriting [EMAIL PROTECTED] ComponentBean}. The value property is ignored in the + * [EMAIL PROTECTED] AttributeBean}. The goal is to copy the behavior of the Java programming + * language applied to meta-data inheritance.</p> + */ + public static final String CLAY_ALLOW_OVERRIDE_ATTRIBUTE = "org.apache.shale.clay.final"; } Modified: shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentBean.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentBean.java?view=diff&rev=524333&r1=524332&r2=524333 ============================================================================== --- shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentBean.java (original) +++ shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentBean.java Fri Mar 30 17:13:39 2007 @@ -401,6 +401,11 @@ * @param bean converter assigned to this component */ public void addConverter(ConverterBean bean) { + if (bean == null) { + converter = null; + return; + } + if (bean.getJsfid() != null) { bean.setHasAParent(this); converter = bean; Modified: shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java?view=diff&rev=524333&r1=524332&r2=524333 ============================================================================== --- shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java (original) +++ shale/framework/trunk/shale-clay/src/main/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java Fri Mar 30 17:13:39 2007 @@ -266,20 +266,19 @@ try { if (i > -1) { - for (Enumeration ui = classloader.getResources(configFile.toString()); - ui.hasMoreElements();) { - urls.add(ui.nextElement()); - } + for (Enumeration ui = classloader.getResources(configFile.toString()); + ui.hasMoreElements();) { + urls.add(ui.nextElement()); + } } else { - if(configFile!=null && !StringUtils.isEmpty(configFile.toString())) - { - URL url = context.getResource(configFile.toString()); - if (url == null) { - throw new PageNotFoundException(messages.getMessage("file.notfound", - new Object[] {configFile.toString()}), configFile.toString()); - } - urls.add(url); - } + if (configFile != null && !StringUtils.isEmpty(configFile.toString())) { + URL url = context.getResource(configFile.toString()); + if (url == null) { + throw new PageNotFoundException(messages.getMessage("file.notfound", + new Object[] {configFile.toString()}), configFile.toString()); + } + urls.add(url); + } } } catch (IOException e) { log.error(e); @@ -489,6 +488,46 @@ // assign the parent to a top-level display element b.setIsAParent(getTopLevelElement(b.getExtends())); + + //if the parent contains the "org.apache.shale.clay.final" + //attribute, we ignore the inheritance by not allowing the parent + //generalization relationship + + //however, we still allow aggregate "child" components to + //extend other components + + if ((b.getIsAParent() != null) + && (b.getIsAParent().getAttribute( + Globals.CLAY_ALLOW_OVERRIDE_ATTRIBUTE) != null)) { + + // if the bean is also a top-level component, just don't + // allow it to extend another topl-level component that is + // determined to be final + if (!(b instanceof InnerComponentBean)) { + log.warn(messages.getMessage("override.allowed.warning", + new Object[] {b.getJsfid(), b.getIsAParent().getJsfid()})); + b.setIsAParent(null); + } else { + log.warn(messages.getMessage("override.invalid.warning", + new Object[] {b.getJsfid(), b.getIsAParent().getJsfid()})); + + // the bean is a inner component (element, validator, + // converter, actionListener, valueChangeListener). + // it can only extend a top-level component definition + // marked as "final". Nothing can be overridden except + // symbols. + + b.getChildren().clear(); + b.getAttributes().clear(); + b.getValidators().clear(); + b.setComponentType(null); + b.setFacetName(null); + b.addConverter(null); + b.getActionListeners().clear(); + b.getValueChangeListeners().clear(); + b.setInheritanceFinal(false); + } + } } // resolve inheritance of nested components Modified: shale/framework/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties?view=diff&rev=524333&r1=524332&r2=524333 ============================================================================== --- shale/framework/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties (original) +++ shale/framework/trunk/shale-clay/src/main/resources/org/apache/shale/clay/Bundle.properties Fri Mar 30 17:13:39 2007 @@ -1,4 +1,4 @@ -# Resource Strings for Shale Framework +# Resource Strings for Shale Framework # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -152,3 +152,7 @@ template.encoding = Using charset "{0}" loading template file "{1}". #org.apache.shale.clay.config.ClayTemplateParser template.encoding.notsupported = The charset override "{0}" is not supported. + +#org.apache.shale.clay.config.beans.ComponentBeanConfig +override.allowed.warning=The component configuration definition identified with jsfid "{0}" cannot extend the top-level component definition "{1}" that has been declared final. +override.invalid.warning=The inner component configuration definition "{0}" cannot override any attributes, elements, converter, and listeners of top-level component "{1}" because it that has been declared final. \ No newline at end of file Modified: shale/framework/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/ConfigTestCase.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/ConfigTestCase.java?view=diff&rev=524333&r1=524332&r2=524333 ============================================================================== --- shale/framework/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/ConfigTestCase.java (original) +++ shale/framework/trunk/shale-clay/src/test/java/org/apache/shale/clay/config/ConfigTestCase.java Fri Mar 30 17:13:39 2007 @@ -24,6 +24,8 @@ import org.apache.shale.clay.config.beans.AttributeBean; import org.apache.shale.clay.config.beans.ComponentBean; import org.apache.shale.clay.config.beans.ElementBean; +import org.apache.shale.clay.config.beans.ValidatorBean; +import org.apache.shale.clay.config.beans.ValueChangeListenerBean; // Tests that the clay component metadata can be loaded and inheritance resolved. public class ConfigTestCase extends AbstractTestCaseConfig { @@ -560,6 +562,96 @@ } + //test the allow override flag + public void testFinal() { + // loads the default and the final config file + loadConfigFile("/org/apache/shale/clay/config/final-config.xml"); + + // top-level inheritance on a final component + // the extends will be ignored as if it didn't extend another definition + ComponentBean bean = standardConfigBean.getElement("zipOverrideFinal"); + assertNotNull(bean); + assertEquals("none.provided", bean.getComponentType()); + assertNull(bean.getId()); + assertNull(bean.getAttribute("value")); + assertNull("basesymbol", bean.getSymbol("basesymbol")); + assertEquals("mysymbol", "mysymbol", bean.getSymbol("mysymbol").getValue()); + + // extending a top-level final component as an "element" will not allow you to + // override anything but symbols. All other overrides are ignored + bean = standardConfigBean.getElement("testForm"); + assertNotNull(bean); + + assertEquals(1, bean.getChildren().size()); + + ElementBean childBean = (ElementBean) bean.getChildrenIterator().next(); + assertNotNull(childBean); + checkElementExtendingFinal(childBean); + + // html nodes bound to a JSF component behave like nested "elements". + // when a html node is bound to a top-level final component, it can not + // override anything but the symbols + bean = htmlTemplateConfigBean.getElement("/org/apache/shale/clay/config/final.html"); + assertNotNull(bean); + assertEquals(2, bean.getChildren().size()); + Iterator ci = bean.getChildrenIterator(); + // first node is a "\n" newline withing the template + ci.next(); + + childBean = (ElementBean) ci.next(); + assertNotNull(childBean); + checkElementExtendingFinal(childBean); + + + } + + private void checkElementExtendingFinal(ElementBean childBean) { + assertEquals("componentType", "javax.faces.HtmlInputText", childBean.getComponentType()); + assertEquals("id", "zip", childBean.getId()); + + AttributeBean attr = childBean.getAttribute("maxlength"); + assertNotNull("maxlength", attr); + assertEquals("maxlength", "9", attr.getValue()); + + attr = childBean.getAttribute("size"); + assertNotNull("size", attr); + assertEquals("size", "5", attr.getValue()); + + attr = childBean.getAttribute("value"); + assertNotNull("value", attr); + assertEquals("value", "[EMAIL PROTECTED]", attr.getValue()); + + attr = childBean.getAttribute("valueChangeListener"); + assertNotNull("valueChangeListener", attr); + assertEquals("valueChangeListener", "[EMAIL PROTECTED]", attr.getValue()); + + assertNotNull("converter", childBean.getConverter()); + assertEquals("jsfid", "integerConverter", childBean.getConverter().getJsfid()); + + assertEquals("validator", 1, childBean.getValidators().size()); + ValidatorBean validator = (ValidatorBean) childBean.getValidatorIterator().next(); + assertEquals("jsfid", "longRangeValidator", validator.getJsfid()); + + attr = validator.getAttribute("minimum"); + assertNotNull("minimum", attr); + assertEquals("minimum", "80000", attr.getValue()); + + attr = validator.getAttribute("maximum"); + assertNotNull("maximum", attr); + assertEquals("maximum", "80125", attr.getValue()); + + assertEquals("valueChangeListener", 1, childBean.getValueChangeListeners().size()); + + ValueChangeListenerBean listener = (ValueChangeListenerBean) childBean.getValueChangeListenerIterator().next(); + assertNotNull("valueChangeListener", listener); + assertEquals("jsfid", "testValueChangeListener", listener.getJsfid()); + + assertEquals("basesymbol", "basesymbol", childBean.getSymbol("basesymbol").getValue()); + + // symbol overrides are allowed + assertEquals("mysymbol", "mysymbol", childBean.getSymbol("mysymbol").getValue()); + + } } Added: shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final-config.xml URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final-config.xml?view=auto&rev=524333 ============================================================================== --- shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final-config.xml (added) +++ shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final-config.xml Fri Mar 30 17:13:39 2007 @@ -0,0 +1,82 @@ +<?xml version='1.0' encoding="UTF-8"?> + + <!DOCTYPE view PUBLIC + "-//Apache Software Foundation//DTD Shale Clay View Configuration 1.0//EN" + "http://shale.apache.org/dtds/clay-config_1_0.dtd"> + +<!-- ### clay:remove ### --> +<!-- + 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. +--> +<!-- ### /clay:remove ### --> +<view> + <component jsfid="testActionListener" componentType="org.apache.shale.clay.config.TestActionListener"/> + <component jsfid="testValueChangeListener" componentType="org.apache.shale.clay.config.TestValueChangeListener"/> + <component jsfid="testValueChangeListener2" componentType="org.apache.shale.clay.config.TestValueChangeListener"/> + + <component jsfid="zip" id="zip" extends="inputText"> + <attributes> + <set name="value" value="[EMAIL PROTECTED]" /> + <set name="maxlength" value="9" /> + <set name="size" value="5"/> + <set name="valueChangeListener" value="[EMAIL PROTECTED]" /> + <set name="org.apache.shale.clay.final"> + <description>Declare this config final</description> + </set> + </attributes> + <symbols> + <set name="basesymbol" value="basesymbol" /> + </symbols> + + + <converter jsfid="integerConverter" /> + <validator jsfid="longRangeValidator"> + <attributes> + <set name="minimum" value="80000" /> + <set name="maximum" value="80125" /> + </attributes> + </validator> + <valueChangeListener jsfid="testValueChangeListener" /> + </component> + + <component jsfid="zipOverrideFinal" extends="zip" componentType="none.provided"> + <description>Component config bean extends a component config that + is declared final. Nothing should be inherited. We need to provide a + component type since there will not be any inheritance.</description> + <symbols> + <set name="mysymbol" value="mysymbol" /> + </symbols> + </component> + + + <component jsfid="testForm" extends="form" > + <element renderId="1" jsfid="zip" id="nooverride"> + <attributes> + <set name="value" value="test"/> + <set name="maxlength" value="999" /> + <set name="size" value="555"/> + <set name="valueChangeListener" value="[EMAIL PROTECTED]" /> + </attributes> + <symbols> + <set name="mysymbol" value="mysymbol" /> + </symbols> + + <valueChangeListener jsfid="testValueChangeListener2" /> + </element> + + </component> + +</view> Propchange: shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final-config.xml ------------------------------------------------------------------------------ svn:eol-style = native Added: shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final.html URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final.html?view=auto&rev=524333 ============================================================================== --- shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final.html (added) +++ shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final.html Fri Mar 30 17:13:39 2007 @@ -0,0 +1,19 @@ +<!-- ### clay:remove ### --> +<!-- + 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. +--> +<!-- ### /clay:remove ### --> +<span jsfid="zip" value="test" maxlength="999" size="555" valueChangeListener="[EMAIL PROTECTED]" mysymbol="mysymbol" /> \ No newline at end of file Propchange: shale/framework/trunk/shale-clay/src/test/resources/org/apache/shale/clay/config/final.html ------------------------------------------------------------------------------ svn:eol-style = native