2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
24 package org.openecomp.appc.util;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Properties;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
33 * This class is used to assemble properties that are defined using a structured name into groups, and allow them to be
34 * processed as sets of definitions.
36 * For example, a structured name uses a dotted-notation, like "provider.name". Further, the nodes of the structured
37 * name may be serialized using a suffix ordinal number (e.g., "provider1.name"). These structured properties form a
38 * hierarchical name space where the names are grouped together and can be retrieved as a set.
43 public class StructuredPropertyHelper {
46 * This method scans the properties object for all properties that match the root name and constructs a list of
47 * structured property node graphs that represents the namespaces of the properties.
49 * For example, assume that there are structured properties of the form "provider1.name", "provider2.name",
50 * "provider3.name", and so forth. There may also be other subordinate properties as well (e.g., "provider1.type").
51 * This method would construct a list of graphs of nodes, where each node represents one value of the structured
52 * name. The roots would be the values "provider1", "provider2", "provider3", and so forth. The values of the
53 * subordinate nodes would be the second, third, and so forth name nodes of the compound name. The value of the
54 * property is associated with nodes that are representative of the leaf of the name space.
58 * The properties to be processed
60 * The prefix of the root structured property name
61 * @return The node graph of the properties
63 public static List<Node> getStructuredProperties(Properties properties, String prefix) {
64 List<Node> roots = new ArrayList<>();
66 for (String name : properties.stringPropertyNames()) {
67 if (name.startsWith(prefix)) {
68 String value = properties.getProperty(name);
69 processNamespace(roots, name, value);
77 * This method recursively walks the name space of the structured property and constructs the node graph to
78 * represent the property
81 * The collection of nodes for the current level of the name space
83 * The name of the node
86 * @return The node for this level in the namespace
88 @SuppressWarnings("nls")
89 private static Node processNamespace(List<Node> nodes, String propertyName, String value) {
90 String[] tokens = propertyName.split("\\.", 2);
91 String nodeName = normalizeNodeName(tokens[0]);
93 Node namespaceNode = null;
94 for (Node node : nodes) {
95 if (node.getName().equals(nodeName)) {
100 if (namespaceNode == null) {
101 namespaceNode = new Node();
102 namespaceNode.setName(nodeName);
103 nodes.add(namespaceNode);
106 if (tokens.length == 1 || tokens[1] == null || tokens[1].length() == 0) {
107 namespaceNode.setValue(value);
109 processNamespace(namespaceNode.getChildren(), tokens[1], value);
112 return namespaceNode;
116 * This method normalizes a node name of the structured property name by removing leading and trailing whitespace,
117 * and by converting any ordinal position to a simple expression without leading zeroes.
120 * The token to be normalized
121 * @return The normalized name, or null if the token was null;
123 @SuppressWarnings("nls")
124 private static String normalizeNodeName(String token) {
129 StringBuffer buffer = new StringBuffer(token.trim());
130 Pattern pattern = Pattern.compile("([^0-9]+)([0-9]*)");
131 Matcher matcher = pattern.matcher(buffer);
132 if (matcher.matches()) {
133 String nameRoot = matcher.group(1);
134 String ordinal = matcher.group(2);
135 if (ordinal != null && ordinal.length() > 0) {
136 int i = Integer.parseInt(ordinal);
138 buffer.append(nameRoot);
139 buffer.append(Integer.toString(i));
142 return buffer.toString();
146 * This class represents a node in the structured property name space
149 public static class Node implements Comparable<Node> {
152 * The name of the structured property node
157 * If the node is a leaf, then the value of the property
159 private String value;
162 * If the node is not a leaf, then the sub-nodes of the property
164 private List<Node> children;
167 * @return the value of name
169 public String getName() {
177 public void setName(String name) {
182 * @return the value of value
184 public String getValue() {
190 * the value for value
192 public void setValue(String value) {
197 * @return the value of children
199 public List<Node> getChildren() {
200 if (children == null) {
201 children = new ArrayList<>();
207 * @see java.lang.Object#hashCode()
210 public int hashCode() {
211 return name.hashCode() + (value != null ? value.hashCode() : children.hashCode());
215 * @see java.lang.Object#equals(java.lang.Object)
218 public boolean equals(Object obj) {
219 Node other = (Node) obj;
220 boolean result = name.equals(other.name);
223 result &= other.value == null;
225 result &= value.equals(other.value);
227 if (children == null) {
228 result &= other.children == null;
230 result &= children.equals(other.children);
236 * @see java.lang.Object#toString()
238 @SuppressWarnings("nls")
240 public String toString() {
242 return String.format("%s = %s", name, value);
244 return String.format("%s.%s", name, children.toString());
248 public int compareTo(StructuredPropertyHelper.Node o) {
249 return name.compareTo(o.name);