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 }