1 /*
2 * Copyright 2013 smartics, Kronseder & Reiner GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package de.smartics.properties.jboss.extension.resources.util;
17
18 import java.util.LinkedHashMap;
19 import java.util.Locale;
20 import java.util.Map;
21 import java.util.ResourceBundle;
22
23 import javax.xml.stream.XMLStreamException;
24 import javax.xml.stream.XMLStreamWriter;
25
26 import org.jboss.as.controller.MapAttributeDefinition;
27 import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
28 import org.jboss.as.controller.descriptions.ResourceDescriptionResolver;
29 import org.jboss.as.controller.operations.validation.ModelTypeValidator;
30 import org.jboss.as.controller.operations.validation.ParameterValidator;
31 import org.jboss.dmr.ModelNode;
32 import org.jboss.dmr.ModelType;
33 import org.jboss.dmr.Property;
34
35 /**
36 * A map of simple map values.
37 */
38 public final class SimpleMapAttributeDefinition extends MapAttributeDefinition
39 {
40 // ********************************* Fields *********************************
41
42 // --- constants ------------------------------------------------------------
43
44 // --- members --------------------------------------------------------------
45
46 /**
47 * The name of the XML element that encloses the items named by
48 * {@link #xmlName}.
49 */
50 private final String wrapperXmlName;
51
52 /**
53 * The name of the XML attribute that references the type name.
54 */
55 private final String xmlAttributeName;
56
57 // ****************************** Initializer *******************************
58
59 // ****************************** Constructors ******************************
60
61 /**
62 * Default constructor.
63 *
64 * @param wrapperXmlName the name of the XML element that encloses the items
65 * named by {@link #xmlName}.
66 * @param name the name of the map attribute.
67 * @param xmlName the name of the XML element.
68 * @param xmlAttributeName the name of the XML attribute that references the
69 * type name.
70 * @param allowNull the flag to mark the attribute containing the tuples as
71 * optional ( <code>true</code>) or mandatory (<code>false</code>).
72 * @param elementValidator the validator of the tuple values.
73 */
74 private SimpleMapAttributeDefinition(final String wrapperXmlName,
75 final String name, final String xmlName, final String xmlAttributeName,
76 final boolean allowNull, final ParameterValidator elementValidator)
77 {
78 super(name, xmlName, allowNull, 0, Integer.MAX_VALUE, elementValidator,
79 null, null);
80 this.wrapperXmlName = wrapperXmlName;
81 this.xmlAttributeName = xmlAttributeName;
82 }
83
84 // ****************************** Inner Classes *****************************
85
86 /**
87 * Builds instances of {@link SimpleMapAttributeDefinition}.
88 */
89 public static final class Builder
90 {
91 // ******************************** Fields ********************************
92
93 // --- constants ----------------------------------------------------------
94
95 // --- members ------------------------------------------------------------
96
97 /**
98 * The name of the XML element that encloses the items named by
99 * {@link #xmlName}.
100 */
101 private String wrapperXmlName;
102
103 /**
104 * The name of the map attribute.
105 */
106 private String name;
107
108 /**
109 * The name of the XML element where the attribute is the key and the
110 * contents is the value.
111 */
112 private String xmlName;
113
114 /**
115 * The name of the XML attribute that references the type name.
116 */
117 private String xmlAttributeName;
118
119 /**
120 * The type of the value.
121 */
122 private ModelType type;
123
124 /**
125 * The flag to mark the attribute containing the tuples as optional (
126 * <code>true</code>) or mandatory (<code>false</code>).
127 */
128 private boolean allowNull;
129
130 /**
131 * Flag to mark the value being allowed to contain expressions.
132 */
133 private boolean allowExpression;
134
135 /**
136 * The validator for values.
137 */
138 private ParameterValidator validator;
139
140 // ***************************** Initializer ******************************
141
142 // ***************************** Constructors *****************************
143
144 /**
145 * Default constructor.
146 */
147 public Builder()
148 {
149 }
150
151 // ***************************** Inner Classes ****************************
152
153 // ******************************** Methods *******************************
154
155 // --- init ---------------------------------------------------------------
156
157 // --- get&set ------------------------------------------------------------
158
159 /**
160 * Sets the name of the XML element that encloses the items named by
161 * {@link #setXmlName() xmlName}.
162 *
163 * @param wrapperXmlName the name of the XML element that encloses the items
164 * named by {@link #setXmlName() xmlName}.
165 * @return a reference to this builder.
166 */
167 public Builder withWrapperXmlName(final String wrapperXmlName)
168 {
169 this.wrapperXmlName = wrapperXmlName;
170 return this;
171 }
172
173 /**
174 * Sets the name of the map attribute.
175 *
176 * @param name the name of the attribute.
177 * @return a reference to this builder.
178 */
179 public Builder withName(final String name)
180 {
181 this.name = name;
182 return this;
183 }
184
185 /**
186 * Sets the name of the XML element where the attribute is the key and the
187 * contents is the value.
188 *
189 * @param xmlName the name of the XML element where the attribute is the key
190 * and the contents is the value.
191 * @return a reference to this builder.
192 */
193 public Builder withXmlName(final String xmlName)
194 {
195 this.xmlName = xmlName;
196 return this;
197 }
198
199 /**
200 * Sets the name of the XML attribute that references the type name.
201 *
202 * @param xmlAttributeName the name of the XML attribute that references the
203 * type name.
204 * @return a reference to this builder.
205 */
206 public Builder withXmlAttributeName(final String xmlAttributeName)
207 {
208 this.xmlAttributeName = xmlAttributeName;
209 return this;
210 }
211
212 /**
213 * Sets the type of the value.
214 *
215 * @param type the type of the value.
216 * @return a reference to this builder.
217 */
218 public Builder withType(final ModelType type)
219 {
220 this.type = type;
221 return this;
222 }
223
224 /**
225 * Sets the flag to mark the attribute containing the tuples as optional (
226 * <code>true</code>) or mandatory (<code>false</code>).
227 *
228 * @param allowNull the flag to mark the attribute containing the tuples as
229 * optional ( <code>true</code>) or mandatory (<code>false</code>).
230 * @return a reference to this builder.
231 */
232 public Builder withAllowNull(final boolean allowNull)
233 {
234 this.allowNull = allowNull;
235 return this;
236 }
237
238 /**
239 * Sets the value for allowExpression.
240 * <p>
241 * Flag to mark the value being allowed to contain expressions.
242 *
243 * @param allowExpression the value for allowExpression.
244 * @return a reference to this builder.
245 */
246 public Builder withAllowExpression(final boolean allowExpression)
247 {
248 this.allowExpression = allowExpression;
249 return this;
250 }
251
252 /**
253 * Sets the validator for values.
254 *
255 * @param validator the validator for values.
256 * @return a reference to this builder.
257 */
258 public Builder withValidator(final ParameterValidator validator)
259 {
260 this.validator = validator;
261 return this;
262 }
263
264 // --- business -----------------------------------------------------------
265
266 /**
267 * Creates the instance.
268 *
269 * @return the instance.
270 */
271 public SimpleMapAttributeDefinition build()
272 {
273 if (type == null)
274 {
275 type = ModelType.STRING;
276 }
277 if (xmlAttributeName == null)
278 {
279 xmlAttributeName = "type";
280 }
281
282 if (validator == null)
283 {
284 validator = new ModelTypeValidator(type, allowNull, allowExpression);
285 }
286
287 return new SimpleMapAttributeDefinition(wrapperXmlName, name, xmlName,
288 xmlAttributeName, allowNull, validator);
289 }
290
291 // --- object basics ------------------------------------------------------
292 }
293
294 // ********************************* Methods ********************************
295
296 // --- init -----------------------------------------------------------------
297
298 // --- get&set --------------------------------------------------------------
299
300 /**
301 * Returns the name of the XML element that encloses the items named by
302 * {@link #getXmlName() xmlName}.
303 *
304 * @return the name of the XML element that encloses the items named by
305 * {@link #getXmlName() xmlName}.
306 */
307 public String getWrapperXmlName()
308 {
309 return wrapperXmlName;
310 }
311
312 /**
313 * Returns the name of the XML attribute that references the type name.
314 *
315 * @return the name of the XML attribute that references the type name.
316 */
317 public String getXmlAttributeName()
318 {
319 return xmlAttributeName;
320 }
321
322 // --- business -------------------------------------------------------------
323
324 @Override
325 protected void addValueTypeDescription(final ModelNode node,
326 final ResourceBundle bundle)
327 {
328 setValueType(node);
329 }
330
331 @Override
332 protected void addAttributeValueTypeDescription(final ModelNode result,
333 final ResourceDescriptionResolver resolver, final Locale locale,
334 final ResourceBundle bundle)
335 {
336 setValueType(result);
337 }
338
339 @Override
340 protected void addOperationParameterValueTypeDescription(
341 final ModelNode result, final String operationName,
342 final ResourceDescriptionResolver resolver, final Locale locale,
343 final ResourceBundle bundle)
344 {
345 setValueType(result);
346 }
347
348 void setValueType(final ModelNode node)
349 {
350 node.get(ModelDescriptionConstants.VALUE_TYPE).set(ModelType.STRING);
351 if (isAllowExpression())
352 {
353 node.get(ModelDescriptionConstants.EXPRESSIONS_ALLOWED).set(
354 new ModelNode(true));
355 }
356 }
357
358 @Override
359 public void marshallAsElement(final ModelNode resourceModel,
360 final XMLStreamWriter writer) throws XMLStreamException
361 {
362 final String modelName = getName();
363 final ModelNode mapModel = resourceModel.get(modelName);
364 writer.writeStartElement(wrapperXmlName == null ? modelName
365 : wrapperXmlName);
366
367 for (final ModelNode listNode : mapModel.asList())
368 {
369 final Property property = listNode.asProperty();
370 writer.writeStartElement(getXmlName());
371 writer.writeAttribute(xmlAttributeName, property.getName());
372 writer.writeCharacters(property.getValue().asString());
373 writer.writeEndElement();
374 }
375
376 writer.writeEndElement();
377 }
378
379 public Map<String, String> toStringMap(final ModelNode resourceModel)
380 {
381 final Map<String, String> map = new LinkedHashMap<String, String>();
382
383 final String modelName = getName();
384 final ModelNode mapModel = resourceModel.get(modelName);
385 if (mapModel.isDefined())
386 {
387 for (final ModelNode listNode : mapModel.asList())
388 {
389 final Property property = listNode.asProperty();
390 final String key = property.getName();
391 final String value = property.getValue().asString();
392 map.put(key, value);
393 }
394 }
395
396 return map;
397 }
398
399 // --- object basics --------------------------------------------------------
400
401 }