You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2014/06/03 18:21:18 UTC

[1/4] git commit: A bit more refactoring, might as well get the name just right

Repository: tapestry-5
Updated Branches:
  refs/heads/master 24d47d1a2 -> 69e672d05


A bit more refactoring, might as well get the name just right


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/69e672d0
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/69e672d0
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/69e672d0

Branch: refs/heads/master
Commit: 69e672d055d3b9da5c9aef30b01bbd4dbc27ae0b
Parents: 6e63b05
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Tue Jun 3 09:21:19 2014 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Tue Jun 3 09:21:33 2014 -0700

----------------------------------------------------------------------
 .../tapestry5/corelib/base/AbstractField.java   |  4 ++--
 .../tapestry5/corelib/components/Form.java      |  2 +-
 .../tapestry5/internal/InternalSymbols.java     |  8 ++++---
 .../services/FormControlNameManager.java        | 25 +++++++++++---------
 .../services/FormControlNameManagerImpl.java    |  6 ++---
 .../tapestry5/modules/TapestryModule.java       |  2 +-
 6 files changed, 26 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/69e672d0/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
index 871499e..eec94df 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
@@ -218,13 +218,13 @@ public abstract class AbstractField implements Field
             // by id OR name; so an id of "submit" (for example) will mask the HTMLFormElement.submit()
             // function.
 
-            if (formControlNameManager.isPreselected(clientId))
+            if (formControlNameManager.isReserved(clientId))
             {
                 throw new TapestryException(String.format(
                         "The value '%s' for parameter clientId is not allowed as it causes a naming conflict in the client-side DOM. " +
                                 "Select an id not in the list: %s.",
                         clientId,
-                        InternalUtils.joinSorted(formControlNameManager.getPreselectedNames())), this, null);
+                        InternalUtils.joinSorted(formControlNameManager.getReservedNames())), this, null);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/69e672d0/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
index 9f2452d..1347484 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
@@ -739,7 +739,7 @@ public class Form implements ClientElement, FormValidationControl
 
     private void preallocateNames(IdAllocator idAllocator)
     {
-        for (String name : formControlNameManager.getPreselectedNames())
+        for (String name : formControlNameManager.getReservedNames())
         {
             idAllocator.allocateId(name);
             // See https://issues.apache.org/jira/browse/TAP5-1632

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/69e672d0/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java
index 87c25a4..1066c71 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java
@@ -1,5 +1,3 @@
-// Copyright 2009, 2010, 2011 The Apache Software Foundation
-//
 // Licensed 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
@@ -14,6 +12,8 @@
 
 package org.apache.tapestry5.internal;
 
+import org.apache.tapestry5.ioc.annotations.IncompatibleChange;
+
 public class InternalSymbols
 {
     /**
@@ -34,8 +34,10 @@ public class InternalSymbols
      * Comma-separated list of pre-allocated Form component control names. Basically, this exists to
      * work around name collisions on the client side. Starting in 5.3, these names are
      * also pre-allocated as ids.
+     * <p/>
      *
      * @since 5.2.0
      */
-    public static final String PRE_SELECTED_FORM_NAMES = "tapestry.pre-selected-form-names";
+    @IncompatibleChange(release = "5.4", details = "Renamed from PRE_SELECTED_FORM_NAMES.")
+    public static final String RESERVED_FORM_CONTROL_NAMES = "tapestry.reserved-form-control-names";
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/69e672d0/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
index 7179197..e4b92f0 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
@@ -11,29 +11,32 @@
 // limitations under the License.package org.apache.tapestry5.internal.services;
 package org.apache.tapestry5.internal.services;
 
-import java.util.Set;
-
 import org.apache.tapestry5.internal.InternalSymbols;
 
+import java.util.Set;
+
 /**
- * Service providing methods related to names that shouldn't be used as HTML elements client ids.
- * 
- * @see InternalSymbols#PRE_SELECTED_FORM_NAMES
+ * Service providing methods related to names that shouldn't be used as form control element
+ * names or ids.
+ *
+ * @see InternalSymbols#RESERVED_FORM_CONTROL_NAMES
  */
 public interface FormControlNameManager
 {
     /**
-     * Returns the set of pre-selected form names (ones that shouldn't be used as HTML elements
+     * Returns the set of reserved form names (ones that shouldn't be used as HTML elements
      * client ids).
+     *
      * @return a {@link Set} of {@link String}s.
      */
-    Set<String> getPreselectedNames();
-    
+    Set<String> getReservedNames();
+
     /**
-     * Tells whether a given name is pre-selected.
+     * Tells whether a given name is reserved.
+     *
      * @param string
      * @return
      */
-    boolean isPreselected(String name);
-    
+    boolean isReserved(String name);
+
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/69e672d0/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
index 5e586c2..fc5365d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
@@ -25,19 +25,19 @@ public class FormControlNameManagerImpl implements FormControlNameManager
     final private Set<String> names;
 
     public FormControlNameManagerImpl(
-            @Symbol(InternalSymbols.PRE_SELECTED_FORM_NAMES) String preselectedFormNames)
+            @Symbol(InternalSymbols.RESERVED_FORM_CONTROL_NAMES) String preselectedFormNames)
     {
         this.names = Collections.unmodifiableSet(CollectionFactory.<String,String>newSet(TapestryInternalUtils.splitAtCommas(preselectedFormNames)));
     }
 
     @Override
-    public Set<String> getPreselectedNames()
+    public Set<String> getReservedNames()
     {
         return names;
     }
 
     @Override
-    public boolean isPreselected(String name)
+    public boolean isReserved(String name)
     {
         return names.contains(name.toLowerCase());
     }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/69e672d0/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
index 78e1523..63c114b 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
@@ -2063,7 +2063,7 @@ public final class TapestryModule
 
         configuration.add(SymbolConstants.ENCODE_LOCALE_INTO_PATH, true);
 
-        configuration.add(InternalSymbols.PRE_SELECTED_FORM_NAMES, "reset,submit,select,id,method,action,onsubmit," + InternalConstants.CANCEL_NAME);
+        configuration.add(InternalSymbols.RESERVED_FORM_CONTROL_NAMES, "reset,submit,select,id,method,action,onsubmit," + InternalConstants.CANCEL_NAME);
 
         configuration.add(SymbolConstants.COMPONENT_RENDER_TRACING_ENABLED, false);
 


[2/4] git commit: Some minor refactorings to more pleasant service names

Posted by hl...@apache.org.
Some minor refactorings to more pleasant service names

Also, only complain about a pre-selected client id if not ensuring uniqueness


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

Branch: refs/heads/master
Commit: c8a7eddbacdf718dfd82d3fc14f692f09fe6f7d2
Parents: 193d022
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Tue Jun 3 09:15:52 2014 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Tue Jun 3 09:21:33 2014 -0700

----------------------------------------------------------------------
 .../tapestry5/corelib/base/AbstractField.java   | 27 ++++++-----
 .../tapestry5/corelib/components/Form.java      |  8 ++--
 .../services/FormControlNameManager.java        | 39 ++++++++++++++++
 .../services/FormControlNameManagerImpl.java    | 45 +++++++++++++++++++
 .../services/PreSelectedFormNamesService.java   | 39 ----------------
 .../PreSelectedFormNamesServiceImpl.java        | 47 --------------------
 .../tapestry5/modules/InternalModule.java       |  4 +-
 7 files changed, 105 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
index beb4d1d..871499e 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
@@ -18,7 +18,7 @@ import org.apache.tapestry5.corelib.mixins.DiscardBody;
 import org.apache.tapestry5.corelib.mixins.RenderInformals;
 import org.apache.tapestry5.internal.BeanValidationContext;
 import org.apache.tapestry5.internal.InternalComponentResources;
-import org.apache.tapestry5.internal.services.PreSelectedFormNamesService;
+import org.apache.tapestry5.internal.services.FormControlNameManager;
 import org.apache.tapestry5.ioc.annotations.Inject;
 import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
@@ -169,7 +169,7 @@ public abstract class AbstractField implements Field
     protected FieldValidationSupport fieldValidationSupport;
 
     @Inject
-    private PreSelectedFormNamesService preSelectedFormNamesService;
+    private FormControlNameManager formControlNameManager;
 
     final String defaultLabel()
     {
@@ -207,18 +207,25 @@ public abstract class AbstractField implements Field
             return javaScriptSupport.allocateClientId(resources);
         }
 
-        if (preSelectedFormNamesService.isPreselected(clientId))
-        {
-            throw new TapestryException(String.format(
-                    "The value '%s' for parameter clientId is not allowed as it causes a naming conflict in the client-side DOM. " +
-                            "Select a name not in the list: %s.",
-                    clientId,
-                    InternalUtils.joinSorted(preSelectedFormNamesService.getNames())), this, null);
-        }
 
         if (ensureClientIdUnique)
         {
             return javaScriptSupport.allocateClientId(clientId);
+        } else
+        {
+            // See https://issues.apache.org/jira/browse/TAP5-1632
+            // Basically, on the client, there can be a convenience lookup inside a HTMLFormElement
+            // by id OR name; so an id of "submit" (for example) will mask the HTMLFormElement.submit()
+            // function.
+
+            if (formControlNameManager.isPreselected(clientId))
+            {
+                throw new TapestryException(String.format(
+                        "The value '%s' for parameter clientId is not allowed as it causes a naming conflict in the client-side DOM. " +
+                                "Select an id not in the list: %s.",
+                        clientId,
+                        InternalUtils.joinSorted(formControlNameManager.getPreselectedNames())), this, null);
+            }
         }
 
         return clientId;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
index bb8d6a0..9f2452d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
@@ -1,5 +1,3 @@
-// Copyright 2006-2014 The Apache Software Foundation
-//
 // Licensed 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
@@ -22,8 +20,8 @@ import org.apache.tapestry5.corelib.internal.FormSupportImpl;
 import org.apache.tapestry5.corelib.internal.InternalFormSupport;
 import org.apache.tapestry5.dom.Element;
 import org.apache.tapestry5.internal.*;
+import org.apache.tapestry5.internal.services.FormControlNameManager;
 import org.apache.tapestry5.internal.services.HeartbeatImpl;
-import org.apache.tapestry5.internal.services.PreSelectedFormNamesService;
 import org.apache.tapestry5.internal.util.AutofocusValidationDecorator;
 import org.apache.tapestry5.ioc.Location;
 import org.apache.tapestry5.ioc.Messages;
@@ -223,7 +221,7 @@ public class Form implements ClientElement, FormValidationControl
     private ComponentSource source;
 
     @Inject
-    private PreSelectedFormNamesService preSelectedFormNamesService;
+    private FormControlNameManager formControlNameManager;
 
 
     /**
@@ -741,7 +739,7 @@ public class Form implements ClientElement, FormValidationControl
 
     private void preallocateNames(IdAllocator idAllocator)
     {
-        for (String name : preSelectedFormNamesService.getNames())
+        for (String name : formControlNameManager.getPreselectedNames())
         {
             idAllocator.allocateId(name);
             // See https://issues.apache.org/jira/browse/TAP5-1632

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
new file mode 100644
index 0000000..7179197
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
@@ -0,0 +1,39 @@
+// Licensed 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.tapestry5.internal.services;
+package org.apache.tapestry5.internal.services;
+
+import java.util.Set;
+
+import org.apache.tapestry5.internal.InternalSymbols;
+
+/**
+ * Service providing methods related to names that shouldn't be used as HTML elements client ids.
+ * 
+ * @see InternalSymbols#PRE_SELECTED_FORM_NAMES
+ */
+public interface FormControlNameManager
+{
+    /**
+     * Returns the set of pre-selected form names (ones that shouldn't be used as HTML elements
+     * client ids).
+     * @return a {@link Set} of {@link String}s.
+     */
+    Set<String> getPreselectedNames();
+    
+    /**
+     * Tells whether a given name is pre-selected.
+     * @param string
+     * @return
+     */
+    boolean isPreselected(String name);
+    
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
new file mode 100644
index 0000000..5e586c2
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
@@ -0,0 +1,45 @@
+// Licensed 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.tapestry5.internal.services;
+package org.apache.tapestry5.internal.services;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.InternalSymbols;
+import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+public class FormControlNameManagerImpl implements FormControlNameManager
+{
+    
+    final private Set<String> names;
+
+    public FormControlNameManagerImpl(
+            @Symbol(InternalSymbols.PRE_SELECTED_FORM_NAMES) String preselectedFormNames)
+    {
+        this.names = Collections.unmodifiableSet(CollectionFactory.<String,String>newSet(TapestryInternalUtils.splitAtCommas(preselectedFormNames)));
+    }
+
+    @Override
+    public Set<String> getPreselectedNames()
+    {
+        return names;
+    }
+
+    @Override
+    public boolean isPreselected(String name)
+    {
+        return names.contains(name.toLowerCase());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
deleted file mode 100644
index 379c53b..0000000
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Licensed 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.tapestry5.internal.services;
-package org.apache.tapestry5.internal.services;
-
-import java.util.Set;
-
-import org.apache.tapestry5.internal.InternalSymbols;
-
-/**
- * Service providing methods related to names that shouldn't be used as HTML elements client ids.
- * 
- * @see InternalSymbols#PRE_SELECTED_FORM_NAMES
- */
-public interface PreSelectedFormNamesService
-{
-    /**
-     * Returns the set of pre-selected form names (ones that shouldn't be used as HTML elements
-     * client ids.
-     * @return a {@link Set} of {@link String}s.
-     */
-    Set<String> getNames();
-    
-    /**
-     * Tells whether a given name is pre-selected.
-     * @param string
-     * @return
-     */
-    boolean isPreselected(String name);
-    
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesServiceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesServiceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesServiceImpl.java
deleted file mode 100644
index a6c801b..0000000
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesServiceImpl.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 The Apache Software Foundation
-//
-// Licensed 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.tapestry5.internal.services;
-package org.apache.tapestry5.internal.services;
-
-import java.util.Collections;
-import java.util.Set;
-
-import org.apache.tapestry5.internal.InternalSymbols;
-import org.apache.tapestry5.internal.TapestryInternalUtils;
-import org.apache.tapestry5.ioc.annotations.Symbol;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-
-public class PreSelectedFormNamesServiceImpl implements PreSelectedFormNamesService
-{
-    
-    final private Set<String> names;
-
-    public PreSelectedFormNamesServiceImpl(    
-            @Symbol(InternalSymbols.PRE_SELECTED_FORM_NAMES) String preselectedFormNames)
-    {
-        this.names = Collections.unmodifiableSet(CollectionFactory.<String,String>newSet(TapestryInternalUtils.splitAtCommas(preselectedFormNames)));
-    }
-
-    @Override
-    public Set<String> getNames()
-    {
-        return names;
-    }
-
-    @Override
-    public boolean isPreselected(String name)
-    {
-        return names.contains(name.toLowerCase());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
index 32473ac..6d7f967 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
@@ -1,5 +1,3 @@
-// Copyright 2008-2013 The Apache Software Foundation
-//
 // Licensed 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
@@ -72,7 +70,7 @@ public class InternalModule
         binder.bind(PageLoader.class, PageLoaderImpl.class).preventReloading();
         binder.bind(UnknownActivationContextHandler.class, UnknownActivationContextHandlerImpl.class);
         binder.bind(ReloadHelper.class, ReloadHelperImpl.class);
-        binder.bind(PreSelectedFormNamesService.class, PreSelectedFormNamesServiceImpl.class);
+        binder.bind(FormControlNameManager.class, FormControlNameManagerImpl.class);
 
     }
 


[3/4] git commit: Allow IncompatibleChange to be attached to fields as well as methods

Posted by hl...@apache.org.
Allow IncompatibleChange to be attached to fields as well as methods


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/6e63b052
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/6e63b052
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/6e63b052

Branch: refs/heads/master
Commit: 6e63b052ac090dca7a8496838e9888cf8b48340d
Parents: c8a7edd
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Tue Jun 3 09:18:47 2014 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Tue Jun 3 09:21:33 2014 -0700

----------------------------------------------------------------------
 .../org/apache/tapestry5/ioc/annotations/IncompatibleChange.java | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6e63b052/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java
index 38b1535..ffc9490 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java
@@ -1,5 +1,3 @@
-//  Copyright 2013 The Apache Software Foundation
-//
 // Licensed 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
@@ -16,7 +14,7 @@ package org.apache.tapestry5.ioc.annotations;
 
 import java.lang.annotation.*;
 
-@Target(ElementType.METHOD)
+@Target({ElementType.METHOD, ElementType.FIELD})
 @Retention(RetentionPolicy.CLASS)
 @Documented
 public @interface IncompatibleChange


[2/4] git commit: Some minor refactorings to more pleasant service names

Posted by hl...@apache.org.
Some minor refactorings to more pleasant service names

Also, only complain about a pre-selected client id if not ensuring uniqueness


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

Branch: refs/heads/master
Commit: c8a7eddbacdf718dfd82d3fc14f692f09fe6f7d2
Parents: 193d022
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Tue Jun 3 09:15:52 2014 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Tue Jun 3 09:21:33 2014 -0700

----------------------------------------------------------------------
 .../tapestry5/corelib/base/AbstractField.java   | 27 ++++++-----
 .../tapestry5/corelib/components/Form.java      |  8 ++--
 .../services/FormControlNameManager.java        | 39 ++++++++++++++++
 .../services/FormControlNameManagerImpl.java    | 45 +++++++++++++++++++
 .../services/PreSelectedFormNamesService.java   | 39 ----------------
 .../PreSelectedFormNamesServiceImpl.java        | 47 --------------------
 .../tapestry5/modules/InternalModule.java       |  4 +-
 7 files changed, 105 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
index beb4d1d..871499e 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
@@ -18,7 +18,7 @@ import org.apache.tapestry5.corelib.mixins.DiscardBody;
 import org.apache.tapestry5.corelib.mixins.RenderInformals;
 import org.apache.tapestry5.internal.BeanValidationContext;
 import org.apache.tapestry5.internal.InternalComponentResources;
-import org.apache.tapestry5.internal.services.PreSelectedFormNamesService;
+import org.apache.tapestry5.internal.services.FormControlNameManager;
 import org.apache.tapestry5.ioc.annotations.Inject;
 import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
@@ -169,7 +169,7 @@ public abstract class AbstractField implements Field
     protected FieldValidationSupport fieldValidationSupport;
 
     @Inject
-    private PreSelectedFormNamesService preSelectedFormNamesService;
+    private FormControlNameManager formControlNameManager;
 
     final String defaultLabel()
     {
@@ -207,18 +207,25 @@ public abstract class AbstractField implements Field
             return javaScriptSupport.allocateClientId(resources);
         }
 
-        if (preSelectedFormNamesService.isPreselected(clientId))
-        {
-            throw new TapestryException(String.format(
-                    "The value '%s' for parameter clientId is not allowed as it causes a naming conflict in the client-side DOM. " +
-                            "Select a name not in the list: %s.",
-                    clientId,
-                    InternalUtils.joinSorted(preSelectedFormNamesService.getNames())), this, null);
-        }
 
         if (ensureClientIdUnique)
         {
             return javaScriptSupport.allocateClientId(clientId);
+        } else
+        {
+            // See https://issues.apache.org/jira/browse/TAP5-1632
+            // Basically, on the client, there can be a convenience lookup inside a HTMLFormElement
+            // by id OR name; so an id of "submit" (for example) will mask the HTMLFormElement.submit()
+            // function.
+
+            if (formControlNameManager.isPreselected(clientId))
+            {
+                throw new TapestryException(String.format(
+                        "The value '%s' for parameter clientId is not allowed as it causes a naming conflict in the client-side DOM. " +
+                                "Select an id not in the list: %s.",
+                        clientId,
+                        InternalUtils.joinSorted(formControlNameManager.getPreselectedNames())), this, null);
+            }
         }
 
         return clientId;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
index bb8d6a0..9f2452d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
@@ -1,5 +1,3 @@
-// Copyright 2006-2014 The Apache Software Foundation
-//
 // Licensed 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
@@ -22,8 +20,8 @@ import org.apache.tapestry5.corelib.internal.FormSupportImpl;
 import org.apache.tapestry5.corelib.internal.InternalFormSupport;
 import org.apache.tapestry5.dom.Element;
 import org.apache.tapestry5.internal.*;
+import org.apache.tapestry5.internal.services.FormControlNameManager;
 import org.apache.tapestry5.internal.services.HeartbeatImpl;
-import org.apache.tapestry5.internal.services.PreSelectedFormNamesService;
 import org.apache.tapestry5.internal.util.AutofocusValidationDecorator;
 import org.apache.tapestry5.ioc.Location;
 import org.apache.tapestry5.ioc.Messages;
@@ -223,7 +221,7 @@ public class Form implements ClientElement, FormValidationControl
     private ComponentSource source;
 
     @Inject
-    private PreSelectedFormNamesService preSelectedFormNamesService;
+    private FormControlNameManager formControlNameManager;
 
 
     /**
@@ -741,7 +739,7 @@ public class Form implements ClientElement, FormValidationControl
 
     private void preallocateNames(IdAllocator idAllocator)
     {
-        for (String name : preSelectedFormNamesService.getNames())
+        for (String name : formControlNameManager.getPreselectedNames())
         {
             idAllocator.allocateId(name);
             // See https://issues.apache.org/jira/browse/TAP5-1632

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
new file mode 100644
index 0000000..7179197
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManager.java
@@ -0,0 +1,39 @@
+// Licensed 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.tapestry5.internal.services;
+package org.apache.tapestry5.internal.services;
+
+import java.util.Set;
+
+import org.apache.tapestry5.internal.InternalSymbols;
+
+/**
+ * Service providing methods related to names that shouldn't be used as HTML elements client ids.
+ * 
+ * @see InternalSymbols#PRE_SELECTED_FORM_NAMES
+ */
+public interface FormControlNameManager
+{
+    /**
+     * Returns the set of pre-selected form names (ones that shouldn't be used as HTML elements
+     * client ids).
+     * @return a {@link Set} of {@link String}s.
+     */
+    Set<String> getPreselectedNames();
+    
+    /**
+     * Tells whether a given name is pre-selected.
+     * @param string
+     * @return
+     */
+    boolean isPreselected(String name);
+    
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
new file mode 100644
index 0000000..5e586c2
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/FormControlNameManagerImpl.java
@@ -0,0 +1,45 @@
+// Licensed 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.tapestry5.internal.services;
+package org.apache.tapestry5.internal.services;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.InternalSymbols;
+import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+public class FormControlNameManagerImpl implements FormControlNameManager
+{
+    
+    final private Set<String> names;
+
+    public FormControlNameManagerImpl(
+            @Symbol(InternalSymbols.PRE_SELECTED_FORM_NAMES) String preselectedFormNames)
+    {
+        this.names = Collections.unmodifiableSet(CollectionFactory.<String,String>newSet(TapestryInternalUtils.splitAtCommas(preselectedFormNames)));
+    }
+
+    @Override
+    public Set<String> getPreselectedNames()
+    {
+        return names;
+    }
+
+    @Override
+    public boolean isPreselected(String name)
+    {
+        return names.contains(name.toLowerCase());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
deleted file mode 100644
index 379c53b..0000000
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Licensed 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.tapestry5.internal.services;
-package org.apache.tapestry5.internal.services;
-
-import java.util.Set;
-
-import org.apache.tapestry5.internal.InternalSymbols;
-
-/**
- * Service providing methods related to names that shouldn't be used as HTML elements client ids.
- * 
- * @see InternalSymbols#PRE_SELECTED_FORM_NAMES
- */
-public interface PreSelectedFormNamesService
-{
-    /**
-     * Returns the set of pre-selected form names (ones that shouldn't be used as HTML elements
-     * client ids.
-     * @return a {@link Set} of {@link String}s.
-     */
-    Set<String> getNames();
-    
-    /**
-     * Tells whether a given name is pre-selected.
-     * @param string
-     * @return
-     */
-    boolean isPreselected(String name);
-    
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesServiceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesServiceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesServiceImpl.java
deleted file mode 100644
index a6c801b..0000000
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesServiceImpl.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 The Apache Software Foundation
-//
-// Licensed 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.tapestry5.internal.services;
-package org.apache.tapestry5.internal.services;
-
-import java.util.Collections;
-import java.util.Set;
-
-import org.apache.tapestry5.internal.InternalSymbols;
-import org.apache.tapestry5.internal.TapestryInternalUtils;
-import org.apache.tapestry5.ioc.annotations.Symbol;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-
-public class PreSelectedFormNamesServiceImpl implements PreSelectedFormNamesService
-{
-    
-    final private Set<String> names;
-
-    public PreSelectedFormNamesServiceImpl(    
-            @Symbol(InternalSymbols.PRE_SELECTED_FORM_NAMES) String preselectedFormNames)
-    {
-        this.names = Collections.unmodifiableSet(CollectionFactory.<String,String>newSet(TapestryInternalUtils.splitAtCommas(preselectedFormNames)));
-    }
-
-    @Override
-    public Set<String> getNames()
-    {
-        return names;
-    }
-
-    @Override
-    public boolean isPreselected(String name)
-    {
-        return names.contains(name.toLowerCase());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/c8a7eddb/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
index 32473ac..6d7f967 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/InternalModule.java
@@ -1,5 +1,3 @@
-// Copyright 2008-2013 The Apache Software Foundation
-//
 // Licensed 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
@@ -72,7 +70,7 @@ public class InternalModule
         binder.bind(PageLoader.class, PageLoaderImpl.class).preventReloading();
         binder.bind(UnknownActivationContextHandler.class, UnknownActivationContextHandlerImpl.class);
         binder.bind(ReloadHelper.class, ReloadHelperImpl.class);
-        binder.bind(PreSelectedFormNamesService.class, PreSelectedFormNamesServiceImpl.class);
+        binder.bind(FormControlNameManager.class, FormControlNameManagerImpl.class);
 
     }
 


[4/4] git commit: Revised solution for TAP5-2331

Posted by hl...@apache.org.
Revised solution for TAP5-2331


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/193d022b
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/193d022b
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/193d022b

Branch: refs/heads/master
Commit: 193d022be074d90fec562a9915d72af9b85e9ad4
Parents: 24d47d1
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Tue Jun 3 09:05:48 2014 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Tue Jun 3 09:21:33 2014 -0700

----------------------------------------------------------------------
 .../tapestry5/corelib/base/AbstractField.java   | 132 +++++++++----------
 .../corelib/pages/PropertyEditBlocks.java       |  18 ++-
 .../services/PreSelectedFormNamesService.java   |   6 +-
 .../src/test/app1/MultiZoneUpdateInsideForm.tml |   3 +-
 .../integration/app1/AlertsTests.groovy         |  26 ++--
 .../app1/pages/MultiZoneUpdateInsideForm.java   |   2 -
 .../pages/PerFormValidationMessageDemo.java     |   2 -
 7 files changed, 93 insertions(+), 96 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
index dc400d2..beb4d1d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
@@ -1,5 +1,3 @@
-// Copyright 2006-2013 The Apache Software Foundation
-//
 // Licensed 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
@@ -14,24 +12,8 @@
 
 package org.apache.tapestry5.corelib.base;
 
-import java.io.Serializable;
-
-import org.apache.tapestry5.BindingConstants;
-import org.apache.tapestry5.ComponentAction;
-import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.Field;
-import org.apache.tapestry5.FieldValidationSupport;
-import org.apache.tapestry5.SymbolConstants;
-import org.apache.tapestry5.ValidationDecorator;
-import org.apache.tapestry5.ValidationTracker;
-import org.apache.tapestry5.Validator;
-import org.apache.tapestry5.annotations.AfterRender;
-import org.apache.tapestry5.annotations.BeginRender;
-import org.apache.tapestry5.annotations.Environmental;
-import org.apache.tapestry5.annotations.Mixin;
-import org.apache.tapestry5.annotations.Parameter;
-import org.apache.tapestry5.annotations.SetupRender;
-import org.apache.tapestry5.annotations.SupportsInformalParameters;
+import org.apache.tapestry5.*;
+import org.apache.tapestry5.annotations.*;
 import org.apache.tapestry5.corelib.mixins.DiscardBody;
 import org.apache.tapestry5.corelib.mixins.RenderInformals;
 import org.apache.tapestry5.internal.BeanValidationContext;
@@ -39,12 +21,16 @@ import org.apache.tapestry5.internal.InternalComponentResources;
 import org.apache.tapestry5.internal.services.PreSelectedFormNamesService;
 import org.apache.tapestry5.ioc.annotations.Inject;
 import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.internal.util.TapestryException;
 import org.apache.tapestry5.services.ComponentDefaultProvider;
 import org.apache.tapestry5.services.Environment;
 import org.apache.tapestry5.services.FormSupport;
 import org.apache.tapestry5.services.Request;
 import org.apache.tapestry5.services.javascript.JavaScriptSupport;
 
+import java.io.Serializable;
+
 /**
  * Provides initialization of the clientId and elementName properties. In addition, adds the {@link RenderInformals},
  * and {@link DiscardBody} mixins.
@@ -80,7 +66,7 @@ public abstract class AbstractField implements Field
 
     @Inject
     protected Environment environment;
-    
+
     @Inject
     @Symbol(SymbolConstants.FORM_FIELD_CSS_CLASS)
     protected String cssClass;
@@ -130,37 +116,32 @@ public abstract class AbstractField implements Field
     private static final ProcessSubmission PROCESS_SUBMISSION_ACTION = new ProcessSubmission();
 
     /**
-     * The id used to generate a page-unique client-side identifier for the component. 
-     * If this parameter is not bound and this component is rendered multiple times in a request
-     * and <code>forceClientAllocation</code> is false (the default),
-     * a suffix will be appended to the to id to ensure uniqueness. Either way, 
-     * its value may be accessed via the {@link #getClientId() clientId property}.
-     * When this parameter is bound, Tapestry considers the user (developer) is taking care of 
-     * providing unique client-side identifiers. Special care should be taken when the
-     * field is inside a Zone.
-     * <br>
-     * <strong>Default value: the component's t:id</strong>.
-     * <br>
-     * <em>This parameter will be ignored if it receives any of these values:</em>
-     * <ul>
-     *   <li>reset</li>
-     *   <li>submit</li>
-     *   <li>id</li>
-     *   <li>method</li>
-     *   <li>action</li>
-     *   <li>onsubmit</li>
-     *   <li>cancel</li>
-     * </ul>
+     * Used to explicitly set the client-side id of the element for this component. Normally this is not
+     * bound (or null) and {@link org.apache.tapestry5.services.javascript.JavaScriptSupport#allocateClientId(org.apache.tapestry5.ComponentResources)}
+     * is used to generate a unique client-id based on the component's id. In some cases, when creating client-side
+     * behaviors, it is useful to explicitly set a unique id for an element using this parameter.
+     * <p/>
+     * Certain values, such as "submit", "method", "reset", etc., will cause client-side conflicts and are not allowed; using such will
+     * cause a runtime exception.
      */
     @Parameter(defaultPrefix = BindingConstants.LITERAL)
-    protected String clientId;
-    
+    private String clientId;
+
     /**
-     * When true, it forces the clientId to be passed through the id allocator to avoid repeated ids
-     * even when the clientId parameter is bound.
+     * A rarely used option that indicates that the actual client id should start with the clientId parameter (if non-null)
+     * but should still pass that Id through {@link org.apache.tapestry5.services.javascript.JavaScriptSupport#allocateClientId(String)}
+     * to generate the final id.
+     * <p/>
+     * An example of this are the components used inside a {@link org.apache.tapestry5.corelib.components.BeanEditor} which
+     * will specify a clientId (based on the property name) but still require that it be unique.
+     * <p/>
+     * Defaults to false.
+     *
+     * @since 5.4
      */
-    @Parameter("false")
-    private boolean forceClientIdAllocation;
+    @Parameter
+    private boolean ensureClientIdUnique;
+
 
     private String assignedClientId;
 
@@ -186,7 +167,7 @@ public abstract class AbstractField implements Field
 
     @Inject
     protected FieldValidationSupport fieldValidationSupport;
-    
+
     @Inject
     private PreSelectedFormNamesService preSelectedFormNamesService;
 
@@ -195,11 +176,6 @@ public abstract class AbstractField implements Field
         return defaultProvider.defaultLabel(resources);
     }
 
-    final String defaultClientId()
-    {
-        return resources.getId();
-    }
-
     public final String getLabel()
     {
         return label;
@@ -208,11 +184,6 @@ public abstract class AbstractField implements Field
     @SetupRender
     final void setup()
     {
-        // By default, use the component id as the (base) client id. If the clientid
-        // parameter is bound, then that is the value to use.
-
-        String id = clientId;
-
         // Often, these controlName and clientId will end up as the same value. There are many
         // exceptions, including a form that renders inside a loop, or a form inside a component
         // that is used multiple times.
@@ -220,16 +191,39 @@ public abstract class AbstractField implements Field
         if (formSupport == null)
             throw new RuntimeException(String.format("Component %s must be enclosed by a Form component.",
                     resources.getCompleteId()));
-        
-        final boolean avoidAllocation = resources.isBound("clientId") && !forceClientIdAllocation && !preSelectedFormNamesService.isPreselected(clientId);
-        assignedClientId = avoidAllocation ? clientId : javaScriptSupport.allocateClientId(id);
-        
-        String controlName = formSupport.allocateControlName(id);
+
+        assignedClientId = allocateClientId();
+
+        String controlName = formSupport.allocateControlName(assignedClientId);
 
         formSupport.storeAndExecute(this, new Setup(controlName));
         formSupport.store(this, PROCESS_SUBMISSION_ACTION);
     }
 
+    private String allocateClientId()
+    {
+        if (clientId == null)
+        {
+            return javaScriptSupport.allocateClientId(resources);
+        }
+
+        if (preSelectedFormNamesService.isPreselected(clientId))
+        {
+            throw new TapestryException(String.format(
+                    "The value '%s' for parameter clientId is not allowed as it causes a naming conflict in the client-side DOM. " +
+                            "Select a name not in the list: %s.",
+                    clientId,
+                    InternalUtils.joinSorted(preSelectedFormNamesService.getNames())), this, null);
+        }
+
+        if (ensureClientIdUnique)
+        {
+            return javaScriptSupport.allocateClientId(clientId);
+        }
+
+        return clientId;
+    }
+
     public final String getClientId()
     {
         return assignedClientId;
@@ -328,7 +322,10 @@ public abstract class AbstractField implements Field
 
     protected void putPropertyNameIntoBeanValidationContext(String parameterName)
     {
-        if (beanValidationDisabled) { return; }
+        if (beanValidationDisabled)
+        {
+            return;
+        }
 
         String propertyName = ((InternalComponentResources) resources).getPropertyName(parameterName);
 
@@ -346,7 +343,10 @@ public abstract class AbstractField implements Field
 
     protected void removePropertyNameFromBeanValidationContext()
     {
-        if (beanValidationDisabled) { return; }
+        if (beanValidationDisabled)
+        {
+            return;
+        }
 
         BeanValidationContext beanValidationContext = environment.peek(BeanValidationContext.class);
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java
index 0b92f4b..19326cc 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java
@@ -1,5 +1,3 @@
-// Copyright 2007, 2008, 2011 The Apache Software Foundation
-//
 // Licensed 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
@@ -45,52 +43,52 @@ public class PropertyEditBlocks
             parameters = {"value=context.propertyValue", "label=prop:context.label",
                     "translate=prop:textFieldTranslator", "validate=prop:textFieldValidator",
                     "clientId=prop:context.propertyId", "annotationProvider=context",
-                    "forceClientIdAllocation=true"})
+                    "ensureClientIdUnique=true"})
     private TextField textField;
 
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label",
                     "translate=prop:numberFieldTranslator", "validate=prop:numberFieldValidator",
                     "clientId=prop:context.propertyId", "annotationProvider=context",
-                    "forceClientIdAllocation=true"})
+                    "ensureClientIdUnique=true"})
     private TextField numberField;
 
 
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label", "encoder=valueEncoderForProperty",
                     "model=selectModelForProperty", "validate=prop:selectValidator",
-                    "clientId=prop:context.propertyId", "forceClientIdAllocation=true"})
+                    "clientId=prop:context.propertyId", "ensureClientIdUnique=true"})
     private Select select;
 
     @SuppressWarnings("unused")
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label",
-                    "clientId=prop:context.propertyId", "forceClientIdAllocation=true"})
+                    "clientId=prop:context.propertyId", "ensureClientIdUnique=true"})
     private Checkbox checkboxField;
 
     @SuppressWarnings("unused")
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label", "clientId=prop:context.propertyid",
-                    "validate=prop:dateFieldValidator", "forceClientIdAllocation=true"})
+                    "validate=prop:dateFieldValidator", "ensureClientIdUnique=true"})
     private DateField dateField;
 
     @SuppressWarnings("unused")
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label", "clientId=prop:context.propertyid",
-                    "validate=prop:calendarFieldValidator", "forceClientIdAllocation=true"})
+                    "validate=prop:calendarFieldValidator", "ensureClientIdUnique=true"})
     private DateField calendarField;
 
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label",
                     "translate=prop:passwordFieldTranslator", "validate=prop:passwordFieldValidator",
-                    "clientId=prop:context.propertyId", "annotationProvider=context", "forceClientIdAllocation=true"})
+                    "clientId=prop:context.propertyId", "annotationProvider=context", "ensureClientIdUnique=true"})
     private PasswordField passwordField;
 
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label",
                     "translate=prop:textAreaTranslator",
                     "validate=prop:textAreaValidator", "clientId=prop:context.propertyId",
-                    "annotationProvider=context", "forceClientIdAllocation=true"})
+                    "annotationProvider=context", "ensureClientIdUnique=true"})
     private TextArea textArea;
 
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
index fc00ba6..379c53b 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
@@ -1,5 +1,3 @@
-// Copyright 2014 The Apache Software Foundation
-//
 // Licensed 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
@@ -18,9 +16,9 @@ import java.util.Set;
 import org.apache.tapestry5.internal.InternalSymbols;
 
 /**
- * Service provinding methods related to names that shouldn't be used as HTML elements client ids.
+ * Service providing methods related to names that shouldn't be used as HTML elements client ids.
  * 
- * @see InternalSymbols.PRE_SELECTED_FORM_NAMES
+ * @see InternalSymbols#PRE_SELECTED_FORM_NAMES
  */
 public interface PreSelectedFormNamesService
 {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml b/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml
index ca3180e..5334b34 100644
--- a/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml
+++ b/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml
@@ -8,7 +8,8 @@
     <t:zone t:id="select1ValueZone" visible="false">Show</t:zone>
     <t:zone t:id="select2ValueZone">
       <t:label for="selectValue2"/>
-      <select t:type="Select" t:id="selectValue2" t:validate="required"/>
+      <!-- Only necessary to "lock down" the clientId to facilliate the test. -->
+      <select t:type="Select" t:id="selectValue2" clientId="selectValue2" t:validate="required"/>
     </t:zone>
     <br/>
     <input type="submit" value="Upate Form"/>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy
index 4cf2aa9..081445b 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy
@@ -1,5 +1,3 @@
-// Copyright 2011-2013 The Apache Software Foundation
-//
 // Licensed 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
@@ -99,9 +97,14 @@ class AlertsTests extends App1TestCase {
     void ajax_update_and_remove() {
         openLinks "Alerts Demo", "Reset Alerts Storage"
 
-        select "css=#ajax select[name=\"severity\"]", "Error"
-        select "css=#ajax select[name=\"duration\"]", "Until Dismissed"
-        type "css=#ajax input[name=\"message\"]", "ajax error until"
+        def severitySelector = "css=#ajax select[name='severity_0']"
+        def durationSelector = "css=#ajax select[name='duration_0']"
+        def messageSelector = "css=#ajax input[name='message_0']"
+        def markupSelector = "css=#ajax input[name='markup_0']"
+
+        select severitySelector, "Error"
+        select durationSelector, "Until Dismissed"
+        type messageSelector, "ajax error until"
 
         click "//input[@value='Ajax Update']"
 
@@ -116,14 +119,15 @@ class AlertsTests extends App1TestCase {
         // Check that the alert container is now empty
 
         assertText "css=$CONTAINER", ""
-        
+
         // Now with markup
         openLinks "Alerts Demo", "Reset Alerts Storage"
-        
-        select "css=#ajax select[name=\"severity\"]", "Warn"
-        select "css=#ajax select[name=\"duration\"]", "Single"
-        check "css=#ajax input[name='markup']"
-        type "css=#ajax input[name='message']", "<a><span>Markup!</span></a>"
+
+        select severitySelector, "Warn"
+        select durationSelector, "Single"
+
+        check markupSelector
+        type messageSelector, "<a><span>Markup!</span></a>"
         
         click "//input[@value='Ajax Update']"
         

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java
index ceccda0..155e755 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java
@@ -1,5 +1,3 @@
-// Copyright 2010 The Apache Software Foundation
-//
 // Licensed 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://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
index 633142b..03399f9 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
@@ -1,5 +1,3 @@
-//  Copyright 2008 The Apache Software Foundation
-//
 // Licensed 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


[3/4] git commit: Allow IncompatibleChange to be attached to fields as well as methods

Posted by hl...@apache.org.
Allow IncompatibleChange to be attached to fields as well as methods


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/6e63b052
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/6e63b052
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/6e63b052

Branch: refs/heads/master
Commit: 6e63b052ac090dca7a8496838e9888cf8b48340d
Parents: c8a7edd
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Tue Jun 3 09:18:47 2014 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Tue Jun 3 09:21:33 2014 -0700

----------------------------------------------------------------------
 .../org/apache/tapestry5/ioc/annotations/IncompatibleChange.java | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/6e63b052/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java
index 38b1535..ffc9490 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/IncompatibleChange.java
@@ -1,5 +1,3 @@
-//  Copyright 2013 The Apache Software Foundation
-//
 // Licensed 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
@@ -16,7 +14,7 @@ package org.apache.tapestry5.ioc.annotations;
 
 import java.lang.annotation.*;
 
-@Target(ElementType.METHOD)
+@Target({ElementType.METHOD, ElementType.FIELD})
 @Retention(RetentionPolicy.CLASS)
 @Documented
 public @interface IncompatibleChange


[4/4] git commit: Revised solution for TAP5-2331

Posted by hl...@apache.org.
Revised solution for TAP5-2331


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/193d022b
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/193d022b
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/193d022b

Branch: refs/heads/master
Commit: 193d022be074d90fec562a9915d72af9b85e9ad4
Parents: 24d47d1
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Tue Jun 3 09:05:48 2014 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Tue Jun 3 09:21:33 2014 -0700

----------------------------------------------------------------------
 .../tapestry5/corelib/base/AbstractField.java   | 132 +++++++++----------
 .../corelib/pages/PropertyEditBlocks.java       |  18 ++-
 .../services/PreSelectedFormNamesService.java   |   6 +-
 .../src/test/app1/MultiZoneUpdateInsideForm.tml |   3 +-
 .../integration/app1/AlertsTests.groovy         |  26 ++--
 .../app1/pages/MultiZoneUpdateInsideForm.java   |   2 -
 .../pages/PerFormValidationMessageDemo.java     |   2 -
 7 files changed, 93 insertions(+), 96 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
index dc400d2..beb4d1d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
@@ -1,5 +1,3 @@
-// Copyright 2006-2013 The Apache Software Foundation
-//
 // Licensed 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
@@ -14,24 +12,8 @@
 
 package org.apache.tapestry5.corelib.base;
 
-import java.io.Serializable;
-
-import org.apache.tapestry5.BindingConstants;
-import org.apache.tapestry5.ComponentAction;
-import org.apache.tapestry5.ComponentResources;
-import org.apache.tapestry5.Field;
-import org.apache.tapestry5.FieldValidationSupport;
-import org.apache.tapestry5.SymbolConstants;
-import org.apache.tapestry5.ValidationDecorator;
-import org.apache.tapestry5.ValidationTracker;
-import org.apache.tapestry5.Validator;
-import org.apache.tapestry5.annotations.AfterRender;
-import org.apache.tapestry5.annotations.BeginRender;
-import org.apache.tapestry5.annotations.Environmental;
-import org.apache.tapestry5.annotations.Mixin;
-import org.apache.tapestry5.annotations.Parameter;
-import org.apache.tapestry5.annotations.SetupRender;
-import org.apache.tapestry5.annotations.SupportsInformalParameters;
+import org.apache.tapestry5.*;
+import org.apache.tapestry5.annotations.*;
 import org.apache.tapestry5.corelib.mixins.DiscardBody;
 import org.apache.tapestry5.corelib.mixins.RenderInformals;
 import org.apache.tapestry5.internal.BeanValidationContext;
@@ -39,12 +21,16 @@ import org.apache.tapestry5.internal.InternalComponentResources;
 import org.apache.tapestry5.internal.services.PreSelectedFormNamesService;
 import org.apache.tapestry5.ioc.annotations.Inject;
 import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.internal.util.TapestryException;
 import org.apache.tapestry5.services.ComponentDefaultProvider;
 import org.apache.tapestry5.services.Environment;
 import org.apache.tapestry5.services.FormSupport;
 import org.apache.tapestry5.services.Request;
 import org.apache.tapestry5.services.javascript.JavaScriptSupport;
 
+import java.io.Serializable;
+
 /**
  * Provides initialization of the clientId and elementName properties. In addition, adds the {@link RenderInformals},
  * and {@link DiscardBody} mixins.
@@ -80,7 +66,7 @@ public abstract class AbstractField implements Field
 
     @Inject
     protected Environment environment;
-    
+
     @Inject
     @Symbol(SymbolConstants.FORM_FIELD_CSS_CLASS)
     protected String cssClass;
@@ -130,37 +116,32 @@ public abstract class AbstractField implements Field
     private static final ProcessSubmission PROCESS_SUBMISSION_ACTION = new ProcessSubmission();
 
     /**
-     * The id used to generate a page-unique client-side identifier for the component. 
-     * If this parameter is not bound and this component is rendered multiple times in a request
-     * and <code>forceClientAllocation</code> is false (the default),
-     * a suffix will be appended to the to id to ensure uniqueness. Either way, 
-     * its value may be accessed via the {@link #getClientId() clientId property}.
-     * When this parameter is bound, Tapestry considers the user (developer) is taking care of 
-     * providing unique client-side identifiers. Special care should be taken when the
-     * field is inside a Zone.
-     * <br>
-     * <strong>Default value: the component's t:id</strong>.
-     * <br>
-     * <em>This parameter will be ignored if it receives any of these values:</em>
-     * <ul>
-     *   <li>reset</li>
-     *   <li>submit</li>
-     *   <li>id</li>
-     *   <li>method</li>
-     *   <li>action</li>
-     *   <li>onsubmit</li>
-     *   <li>cancel</li>
-     * </ul>
+     * Used to explicitly set the client-side id of the element for this component. Normally this is not
+     * bound (or null) and {@link org.apache.tapestry5.services.javascript.JavaScriptSupport#allocateClientId(org.apache.tapestry5.ComponentResources)}
+     * is used to generate a unique client-id based on the component's id. In some cases, when creating client-side
+     * behaviors, it is useful to explicitly set a unique id for an element using this parameter.
+     * <p/>
+     * Certain values, such as "submit", "method", "reset", etc., will cause client-side conflicts and are not allowed; using such will
+     * cause a runtime exception.
      */
     @Parameter(defaultPrefix = BindingConstants.LITERAL)
-    protected String clientId;
-    
+    private String clientId;
+
     /**
-     * When true, it forces the clientId to be passed through the id allocator to avoid repeated ids
-     * even when the clientId parameter is bound.
+     * A rarely used option that indicates that the actual client id should start with the clientId parameter (if non-null)
+     * but should still pass that Id through {@link org.apache.tapestry5.services.javascript.JavaScriptSupport#allocateClientId(String)}
+     * to generate the final id.
+     * <p/>
+     * An example of this are the components used inside a {@link org.apache.tapestry5.corelib.components.BeanEditor} which
+     * will specify a clientId (based on the property name) but still require that it be unique.
+     * <p/>
+     * Defaults to false.
+     *
+     * @since 5.4
      */
-    @Parameter("false")
-    private boolean forceClientIdAllocation;
+    @Parameter
+    private boolean ensureClientIdUnique;
+
 
     private String assignedClientId;
 
@@ -186,7 +167,7 @@ public abstract class AbstractField implements Field
 
     @Inject
     protected FieldValidationSupport fieldValidationSupport;
-    
+
     @Inject
     private PreSelectedFormNamesService preSelectedFormNamesService;
 
@@ -195,11 +176,6 @@ public abstract class AbstractField implements Field
         return defaultProvider.defaultLabel(resources);
     }
 
-    final String defaultClientId()
-    {
-        return resources.getId();
-    }
-
     public final String getLabel()
     {
         return label;
@@ -208,11 +184,6 @@ public abstract class AbstractField implements Field
     @SetupRender
     final void setup()
     {
-        // By default, use the component id as the (base) client id. If the clientid
-        // parameter is bound, then that is the value to use.
-
-        String id = clientId;
-
         // Often, these controlName and clientId will end up as the same value. There are many
         // exceptions, including a form that renders inside a loop, or a form inside a component
         // that is used multiple times.
@@ -220,16 +191,39 @@ public abstract class AbstractField implements Field
         if (formSupport == null)
             throw new RuntimeException(String.format("Component %s must be enclosed by a Form component.",
                     resources.getCompleteId()));
-        
-        final boolean avoidAllocation = resources.isBound("clientId") && !forceClientIdAllocation && !preSelectedFormNamesService.isPreselected(clientId);
-        assignedClientId = avoidAllocation ? clientId : javaScriptSupport.allocateClientId(id);
-        
-        String controlName = formSupport.allocateControlName(id);
+
+        assignedClientId = allocateClientId();
+
+        String controlName = formSupport.allocateControlName(assignedClientId);
 
         formSupport.storeAndExecute(this, new Setup(controlName));
         formSupport.store(this, PROCESS_SUBMISSION_ACTION);
     }
 
+    private String allocateClientId()
+    {
+        if (clientId == null)
+        {
+            return javaScriptSupport.allocateClientId(resources);
+        }
+
+        if (preSelectedFormNamesService.isPreselected(clientId))
+        {
+            throw new TapestryException(String.format(
+                    "The value '%s' for parameter clientId is not allowed as it causes a naming conflict in the client-side DOM. " +
+                            "Select a name not in the list: %s.",
+                    clientId,
+                    InternalUtils.joinSorted(preSelectedFormNamesService.getNames())), this, null);
+        }
+
+        if (ensureClientIdUnique)
+        {
+            return javaScriptSupport.allocateClientId(clientId);
+        }
+
+        return clientId;
+    }
+
     public final String getClientId()
     {
         return assignedClientId;
@@ -328,7 +322,10 @@ public abstract class AbstractField implements Field
 
     protected void putPropertyNameIntoBeanValidationContext(String parameterName)
     {
-        if (beanValidationDisabled) { return; }
+        if (beanValidationDisabled)
+        {
+            return;
+        }
 
         String propertyName = ((InternalComponentResources) resources).getPropertyName(parameterName);
 
@@ -346,7 +343,10 @@ public abstract class AbstractField implements Field
 
     protected void removePropertyNameFromBeanValidationContext()
     {
-        if (beanValidationDisabled) { return; }
+        if (beanValidationDisabled)
+        {
+            return;
+        }
 
         BeanValidationContext beanValidationContext = environment.peek(BeanValidationContext.class);
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java
index 0b92f4b..19326cc 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/PropertyEditBlocks.java
@@ -1,5 +1,3 @@
-// Copyright 2007, 2008, 2011 The Apache Software Foundation
-//
 // Licensed 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
@@ -45,52 +43,52 @@ public class PropertyEditBlocks
             parameters = {"value=context.propertyValue", "label=prop:context.label",
                     "translate=prop:textFieldTranslator", "validate=prop:textFieldValidator",
                     "clientId=prop:context.propertyId", "annotationProvider=context",
-                    "forceClientIdAllocation=true"})
+                    "ensureClientIdUnique=true"})
     private TextField textField;
 
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label",
                     "translate=prop:numberFieldTranslator", "validate=prop:numberFieldValidator",
                     "clientId=prop:context.propertyId", "annotationProvider=context",
-                    "forceClientIdAllocation=true"})
+                    "ensureClientIdUnique=true"})
     private TextField numberField;
 
 
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label", "encoder=valueEncoderForProperty",
                     "model=selectModelForProperty", "validate=prop:selectValidator",
-                    "clientId=prop:context.propertyId", "forceClientIdAllocation=true"})
+                    "clientId=prop:context.propertyId", "ensureClientIdUnique=true"})
     private Select select;
 
     @SuppressWarnings("unused")
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label",
-                    "clientId=prop:context.propertyId", "forceClientIdAllocation=true"})
+                    "clientId=prop:context.propertyId", "ensureClientIdUnique=true"})
     private Checkbox checkboxField;
 
     @SuppressWarnings("unused")
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label", "clientId=prop:context.propertyid",
-                    "validate=prop:dateFieldValidator", "forceClientIdAllocation=true"})
+                    "validate=prop:dateFieldValidator", "ensureClientIdUnique=true"})
     private DateField dateField;
 
     @SuppressWarnings("unused")
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label", "clientId=prop:context.propertyid",
-                    "validate=prop:calendarFieldValidator", "forceClientIdAllocation=true"})
+                    "validate=prop:calendarFieldValidator", "ensureClientIdUnique=true"})
     private DateField calendarField;
 
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label",
                     "translate=prop:passwordFieldTranslator", "validate=prop:passwordFieldValidator",
-                    "clientId=prop:context.propertyId", "annotationProvider=context", "forceClientIdAllocation=true"})
+                    "clientId=prop:context.propertyId", "annotationProvider=context", "ensureClientIdUnique=true"})
     private PasswordField passwordField;
 
     @Component(
             parameters = {"value=context.propertyValue", "label=prop:context.label",
                     "translate=prop:textAreaTranslator",
                     "validate=prop:textAreaValidator", "clientId=prop:context.propertyId",
-                    "annotationProvider=context", "forceClientIdAllocation=true"})
+                    "annotationProvider=context", "ensureClientIdUnique=true"})
     private TextArea textArea;
 
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
index fc00ba6..379c53b 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PreSelectedFormNamesService.java
@@ -1,5 +1,3 @@
-// Copyright 2014 The Apache Software Foundation
-//
 // Licensed 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
@@ -18,9 +16,9 @@ import java.util.Set;
 import org.apache.tapestry5.internal.InternalSymbols;
 
 /**
- * Service provinding methods related to names that shouldn't be used as HTML elements client ids.
+ * Service providing methods related to names that shouldn't be used as HTML elements client ids.
  * 
- * @see InternalSymbols.PRE_SELECTED_FORM_NAMES
+ * @see InternalSymbols#PRE_SELECTED_FORM_NAMES
  */
 public interface PreSelectedFormNamesService
 {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml b/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml
index ca3180e..5334b34 100644
--- a/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml
+++ b/tapestry-core/src/test/app1/MultiZoneUpdateInsideForm.tml
@@ -8,7 +8,8 @@
     <t:zone t:id="select1ValueZone" visible="false">Show</t:zone>
     <t:zone t:id="select2ValueZone">
       <t:label for="selectValue2"/>
-      <select t:type="Select" t:id="selectValue2" t:validate="required"/>
+      <!-- Only necessary to "lock down" the clientId to facilliate the test. -->
+      <select t:type="Select" t:id="selectValue2" clientId="selectValue2" t:validate="required"/>
     </t:zone>
     <br/>
     <input type="submit" value="Upate Form"/>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy
index 4cf2aa9..081445b 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AlertsTests.groovy
@@ -1,5 +1,3 @@
-// Copyright 2011-2013 The Apache Software Foundation
-//
 // Licensed 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
@@ -99,9 +97,14 @@ class AlertsTests extends App1TestCase {
     void ajax_update_and_remove() {
         openLinks "Alerts Demo", "Reset Alerts Storage"
 
-        select "css=#ajax select[name=\"severity\"]", "Error"
-        select "css=#ajax select[name=\"duration\"]", "Until Dismissed"
-        type "css=#ajax input[name=\"message\"]", "ajax error until"
+        def severitySelector = "css=#ajax select[name='severity_0']"
+        def durationSelector = "css=#ajax select[name='duration_0']"
+        def messageSelector = "css=#ajax input[name='message_0']"
+        def markupSelector = "css=#ajax input[name='markup_0']"
+
+        select severitySelector, "Error"
+        select durationSelector, "Until Dismissed"
+        type messageSelector, "ajax error until"
 
         click "//input[@value='Ajax Update']"
 
@@ -116,14 +119,15 @@ class AlertsTests extends App1TestCase {
         // Check that the alert container is now empty
 
         assertText "css=$CONTAINER", ""
-        
+
         // Now with markup
         openLinks "Alerts Demo", "Reset Alerts Storage"
-        
-        select "css=#ajax select[name=\"severity\"]", "Warn"
-        select "css=#ajax select[name=\"duration\"]", "Single"
-        check "css=#ajax input[name='markup']"
-        type "css=#ajax input[name='message']", "<a><span>Markup!</span></a>"
+
+        select severitySelector, "Warn"
+        select durationSelector, "Single"
+
+        check markupSelector
+        type messageSelector, "<a><span>Markup!</span></a>"
         
         click "//input[@value='Ajax Update']"
         

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java
index ceccda0..155e755 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateInsideForm.java
@@ -1,5 +1,3 @@
-// Copyright 2010 The Apache Software Foundation
-//
 // Licensed 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://git-wip-us.apache.org/repos/asf/tapestry-5/blob/193d022b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
index 633142b..03399f9 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PerFormValidationMessageDemo.java
@@ -1,5 +1,3 @@
-//  Copyright 2008 The Apache Software Foundation
-//
 // Licensed 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