1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.datadictionary.parse;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.hsqldb.lib.StringUtil;
21 import org.springframework.beans.factory.config.BeanDefinition;
22 import org.springframework.beans.factory.config.BeanDefinitionHolder;
23 import org.springframework.beans.factory.config.RuntimeBeanReference;
24 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
25 import org.springframework.beans.factory.support.ManagedList;
26 import org.springframework.beans.factory.support.ManagedMap;
27 import org.springframework.beans.factory.support.ManagedSet;
28 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
29 import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
30 import org.springframework.beans.factory.xml.ParserContext;
31 import org.springframework.util.xml.DomUtils;
32 import org.w3c.dom.Element;
33 import org.w3c.dom.NamedNodeMap;
34
35 import java.util.ArrayList;
36 import java.util.Map;
37
38
39
40
41
42
43 public class CustomSchemaParser extends AbstractSingleBeanDefinitionParser {
44 private static final Log LOG = LogFactory.getLog(CustomSchemaParser.class);
45
46 private static int beanNumber = 0;
47
48
49
50
51
52
53
54 protected Class getBeanClass(Element bean) {
55 Map<String, BeanTagInfo> beanType = null;
56
57
58 try {
59 beanType = CustomTagAnnotations.getBeanTags();
60 } catch (Exception e) {
61 LOG.error("Error retrieving bean tag information", e);
62 }
63
64 Class<?> beanTag = null;
65 try {
66
67
68 beanTag = beanType.get(bean.getLocalName()).getBeanClass();
69 } catch (Exception e) {
70 LOG.error("Error in retrieved bean tag information", e);
71 }
72
73 return beanTag;
74 }
75
76
77
78
79
80
81
82
83
84 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder bean) {
85
86 Map<String, Map<String, BeanTagAttributeInfo>> attributeProperties =
87 CustomTagAnnotations.getAttributeProperties();
88 Map<String, BeanTagAttributeInfo> entries = attributeProperties.get(element.getLocalName());
89
90
91 if (entries == null) {
92 LOG.error("Bean Tag not found " + element.getLocalName());
93 }
94
95
96 BeanTagInfo tagInfo = CustomTagAnnotations.getBeanTags().get(element.getLocalName());
97 if (tagInfo.getParent().compareTo("none") != 0) {
98 bean.setParentName(tagInfo.getParent());
99 }
100
101
102 NamedNodeMap attributes = element.getAttributes();
103 for (int i = 0; i < attributes.getLength(); i++) {
104 processSingleValue(attributes.item(i).getNodeName(), attributes.item(i).getNodeValue(), entries, bean);
105 }
106
107 ArrayList<Element> children = (ArrayList<Element>) DomUtils.getChildElements(element);
108
109
110 for (int i = 0; i < children.size(); i++) {
111 String tag = children.get(i).getLocalName();
112 BeanTagAttributeInfo info = entries.get(tag);
113
114 String propertyName;
115 BeanTagAttribute.AttributeType type;
116
117
118 if (info == null) {
119
120
121 propertyName = tag;
122 type = findBeanType(children.get(i));
123 } else {
124
125 propertyName = info.getName();
126 type = info.getType();
127 }
128
129 ArrayList<Element> grandChildren = (ArrayList<Element>) DomUtils.getChildElements(children.get(i));
130
131 if (type == BeanTagAttribute.AttributeType.SINGLEBEAN) {
132 bean.addPropertyValue(propertyName, parseBean(grandChildren.get(0), bean, parserContext));
133 } else if (type == BeanTagAttribute.AttributeType.LISTBEAN) {
134 bean.addPropertyValue(propertyName, parseList(grandChildren, children.get(i), bean, parserContext));
135 } else if (type == BeanTagAttribute.AttributeType.LISTVALUE) {
136 bean.addPropertyValue(propertyName, parseList(grandChildren, children.get(i), bean, parserContext));
137 } else if (type == BeanTagAttribute.AttributeType.MAPVALUE) {
138 bean.addPropertyValue(propertyName, parseMap(grandChildren, children.get(i), bean, parserContext));
139 } else if (type == BeanTagAttribute.AttributeType.MAPBEAN) {
140 bean.addPropertyValue(propertyName, parseMap(grandChildren, children.get(i), bean, parserContext));
141 } else if (type == BeanTagAttribute.AttributeType.SETVALUE) {
142 bean.addPropertyValue(propertyName, parseSet(grandChildren, children.get(i), bean, parserContext));
143 } else if (type == BeanTagAttribute.AttributeType.SETBEAN) {
144 bean.addPropertyValue(propertyName, parseSet(grandChildren, children.get(i), bean, parserContext));
145 }
146 }
147 return;
148 }
149
150
151
152
153
154
155
156
157
158 private void processSingleValue(String name, String value, Map<String, BeanTagAttributeInfo> entries,
159 BeanDefinitionBuilder bean) {
160
161 if (name.toLowerCase().compareTo("parent") == 0) {
162
163 bean.setParentName(value);
164 } else if (name.toLowerCase().compareTo("abstract") == 0) {
165
166 bean.setAbstract(Boolean.valueOf(value));
167 } else if (name.toLowerCase().compareTo("id") == 0) {
168 if (value.contains("Demo-CollectionGrouping-Section1")) {
169 System.out.println();
170 }
171
172
173 } else {
174
175
176
177 if (name.contains("-ref")) {
178 bean.addPropertyValue(name.substring(0, name.length() - 4), new RuntimeBeanReference(value));
179 } else {
180 BeanTagAttributeInfo info = entries.get(name);
181 String propertyName;
182
183 if (info == null) {
184 propertyName = name;
185 } else {
186 propertyName = info.getName();
187 }
188 bean.addPropertyValue(propertyName, value);
189 }
190 }
191 }
192
193
194
195
196
197
198
199 private Object findKey(Element grandchild) {
200 String key = grandchild.getAttribute("key");
201 if (!key.isEmpty()) {
202 return key;
203 } else {
204 Element keyTag = DomUtils.getChildElementByTagName(grandchild, "key");
205 if (DomUtils.getChildElements(keyTag).size() == 0) {
206 return keyTag.getTextContent();
207 } else {
208 return DomUtils.getChildElements(keyTag).get(0);
209 }
210 }
211
212 }
213
214
215
216
217
218
219
220 private Object findValue(Element grandchild) {
221 String value = grandchild.getAttribute("value");
222 if (!value.isEmpty()) {
223 return value;
224 } else {
225 Element valueTag = DomUtils.getChildElementByTagName(grandchild, "value");
226 if (DomUtils.getChildElements(valueTag).size() == 0) {
227 return valueTag.getTextContent();
228 } else {
229 return DomUtils.getChildElements(valueTag).get(0);
230 }
231 }
232
233 }
234
235
236
237
238
239
240
241 private BeanTagAttribute.AttributeType findBeanType(Element tag) {
242 int numberChildren = 0;
243
244
245 String overrideType = tag.getAttribute("overrideBeanType");
246 if (!StringUtil.isEmpty(overrideType)) {
247 if (overrideType.toLowerCase().compareTo("singlebean") == 0) {
248 return BeanTagAttribute.AttributeType.SINGLEBEAN;
249 }
250 if (overrideType.toLowerCase().compareTo("singlevalue") == 0) {
251 return BeanTagAttribute.AttributeType.SINGLEVALUE;
252 }
253 if (overrideType.toLowerCase().compareTo("listbean") == 0) {
254 return BeanTagAttribute.AttributeType.LISTBEAN;
255 }
256 if (overrideType.toLowerCase().compareTo("listvalue") == 0) {
257 return BeanTagAttribute.AttributeType.LISTVALUE;
258 }
259 if (overrideType.toLowerCase().compareTo("mapbean") == 0) {
260 return BeanTagAttribute.AttributeType.MAPBEAN;
261 }
262 if (overrideType.toLowerCase().compareTo("mapvalue") == 0) {
263 return BeanTagAttribute.AttributeType.MAPVALUE;
264 }
265 if (overrideType.toLowerCase().compareTo("setbean") == 0) {
266 return BeanTagAttribute.AttributeType.SETBEAN;
267 }
268 if (overrideType.toLowerCase().compareTo("setvalue") == 0) {
269 return BeanTagAttribute.AttributeType.SETVALUE;
270 }
271 }
272
273
274 numberChildren = DomUtils.getChildElementsByTagName(tag, "value").size();
275 if (numberChildren > 0) {
276 return BeanTagAttribute.AttributeType.LISTVALUE;
277 }
278
279
280 numberChildren = DomUtils.getChildElementsByTagName(tag, "entry").size();
281 if (numberChildren > 0) {
282 return BeanTagAttribute.AttributeType.MAPVALUE;
283 }
284
285
286 numberChildren = DomUtils.getChildElements(tag).size();
287 if (numberChildren > 1) {
288 return BeanTagAttribute.AttributeType.LISTBEAN;
289 }
290
291
292 return BeanTagAttribute.AttributeType.SINGLEBEAN;
293 }
294
295
296
297
298
299
300
301
302
303 private Object parseBean(Element tag, BeanDefinitionBuilder parent, ParserContext parserContext) {
304 if (tag.getNamespaceURI().compareTo("http://www.springframework.org/schema/beans") == 0) {
305 return parseSpringBean(tag, parserContext);
306 } else {
307 return parseCustomBean(tag, parent, parserContext);
308 }
309 }
310
311
312
313
314
315
316
317 private Object parseSpringBean(Element tag, ParserContext parserContext) {
318 if (tag.getLocalName().compareTo("ref") == 0) {
319
320
321 Element temp = tag.getOwnerDocument().createElement("bean");
322 temp.setAttribute("parent", tag.getAttribute("bean"));
323 tag = temp;
324 return new RuntimeBeanReference(tag.getAttribute("bean"));
325 }
326
327 BeanDefinitionParserDelegate delegate = parserContext.getDelegate();
328 BeanDefinitionHolder bean = delegate.parseBeanDefinitionElement(tag);
329
330
331 String name = bean.getBeanDefinition().getParentName() + "$Customchild" + beanNumber;
332 if (tag.getAttribute("id") != null && !StringUtil.isEmpty(tag.getAttribute("id"))) {
333 name = tag.getAttribute("id");
334 } else {
335 beanNumber++;
336 }
337
338 return new BeanDefinitionHolder(bean.getBeanDefinition(), name);
339 }
340
341
342
343
344
345
346
347
348
349 private Object parseCustomBean(Element tag, BeanDefinitionBuilder parent, ParserContext parserContext) {
350 BeanDefinitionHolder bean;
351 if (tag.getLocalName().compareTo("ref") == 0) {
352 return new RuntimeBeanReference(tag.getAttribute("bean"));
353
354 } else {
355 BeanDefinition beanDefinition = parserContext.getDelegate().parseCustomElement(tag,
356 parent.getBeanDefinition());
357
358 String name = beanDefinition.getParentName() + "$Customchild" + beanNumber;
359 if (tag.getAttribute("id") != null && !StringUtil.isEmpty(tag.getAttribute("id"))) {
360 name = tag.getAttribute("id");
361 } else {
362 beanNumber++;
363 }
364 bean = new BeanDefinitionHolder(beanDefinition, name);
365 }
366
367 return bean;
368 }
369
370
371
372
373
374
375
376
377
378
379 private ManagedList parseList(ArrayList<Element> grandChildren, Element child, BeanDefinitionBuilder parent,
380 ParserContext parserContext) {
381 ArrayList<Object> listItems = new ArrayList<Object>();
382
383 for (int i = 0; i < grandChildren.size(); i++) {
384 Element grandChild = grandChildren.get(i);
385
386 if (grandChild.getTagName().compareTo("value") == 0) {
387 listItems.add(grandChild.getTextContent());
388 } else {
389 listItems.add(parseBean(grandChild, parent, parserContext));
390 }
391 }
392
393 String merge = child.getAttribute("merge");
394
395 ManagedList beans = new ManagedList(listItems.size());
396
397 if (merge != null) {
398 beans.setMergeEnabled(Boolean.valueOf(merge));
399 }
400
401 beans.addAll(listItems);
402 return beans;
403 }
404
405
406
407
408
409
410
411
412
413
414 private ManagedSet parseSet(ArrayList<Element> grandChildren, Element child, BeanDefinitionBuilder parent,
415 ParserContext parserContext) {
416 ManagedSet setItems = new ManagedSet();
417
418 for (int i = 0; i < grandChildren.size(); i++) {
419 Element grandChild = grandChildren.get(i);
420
421 if (child.getTagName().compareTo("value") == 0) {
422 setItems.add(grandChild.getTextContent());
423 } else {
424 setItems.add(parseBean(grandChild, parent, parserContext));
425 }
426 }
427
428 String merge = child.getAttribute("merge");
429 if (merge != null) {
430 setItems.setMergeEnabled(Boolean.valueOf(merge));
431 }
432
433 return setItems;
434 }
435
436
437
438
439
440
441
442
443
444
445 private ManagedMap parseMap(ArrayList<Element> grandChildren, Element child, BeanDefinitionBuilder parent,
446 ParserContext parserContext) {
447 ManagedMap map = new ManagedMap();
448
449 for (int j = 0; j < grandChildren.size(); j++) {
450 Object key = findKey(grandChildren.get(j));
451 Object value = findValue(grandChildren.get(j));
452 map.put(key, value);
453 }
454
455 String merge = child.getAttribute("merge");
456 if (merge != null) {
457 map.setMergeEnabled(Boolean.valueOf(merge));
458 }
459
460 return map;
461 }
462 }