1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.properties.admin.resources.representation.html;
17
18 import static de.smartics.properties.admin.domain.model.AppRelations.PROPERTY;
19
20 import java.io.OutputStream;
21 import java.net.URI;
22 import java.util.List;
23
24 import org.apache.commons.lang.ObjectUtils;
25 import org.apache.commons.lang.StringUtils;
26
27 import de.smartics.html5.jatl.HtmlResourceContext;
28 import de.smartics.properties.admin.domain.model.ConfigurationProperty;
29 import de.smartics.properties.admin.domain.model.Paths;
30 import de.smartics.properties.admin.domain.model.Roles;
31 import de.smartics.properties.admin.resources.controller.ApiResource;
32 import de.smartics.properties.admin.resources.controller.PropertyResource;
33 import de.smartics.properties.admin.resources.representation.html.share.AbstractHtmlRepresentationRenderer;
34 import de.smartics.properties.api.config.domain.DescribedProperty;
35 import de.smartics.properties.api.config.domain.ValidatedProperty;
36 import de.smartics.properties.api.config.domain.key.ConfigurationKey;
37 import de.smartics.properties.api.core.domain.PropertyCategories;
38 import de.smartics.properties.api.core.domain.PropertyConstraint;
39 import de.smartics.properties.api.core.domain.PropertyDescriptor;
40 import de.smartics.properties.spi.core.constraints.PropertyRangeConstraint;
41 import de.smartics.resteasy.hypermedia.renderer.LinkDescriptor;
42 import de.smartics.util.lang.StringFunction;
43
44
45
46
47 public final class PropertyHtmlRepresentationRenderer extends
48 AbstractHtmlRepresentationRenderer<ConfigurationProperty>
49 {
50
51
52
53
54
55
56
57
58
59
60 private static final String CSS_CLASS_TABLE =
61 "table table-striped table-bordered";
62
63
64
65
66
67
68 private final ConfigurationProperty domainObject;
69
70
71
72
73
74
75
76
77
78
79
80
81 public PropertyHtmlRepresentationRenderer(
82 final HtmlResourceContext htmlContext,
83 final ConfigurationProperty domainObject, final OutputStream entityStream)
84 {
85 super(htmlContext, entityStream);
86 this.domainObject = domainObject;
87 }
88
89
90
91
92
93
94
95
96
97 @Override
98 protected String getTitle()
99 {
100 final DescribedProperty property = domainObject.getProperty();
101 return property.getName();
102 }
103
104
105
106 @Override
107 protected void bodyContents()
108 {
109 final Object value = domainObject.getPropertyValue();
110
111 final String subTitle = ObjectUtils.toString(value, null);
112 renderPageTitle(subTitle);
113
114 valueInformation();
115 descriptorInformation();
116 }
117
118 private void valueInformation()
119 {
120 final DescribedProperty property = domainObject.getProperty();
121
122 html.h2().text("Value").end();
123 html.table().classAttr(CSS_CLASS_TABLE);
124 html.tr().th().text("type").end().th().text("value").end().end();
125
126 if (property instanceof ValidatedProperty)
127 {
128 final String resolvedValue =
129 ObjectUtils.toString(
130 ((ValidatedProperty) property).getValidatedValue(), null);
131 final String unresolvedValue = property.getValue();
132
133 if (ObjectUtils.equals(unresolvedValue, resolvedValue))
134 {
135 renderValueFormInRow(property.getName(), property);
136 }
137 else if (property.getDescriptor().isSecured())
138 {
139 renderRow("unresolved value", property.getValue());
140 renderValueFormInRow(property.getName(), property);
141 }
142 else
143 {
144 renderRow("resolved value", resolvedValue);
145 renderValueFormInRow("unresolved value", property);
146 }
147 }
148 else
149 {
150 renderValueFormInRow("unresolved value", property);
151 }
152 renderRow("Source Configuration", property.getConfigurationKey());
153
154 html.end();
155 }
156
157 private void descriptorInformation()
158 {
159 final PropertyDescriptor descriptor = domainObject.getDescriptor();
160
161 html.h2().text("Descriptor").end();
162 html.table().classAttr(CSS_CLASS_TABLE);
163 html.tr().th().text("name").end().th().text("value").end().end();
164 renderRow("mandatory", descriptor.isMandatory());
165 renderRow("access type", descriptor.getAccessType());
166 renderRow("use type", descriptor.getUseType().toString());
167 renderRow("categories", toString(descriptor.getCategories()));
168 renderRow("comment", descriptor.getComment());
169 renderRow("configuration time", descriptor.getConfigurationTime());
170 renderRow("update interval", descriptor.getUpdateIntervalInMs());
171 renderRow("default expression", descriptor.getDefaultExpression());
172 renderRow("value type", descriptor.getType());
173 renderRow("value range", descriptor.getValueRange());
174 renderRow("constraints", toString(descriptor.getConstraints()));
175 renderRow("declaring type", descriptor.getDeclaringType().getName());
176 renderRow("home page", descriptor.getContext().getHomePageUrl());
177 final String reportUrl =
178 descriptor.getContext().getPropertiesContext()
179 .createReportUrl(descriptor);
180 renderRow("Report", reportUrl);
181 html.end();
182
183 html.p();
184 final String propertyKey = descriptor.getKey().toString();
185 final String configurationKey = domainObject.getConfigurationKey();
186 final URI url = createUrl(configurationKey, propertyKey);
187 html.a().id("asXml").rel(PROPERTY).href(url.toString())
188 .icon("icon-download-alt").text(" Download as XML").end();
189 html.end();
190 }
191
192 private URI createUrl(final String configurationKey, final String propertyKey)
193 {
194 final URI url =
195 htmlContext.getContext().getUriInfo().getBaseUriBuilder()
196 .path(PropertyResource.class, "getAsDotXml")
197 .build(new Object[] { configurationKey, propertyKey }, false);
198 return url;
199 }
200
201 private String toString(final PropertyCategories categories)
202 {
203 final List<Class<?>> types = categories.getCategories();
204 final StringBuilder buffer = new StringBuilder(64);
205 for (final Class<?> type : types)
206 {
207 buffer.append(type.getName()).append(' ');
208 }
209 return StringFunction.chop(buffer).toString();
210 }
211
212 private Object toString(
213 final List<? extends PropertyConstraint<?>> constraints)
214 {
215 final StringBuilder buffer = new StringBuilder(64);
216
217 for (final Object constraint : constraints)
218 {
219 if (constraint instanceof PropertyRangeConstraint)
220 {
221 continue;
222 }
223 buffer.append(' ').append(constraint);
224 }
225
226 return buffer.toString();
227 }
228
229 private void renderRow(final String label, final Object value)
230 {
231 if (isNotBlank(value))
232 {
233 html.tr();
234 html.td().text(label).end().td().text(String.valueOf(value)).end();
235 html.end();
236 }
237 }
238
239 private void renderValueFormInRow(final String label,
240 final DescribedProperty property)
241 {
242 final String value =
243 (property instanceof ValidatedProperty)
244 && property.getDescriptor().isSecured() ? ObjectUtils
245 .toString(((ValidatedProperty) property).getValidatedValue())
246 : property.getValue();
247
248 if (htmlContext.getContext().isUserInRole(Roles.EDIT_PROPERTY))
249 {
250 html.tr();
251 html.td().text(label).end().td();
252
253 createForm(property, value);
254
255 html.end();
256 html.end();
257 }
258 else
259 {
260 renderRow(label, value);
261 }
262 }
263
264 private void createForm(final DescribedProperty property, final String value)
265 {
266 final PropertyDescriptor descriptor = domainObject.getDescriptor();
267 final boolean disabled = !descriptor.isRuntimeMutable();
268 html.form().classAttr("form-inline").method("POST");
269 if (disabled)
270 {
271 createOverrideButton();
272 }
273 createInputField(property, value, disabled);
274 createSubmitButton(disabled);
275
276 if (property.getDescriptor().isSecured())
277 {
278 final LinkDescriptor link =
279 linkDescriptorFactory.createDescriptor(ApiResource.SECURITY,
280 "getAsHtml");
281 link.setTarget("smartics_properties_security");
282 html.link(link);
283 }
284
285 html.end();
286 }
287
288 private void createOverrideButton()
289 {
290 html.button()
291 .id("override")
292 .type("button")
293 .classAttr("btn btn-mini btn-default")
294 .onclick(
295 "var toggleButton = document.getElementById(\"override\"); "
296 + "document.getElementById(\"submit\").disabled = false; "
297 + "document.getElementById(\"" + Paths.PARAM_VALUE
298 + "\").disabled = false; "
299 + "toggleButton.style.display = 'none';").text("override!")
300 .end();
301 }
302
303 private void createInputField(final DescribedProperty property,
304 final String value, final boolean disabled)
305 {
306 html.input().type("text").id(Paths.PARAM_VALUE).name(Paths.PARAM_VALUE)
307 .classAttr("input-xlarge");
308 addDisabledStatus(disabled);
309 if (isDefinedInThisConfiguration(property))
310 {
311 html.value(value);
312 }
313 else
314 {
315 html.attr("placeholder", value);
316 }
317 html.end();
318 }
319
320 private void createSubmitButton(final boolean disabled)
321 {
322 html.button().type("submit").id("submit")
323 .classAttr("btn btn-mini btn-default");
324 addDisabledStatus(disabled);
325 html.text("update").end();
326 }
327
328 private boolean isDefinedInThisConfiguration(final DescribedProperty property)
329 {
330 final ConfigurationKey<?> key = property.getConfigurationKey();
331 final String keyString = key != null ? key.toString() : null;
332 final boolean isDefined =
333 domainObject.getConfigurationKey().equals(keyString);
334 return isDefined;
335 }
336
337 private void addDisabledStatus(final boolean disabled)
338 {
339 if (disabled)
340 {
341 html.disabled("disabled");
342 }
343 }
344
345 private boolean isNotBlank(final Object value)
346 {
347 if (value == null)
348 {
349 return false;
350 }
351
352 return StringUtils.isNotBlank(String.valueOf(value));
353 }
354
355 @Override
356 protected List<LinkDescriptor> breadcrumbLinks()
357 {
358 return breadcrumb.property(domainObject.getConfigurationKey(),
359 domainObject.getPropertyKey());
360 }
361
362
363
364 }