001: // Copyright 2004, 2005 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.hivemind.parse;
016:
017: import java.util.ArrayList;
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.ListIterator;
022: import java.util.Map;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.apache.hivemind.Element;
027: import org.apache.hivemind.ErrorHandler;
028: import org.apache.hivemind.schema.AttributeModel;
029: import org.apache.hivemind.schema.ElementModel;
030: import org.apache.hivemind.schema.Rule;
031: import org.apache.hivemind.schema.SchemaProcessor;
032: import org.apache.hivemind.schema.rules.BaseRule;
033: import org.apache.hivemind.schema.rules.CreateObjectRule;
034: import org.apache.hivemind.schema.rules.InvokeParentRule;
035: import org.apache.hivemind.schema.rules.ReadAttributeRule;
036:
037: /**
038: * Descriptor for the <conversion> module descriptor element. This descriptor implements the
039: * {@link Rule}interface and is added as a standard rule to the containing {@link ElementModel}.
040: * When processed it delegates to a {@link CreateObjectRule}, a bunch of {@link ReadAttributeRule},
041: * and finally an {@link InvokeParentRule}.
042: *
043: * @author Howard Lewis Ship
044: */
045: public class ConversionDescriptor extends BaseRule {
046: private static final Log LOG = LogFactory
047: .getLog(ConversionDescriptor.class);
048:
049: private ErrorHandler _errorHandler;
050:
051: private String _className;
052:
053: private String _parentMethodName = "addElement";
054:
055: private Map _attributeNameMappingMap = new HashMap();
056:
057: /** @since 1.1 */
058: private List _attributeMappings = new ArrayList();
059:
060: private List _rules;
061:
062: private ElementModel _elementModel;
063:
064: public ConversionDescriptor(ErrorHandler errorHandler,
065: ElementModel elementModel) {
066: _errorHandler = errorHandler;
067: _elementModel = elementModel;
068: }
069:
070: /**
071: * @since 1.1
072: */
073: public List getAttributeMappings() {
074: return _attributeMappings;
075: }
076:
077: /**
078: * Adds a mapping for an attribute; these come from <map> elements nested within the
079: * <conversion> element. A check for duplicate attribute mappings (that is, duplicated
080: * attribute name), and an error is logged (and the duplicate ignored).
081: */
082: public void addAttributeMapping(
083: AttributeMappingDescriptor descriptor) {
084: String attributeName = descriptor.getAttributeName();
085:
086: AttributeMappingDescriptor existing = (AttributeMappingDescriptor) _attributeNameMappingMap
087: .get(attributeName);
088:
089: if (existing != null) {
090: _errorHandler.error(LOG, ParseMessages
091: .dupeAttributeMapping(descriptor, existing),
092: descriptor.getLocation(), null);
093:
094: return;
095: }
096:
097: _attributeNameMappingMap.put(attributeName, descriptor);
098:
099: _attributeMappings.add(descriptor);
100: }
101:
102: /**
103: * @since 1.1
104: */
105: public String getClassName() {
106: return _className;
107: }
108:
109: public void setClassName(String string) {
110: _className = string;
111: }
112:
113: /**
114: * @since 1.1
115: */
116: public String getParentMethodName() {
117: return _parentMethodName;
118: }
119:
120: public void setParentMethodName(String string) {
121: _parentMethodName = string;
122: }
123:
124: /**
125: * @since 1.1
126: */
127: public void begin(SchemaProcessor processor, Element element) {
128: for (Iterator i = _rules.iterator(); i.hasNext();) {
129: Rule rule = (Rule) i.next();
130:
131: rule.begin(processor, element);
132: }
133: }
134:
135: /**
136: * @since 1.1
137: */
138: public void end(SchemaProcessor processor, Element element) {
139: for (ListIterator i = _rules.listIterator(_rules.size()); i
140: .hasPrevious();) {
141: Rule rule = (Rule) i.previous();
142:
143: rule.end(processor, element);
144: }
145: }
146:
147: public void addRulesForModel() {
148: _rules = new ArrayList();
149:
150: _rules.add(new CreateObjectRule(_className));
151:
152: addAttributeRules();
153:
154: _rules.add(new InvokeParentRule(_parentMethodName));
155: }
156:
157: private void addAttributeRules() {
158: Iterator i = _elementModel.getAttributeModels().iterator();
159:
160: while (i.hasNext()) {
161: AttributeModel am = (AttributeModel) i.next();
162: String attributeName = am.getName();
163:
164: AttributeMappingDescriptor amd = (AttributeMappingDescriptor) _attributeNameMappingMap
165: .get(attributeName);
166:
167: if (amd == null) {
168: _rules.add(new ReadAttributeRule(attributeName,
169: constructPropertyName(attributeName), null,
170: getLocation()));
171: } else {
172: String propertyName = amd.getPropertyName();
173: if (propertyName == null)
174: propertyName = constructPropertyName(attributeName);
175:
176: _rules.add(new ReadAttributeRule(attributeName,
177: propertyName, null, amd.getLocation()));
178:
179: _attributeNameMappingMap.remove(attributeName);
180: }
181: }
182:
183: if (!_attributeNameMappingMap.isEmpty())
184: _errorHandler.error(LOG, ParseMessages.extraMappings(
185: _attributeNameMappingMap.keySet(), _elementModel),
186: _elementModel.getLocation(), null);
187: }
188:
189: private String constructPropertyName(String attributeName) {
190: int dashx = attributeName.indexOf('-');
191: if (dashx < 0)
192: return attributeName;
193:
194: int length = attributeName.length();
195: StringBuffer buffer = new StringBuffer(length);
196:
197: buffer.append(attributeName.substring(0, dashx));
198: boolean toUpper = true;
199:
200: for (int i = dashx + 1; i < length; i++) {
201: char ch = attributeName.charAt(i);
202:
203: if (ch == '-') {
204: toUpper = true;
205: continue;
206: }
207:
208: if (toUpper)
209: ch = Character.toUpperCase(ch);
210:
211: buffer.append(ch);
212:
213: toUpper = false;
214: }
215:
216: return buffer.toString();
217: }
218: }
|