1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package com.rapiddweller.benerator.engine.parser.xml;
28
29 import com.rapiddweller.benerator.engine.BeneratorContext;
30 import com.rapiddweller.benerator.engine.BeneratorRootStatement;
31 import com.rapiddweller.benerator.engine.ResourceManager;
32 import com.rapiddweller.benerator.engine.Statement;
33 import com.rapiddweller.benerator.engine.statement.BeanStatement;
34 import com.rapiddweller.benerator.engine.statement.IfStatement;
35 import com.rapiddweller.common.CollectionUtil;
36 import com.rapiddweller.common.ConfigurationError;
37 import com.rapiddweller.common.ConversionException;
38 import com.rapiddweller.common.ParseException;
39 import com.rapiddweller.common.StringUtil;
40 import com.rapiddweller.common.xml.XMLUtil;
41 import com.rapiddweller.script.Assignment;
42 import com.rapiddweller.script.BeanSpec;
43 import com.rapiddweller.script.DatabeneScriptParser;
44 import com.rapiddweller.script.Expression;
45 import com.rapiddweller.script.expression.BeanConstruction;
46 import com.rapiddweller.script.expression.DefaultConstruction;
47 import com.rapiddweller.script.expression.ExpressionUtil;
48 import org.apache.logging.log4j.LogManager;
49 import org.apache.logging.log4j.Logger;
50 import org.w3c.dom.Element;
51
52 import static com.rapiddweller.benerator.engine.DescriptorConstants.ATT_CLASS;
53 import static com.rapiddweller.benerator.engine.DescriptorConstants.ATT_ID;
54 import static com.rapiddweller.benerator.engine.DescriptorConstants.ATT_SPEC;
55 import static com.rapiddweller.benerator.engine.DescriptorConstants.EL_BEAN;
56 import static com.rapiddweller.benerator.engine.DescriptorConstants.EL_PROPERTY;
57
58
59
60
61
62
63
64
65 public class BeanParser extends AbstractBeneratorDescriptorParser {
66
67 private static final Logger logger = LogManager.getLogger(BeanParser.class);
68
69
70
71
72 public BeanParser() {
73
74 super(EL_BEAN, CollectionUtil.toSet(ATT_ID), CollectionUtil.toSet(ATT_CLASS, ATT_SPEC),
75 BeneratorRootStatement.class, IfStatement.class);
76 }
77
78
79
80
81
82
83
84 @SuppressWarnings({"unchecked", "rawtypes"})
85 public static Expression<?> parseBeanExpression(Element element) {
86 String id = element.getAttribute(ATT_ID);
87 Expression<?> instantiation = null;
88 String beanSpec = element.getAttribute(ATT_SPEC);
89 String beanClass = element.getAttribute(ATT_CLASS);
90 if (!StringUtil.isEmpty(beanSpec)) {
91 try {
92 instantiation = DatabeneScriptParser.parseBeanSpec(beanSpec);
93 } catch (ParseException e) {
94 throw new ConfigurationError("Error parsing bean spec: " + beanSpec, e);
95 }
96 } else if (!StringUtil.isEmpty(beanClass)) {
97 logger.debug("Instantiating bean of class " + beanClass + " (id=" + id + ")");
98 instantiation = new DefaultConstruction(beanClass);
99 } else {
100 syntaxError("bean definition is missing 'class' or 'spec' attribute", element);
101 }
102 Element[] propertyElements = XMLUtil.getChildElements(element, false, EL_PROPERTY);
103 Assignment[] propertyInitializers = mapPropertyDefinitions(propertyElements);
104 return new BeanConstruction(instantiation, propertyInitializers);
105 }
106
107
108
109
110
111
112
113
114 @SuppressWarnings({"unchecked", "rawtypes"})
115 public static BeanSpec resolveBeanExpression(Element element, BeneratorContext context) {
116 String id = element.getAttribute(ATT_ID);
117 Expression<?> instantiation;
118 String beanSpecString = element.getAttribute(ATT_SPEC);
119 String beanClass = element.getAttribute(ATT_CLASS);
120 boolean ref = false;
121 if (!StringUtil.isEmpty(beanSpecString)) {
122 try {
123 BeanSpec spec = DatabeneScriptParser.resolveBeanSpec(beanSpecString, context);
124 instantiation = ExpressionUtil.constant(spec.getBean());
125 ref = spec.isReference();
126 } catch (ParseException e) {
127 throw new ConfigurationError("Error parsing bean spec: " + beanSpecString, e);
128 }
129 } else if (!StringUtil.isEmpty(beanClass)) {
130 logger.debug("Instantiating bean of class " + beanClass + " (id=" + id + ")");
131 instantiation = new DefaultConstruction<>(beanClass);
132 } else {
133 throw new ConfigurationError("Syntax error in definition of bean " + id);
134 }
135 Element[] propertyElements = XMLUtil.getChildElements(element);
136 for (Element propertyElement : propertyElements) {
137 if (!EL_PROPERTY.equals(propertyElement.getNodeName())) {
138 syntaxError("not a supported bean child element: <" + propertyElement.getNodeName() + ">",
139 propertyElement);
140 }
141 }
142 Assignment[] propertyInitializers = mapPropertyDefinitions(propertyElements);
143 Object result = new BeanConstruction(instantiation, propertyInitializers).evaluate(context);
144 return new BeanSpec(result, ref);
145 }
146
147
148
149
150
151
152
153 public static Assignment[] mapPropertyDefinitions(Element[] propertyElements) {
154 Assignment[] assignments = new Assignment[propertyElements.length];
155 for (int i = 0; i < propertyElements.length; i++) {
156 assignments[i] = parseProperty(propertyElements[i]);
157 }
158 return assignments;
159 }
160
161 private static Assignment parseProperty(Element propertyElement) {
162 String propertyName = propertyElement.getAttribute("name");
163 Expression<?> value = SettingParser.parseValue(propertyElement);
164 return new Assignment(propertyName, value);
165 }
166
167 @Override
168 public BeanStatement doParse(Element element, Statement[] parentPath, BeneratorParseContext context) {
169 try {
170 String id = element.getAttribute(ATT_ID);
171 ResourceManager resourceManager = context.getResourceManager();
172 Expression<?> bean = parseBeanExpression(element);
173 return new BeanStatement(id, bean, resourceManager);
174 } catch (ConversionException e) {
175 throw new ConfigurationError(e);
176 }
177 }
178
179 }