001 // Copyright 2007 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry.form.validator;
016
017 import org.apache.tapestry.IMarkupWriter;
018 import org.apache.tapestry.IRequestCycle;
019 import org.apache.tapestry.form.FormComponentContributorContext;
020 import org.apache.tapestry.form.IFormComponent;
021 import org.apache.tapestry.form.ValidationMessages;
022 import org.apache.tapestry.json.JSONLiteral;
023 import org.apache.tapestry.json.JSONObject;
024 import org.apache.tapestry.valid.ValidationConstants;
025 import org.apache.tapestry.valid.ValidationConstraint;
026 import org.apache.tapestry.valid.ValidationStrings;
027 import org.apache.tapestry.valid.ValidatorException;
028
029 /**
030 * Validates that the input value is the same as the value of another field.
031 * This validator can also work in 'differ' mode.
032 * <p/>
033 * Apply this validator to the second field in question and define the name
034 * of the component against which to compare the current value.
035 *
036 * @since 4.1.2
037 */
038 public class Identity extends BaseValidator {
039
040 private String _fieldName;
041 private int _matchType;
042
043 private static final int DIFFER = 0;
044 private static final int MATCH = 1;
045
046 public Identity()
047 {
048 super();
049 }
050
051 public Identity(String initializer)
052 {
053 super(initializer);
054 }
055
056 public String toString(IFormComponent field, Object value)
057 {
058 if (value == null)
059 return null;
060
061 return value.toString();
062 }
063
064 public void validate(IFormComponent field, ValidationMessages messages, Object object)
065 throws ValidatorException
066 {
067 IFormComponent referent = (IFormComponent) field.getContainer().getComponent(_fieldName);
068 Object referentValue = referent.getBinding("value").getObject();
069
070 //TODO: if component is null treat _fieldName as an ognl expression
071 boolean notEq = notEqual(referentValue, object);
072
073 if (_matchType == MATCH ? notEq : !notEq)
074 throw new ValidatorException(buildIdentityMessage(messages, field, referent),
075 ValidationConstraint.CONSISTENCY);
076 }
077
078 public void renderContribution(IMarkupWriter writer, IRequestCycle cycle,
079 FormComponentContributorContext context, IFormComponent field)
080 {
081 if (field.isDisabled())
082 return;
083
084 IFormComponent referent = (IFormComponent) field.getContainer().getComponent(_fieldName);
085
086 JSONObject profile = context.getProfile();
087
088 if (!profile.has(ValidationConstants.CONSTRAINTS)) {
089 profile.put(ValidationConstants.CONSTRAINTS, new JSONObject());
090 }
091 JSONObject cons = profile.getJSONObject(ValidationConstants.CONSTRAINTS);
092
093 String func = (_matchType == MATCH) ?
094 "tapestry.form.validation.isEqual" :
095 "tapestry.form.validation.isNotEqual";
096
097 accumulateProperty(cons, field.getClientId(),
098 new JSONLiteral("[" + func + ",\""
099 + referent.getClientId() + "\"]"));
100 // could define and use a new ValidationConstants.CONFIRM here to apply to
101 // the profile, but it doesn't support differ.
102 accumulateProfileProperty(field, profile,
103 ValidationConstants.CONSTRAINTS, buildIdentityMessage(context, field, referent));
104 }
105
106 public String getMatch()
107 {
108 return _fieldName;
109 }
110
111 public void setMatch(String field)
112 {
113 _fieldName = field;
114 _matchType = MATCH;
115
116 }
117
118 public String getDiffer()
119 {
120 return _fieldName;
121 }
122
123 public void setDiffer(String field)
124 {
125 _fieldName = field;
126 _matchType = DIFFER;
127 }
128
129 protected String buildIdentityMessage(ValidationMessages messages, IFormComponent field, IFormComponent referent)
130 {
131 Object[] parameters = new Object[]{
132 field.getDisplayName(), new Integer(_matchType), referent.getDisplayName()
133 };
134
135 return messages.formatValidationMessage(getMessage(),
136 ValidationStrings.INVALID_FIELD_EQUALITY, parameters);
137 }
138
139 private boolean notEqual(Object o1, Object o2)
140 {
141 if (o1 == null && o2 == null)
142 return false;
143 if (o1 == null || o2 == null)
144 return true;
145
146 return !o1.equals(o2);
147 }
148
149 }