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