001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.compiler.model.validation;
020:
021: import org.apache.beehive.netui.compiler.model.XmlElementSupport;
022: import org.apache.beehive.netui.compiler.model.XmlModelWriter;
023: import org.w3c.dom.Element;
024:
025: import java.util.ArrayList;
026: import java.util.Iterator;
027: import java.util.List;
028: import java.util.Map;
029: import java.util.Collections;
030:
031: public class ValidatableField extends XmlElementSupport {
032: private String _propertyName;
033: private String _displayName;
034: private String _displayNameKey;
035: private boolean _isValidatorOneOne;
036: List _rules = new ArrayList();
037:
038: public ValidatableField(String propertyName, String displayName,
039: String displayNameKey, boolean isValidatorOneOne) {
040: _propertyName = propertyName;
041: _displayName = displayName;
042: _displayNameKey = displayNameKey;
043: _isValidatorOneOne = isValidatorOneOne;
044: }
045:
046: public String getPropertyName() {
047: return _propertyName;
048: }
049:
050: protected boolean hasRule(ValidatorRule rule) {
051: assert rule != null;
052:
053: String name = rule.getRuleName();
054: for (Iterator ii = _rules.iterator(); ii.hasNext();) {
055: ValidatorRule existingRule = (ValidatorRule) ii.next();
056: if (existingRule.getRuleName().equals(name)) {
057: return true;
058: }
059: }
060: return false;
061: }
062:
063: public void addRule(ValidatorRule rule) {
064: assert rule != null;
065:
066: _rules.add(rule);
067: }
068:
069: public ValidatorRule[] getRules() {
070: return (ValidatorRule[]) _rules
071: .toArray(new ValidatorRule[_rules.size()]);
072: }
073:
074: /**
075: * Merge the rule names with the list in the field element's depends attribute.
076: */
077: void mergeDependsList(Element element) {
078: String depends = getElementAttribute(element, "depends");
079: StringBuffer updatedDepends = new StringBuffer();
080:
081: if (depends != null) {
082: updatedDepends.append(depends);
083: } else {
084: depends = "";
085: }
086:
087: ArrayList rules = new ArrayList();
088: for (Iterator i = _rules.iterator(); i.hasNext();) {
089: ValidatorRule rule = (ValidatorRule) i.next();
090: String name = rule.getRuleName();
091:
092: if (depends.indexOf(name) == -1)
093: rules.add(name);
094: }
095: Collections.sort(rules);
096:
097: for (Iterator i = rules.iterator(); i.hasNext();) {
098: if (updatedDepends.length() > 0)
099: updatedDepends.append(',');
100: updatedDepends.append((String) i.next());
101: }
102:
103: if (updatedDepends.length() != 0) {
104: element.setAttribute("depends", updatedDepends.toString());
105: }
106: }
107:
108: public void writeToElement(XmlModelWriter xw, Element element) {
109: assert _propertyName.equals(getElementAttribute(element,
110: "property")) : _propertyName + ", "
111: + getElementAttribute(element, "property");
112:
113: mergeDependsList(element);
114:
115: //
116: // Add the display name as the default first argument (can be overridden by individual rules).
117: //
118: String displayName;
119: boolean displayNameIsResource = false;
120:
121: if (_displayName != null) {
122: displayName = ValidatorConstants.EXPRESSION_KEY_PREFIX
123: + _displayName;
124: displayNameIsResource = true;
125: } else if (_displayNameKey != null) {
126: displayName = _displayNameKey;
127: displayNameIsResource = true;
128: } else {
129: displayName = Character
130: .toUpperCase(_propertyName.charAt(0))
131: + _propertyName.substring(1);
132: }
133:
134: setDefaultArg0Element(xw, displayName, displayNameIsResource,
135: element);
136:
137: //
138: // Go through the rules, and add each one. Each rule can spray into...
139: // 1) an entry in the comma-separated rules dependencies list (handled above with mergeDependsList(),
140: // 2) a set of elements,
141: // 3) a set of elements.
142: //
143: for (Iterator ii = _rules.iterator(); ii.hasNext();) {
144: ValidatorRule rule = (ValidatorRule) ii.next();
145:
146: // Add the message from the rule.
147: setRuleMessage(xw, rule, element);
148:
149: // Add vars from the rule.
150: Map ruleVars = rule.getVars();
151:
152: if (ruleVars != null) {
153: for (Iterator j = ruleVars.entrySet().iterator(); j
154: .hasNext();) {
155: Map.Entry entry = (Map.Entry) j.next();
156: String varName = (String) entry.getKey();
157: Element varElementToUse = findChildElementWithChildText(
158: xw, element, "var", "var-name", varName,
159: true, null);
160: xw.addElementWithText(varElementToUse, "var-value",
161: (String) entry.getValue());
162: }
163: }
164:
165: //
166: // Add message arguments from the rule. If the user didn't specify an args, fill it in with a variable
167: // value from the rule.
168: //
169: Iterator j = ruleVars != null ? ruleVars.keySet()
170: .iterator() : null;
171: setRuleArg(xw, rule, 0, element, null);
172: setRuleArg(xw, rule, 1, element,
173: j != null && j.hasNext() ? (String) j.next() : null);
174: setRuleArg(xw, rule, 2, element,
175: j != null && j.hasNext() ? (String) j.next() : null);
176: setRuleArg(xw, rule, 3, element,
177: j != null && j.hasNext() ? (String) j.next() : null);
178: }
179: }
180:
181: private Element getArgElement(XmlModelWriter xw, Element element,
182: int argNum, String forRuleName, boolean create) {
183: if (_isValidatorOneOne) {
184: String strNum = new Integer(argNum).toString();
185: Element[] argArray = getChildElements(element, "arg");
186: for (int i = 0; i < argArray.length; i++) {
187: Element arg = argArray[i];
188: String argRuleName = getElementAttribute(arg, "name");
189: if ((forRuleName == null && argRuleName == null)
190: || (forRuleName != null && forRuleName
191: .equals(argRuleName))) {
192: if (strNum.equals(getElementAttribute(arg,
193: "position"))) {
194: return arg;
195: }
196: }
197: }
198:
199: Element retVal = null;
200: if (create) {
201: retVal = xw.addElement(element, "arg");
202: setElementAttribute(retVal, "position", strNum);
203: }
204: return retVal;
205: } else {
206: return findChildElement(xw, element, "arg" + argNum,
207: "name", forRuleName, create, null);
208: }
209: }
210:
211: /**
212: * Find or create a default arg 0 element not associated with a specific rule and set it to the display name.
213: */
214: void setDefaultArg0Element(XmlModelWriter xw, String displayName,
215: boolean displayNameIsResource, Element element) {
216: Element defaultArg0Element = getArgElement(xw, element, 0,
217: null, _rules.size() > 0);
218:
219: if (defaultArg0Element != null) {
220: setElementAttribute(defaultArg0Element, "key", displayName);
221: setElementAttribute(defaultArg0Element, "resource", Boolean
222: .toString(displayNameIsResource));
223: defaultArg0Element.removeAttribute("bundle");
224: }
225: }
226:
227: /**
228: * Set up the desired <msg> element and attributes for the given rule.
229: *
230: * @param rule the rule with the message to use
231: */
232: void setRuleMessage(XmlModelWriter xw, ValidatorRule rule,
233: Element element) {
234: String messageKey = rule.getMessageKey();
235: String message = rule.getMessage();
236:
237: if (messageKey != null || message != null) {
238: Element msgElementToUse = findChildElement(xw, element,
239: "msg", "name", rule.getRuleName(), true, null);
240: setElementAttribute(msgElementToUse, "resource", true);
241:
242: if (messageKey != null) {
243: setElementAttribute(msgElementToUse, "key", messageKey);
244: if (_isValidatorOneOne) {
245: setElementAttribute(msgElementToUse, "bundle", rule
246: .getBundle());
247: }
248: } else // message != null (it's a hardcoded message)
249: {
250: // Add our special constant as the message key, append the hardcoded message to it.
251: setElementAttribute(msgElementToUse, "key",
252: ValidatorConstants.EXPRESSION_KEY_PREFIX
253: + message);
254: }
255: }
256: }
257:
258: /**
259: * Set up the desired <arg> element and attributes for the given rule.
260: *
261: * @param rule the rule with the message and arg information to use
262: * @param argNum the position of the arg in the message
263: * @param element a <code><field></code> element in the validation XML to update
264: * @param altMessageVar alternative message var
265: */
266: void setRuleArg(XmlModelWriter xw, ValidatorRule rule, int argNum,
267: Element element, String altMessageVar) {
268: Integer argPosition = new Integer(argNum);
269: ValidatorRule.MessageArg arg = rule.getArg(argPosition);
270:
271: if (arg != null || altMessageVar != null) {
272: String ruleName = rule.getRuleName();
273: Element argElementToUse = getArgElement(xw, element,
274: argNum, ruleName, true);
275:
276: if (arg != null) {
277: String argMessage = arg.getMessage();
278: String key = arg.isKey() ? argMessage
279: : ValidatorConstants.EXPRESSION_KEY_PREFIX
280: + argMessage;
281: setElementAttribute(argElementToUse, "key", key);
282: setElementAttribute(argElementToUse, "resource", true);
283: if (arg.isKey() && _isValidatorOneOne) {
284: setElementAttribute(argElementToUse, "bundle", rule
285: .getBundle());
286: }
287: } else {
288: altMessageVar = "${var:" + altMessageVar + '}';
289: setElementAttribute(argElementToUse, "key",
290: altMessageVar);
291: setElementAttribute(argElementToUse, "resource",
292: "false");
293: }
294:
295: setElementAttribute(argElementToUse, "name", ruleName);
296: }
297: }
298:
299: public String getDisplayName() {
300: return _displayName;
301: }
302:
303: public void setDisplayName(String displayName) {
304: _displayName = displayName;
305: }
306:
307: public String getDisplayNameKey() {
308: return _displayNameKey;
309: }
310:
311: public void setDisplayNameKey(String displayNameKey) {
312: _displayNameKey = displayNameKey;
313: }
314: }
|