View Javadoc
1   /*-
2    * #%L
3    * io.earcam.instrumental.module.osgi
4    * %%
5    * Copyright (C) 2018 earcam
6    * %%
7    * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
8    * 
9    * You <b>must</b> choose to accept, in full - any individual or combination of 
10   * the following licenses:
11   * <ul>
12   * 	<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
13   * 	<li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
14   * 	<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
15   * 	<li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
16   * </ul>
17   * #L%
18   */
19  package io.earcam.instrumental.module.osgi;
20  
21  import static io.earcam.instrumental.module.osgi.OsgiAttributeConstants.VERSION_ATTRIBUTE;
22  import static java.util.Collections.emptyMap;
23  
24  import java.io.IOException;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.Map;
28  import java.util.Map.Entry;
29  import java.util.Objects;
30  
31  import io.earcam.instrumental.fluent.Fluent;
32  import io.earcam.unexceptional.Exceptional;
33  
34  /**
35   * <p>
36   * ClauseParameters class.
37   * </p>
38   *
39   * @see ClauseParameter for construction
40   */
41  public final class ClauseParameters {
42  
43  	public static final class ClauseParameter {
44  
45  		private ClauseParameter()
46  		{}
47  
48  
49  		@Fluent
50  		public static ClauseParameters directive(String key, String value)
51  		{
52  			ClauseParameters parameters = new ClauseParameters();
53  			parameters.directive(key, value);
54  			return parameters;
55  		}
56  
57  
58  		@Fluent
59  		public static ClauseParameters attribute(String key, String value)
60  		{
61  			ClauseParameters parameters = new ClauseParameters();
62  			parameters.attribute(key, value);
63  			return parameters;
64  		}
65  
66  
67  		@Fluent
68  		public static ClauseParameters version(int major, int minor, int micro)
69  		{
70  			ClauseParameters parameters = new ClauseParameters();
71  			parameters.attribute(VERSION_ATTRIBUTE.value, major + "." + minor + "." + micro);
72  			return parameters;
73  		}
74  	}
75  
76  	/**
77  	 * Empty parameters, immutably so
78  	 */
79  	public static final ClauseParameters EMPTY_PARAMETERS = new ClauseParameters(emptyMap(), emptyMap());
80  
81  	private final Map<String, String> attributes;
82  	private final Map<String, String> directives;
83  
84  
85  	/**
86  	 * <p>
87  	 * Constructor for ClauseParameters.
88  	 * </p>
89  	 */
90  	public ClauseParameters()
91  	{
92  		this(new HashMap<>(), new HashMap<>());
93  	}
94  
95  
96  	/**
97  	 * <p>
98  	 * Constructor for ClauseParameters.
99  	 * </p>
100 	 *
101 	 * @param attributes a {@link java.util.Map} object.
102 	 * @param directives a {@link java.util.Map} object.
103 	 * @see ClauseParameter#attribute(String, String)
104 	 * @see ClauseParameter#directive(String, String)
105 	 * @see ClauseParameter#attribute(String, String)
106 	 * @see ClauseParameter#directive(String, String)
107 	 */
108 	public ClauseParameters(Map<String, String> attributes, Map<String, String> directives)
109 	{
110 		this.attributes = attributes;
111 		this.directives = directives;
112 	}
113 
114 
115 	@Override
116 	public String toString()
117 	{
118 		return Exceptional.apply(this::appendTo, new StringBuilder()).toString();
119 	}
120 
121 
122 	@Override
123 	public boolean equals(Object other)
124 	{
125 		return other instanceof ClauseParameters && equals((ClauseParameters) other);
126 	}
127 
128 
129 	/**
130 	 * <p>
131 	 * equals.
132 	 * </p>
133 	 *
134 	 * @param that a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
135 	 * @return a boolean.
136 	 */
137 	public boolean equals(ClauseParameters that)
138 	{
139 		return that != null
140 				&& that.attributes.equals(this.attributes)
141 				&& that.directives.equals(this.directives);
142 	}
143 
144 
145 	@Override
146 	public int hashCode()
147 	{
148 		return Objects.hash(attributes, directives);
149 	}
150 
151 
152 	/**
153 	 * <p>
154 	 * isEmpty.
155 	 * </p>
156 	 *
157 	 * @return a boolean.
158 	 */
159 	public boolean isEmpty()
160 	{
161 		return attributes().isEmpty()
162 				&& directives().isEmpty();
163 	}
164 
165 
166 	/**
167 	 * <p>
168 	 * directives.
169 	 * </p>
170 	 *
171 	 * @return a {@link java.util.Map} object.
172 	 */
173 	public Map<String, String> directives()
174 	{
175 		return directives;
176 	}
177 
178 
179 	/**
180 	 * <p>
181 	 * directive.
182 	 * </p>
183 	 *
184 	 * @param key a {@link java.lang.String} object.
185 	 * @param value a {@link java.lang.String} object.
186 	 * @return a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
187 	 */
188 	public ClauseParameters directive(String key, String value)
189 	{
190 		directives.put(key, value);
191 		return this;
192 	}
193 
194 
195 	/**
196 	 * <p>
197 	 * attributes.
198 	 * </p>
199 	 *
200 	 * @return a modifiable {@link Map}.
201 	 */
202 	public Map<String, String> attributes()
203 	{
204 		return attributes;
205 	}
206 
207 
208 	/**
209 	 * <p>
210 	 * attribute.
211 	 * </p>
212 	 *
213 	 * @param key a {@link java.lang.String} object.
214 	 * @param value a {@link java.lang.String} object.
215 	 * @return a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
216 	 */
217 	public ClauseParameters attribute(String key, String value)
218 	{
219 		attributes.put(key, value);
220 		return this;
221 	}
222 
223 
224 	/**
225 	 * <p>
226 	 * appendTo.
227 	 * </p>
228 	 *
229 	 * @param appendix a {@link java.lang.Appendable} object.
230 	 * @return a {@link java.lang.Appendable} object.
231 	 * @throws java.io.IOException if any.
232 	 */
233 	public Appendable appendTo(Appendable appendix) throws IOException
234 	{
235 		appendTo(appendix, attributes, "=");
236 		appendTo(appendix, directives, ":=");
237 		return appendix;
238 	}
239 
240 
241 	private void appendTo(Appendable appendage, Map<String, String> source, String symbol) throws IOException
242 	{
243 		if(!source.isEmpty()) {
244 			appendage.append(';');
245 			for(Iterator<Entry<String, String>> it = source.entrySet().iterator(); it.hasNext();) {
246 				Entry<String, String> entry = it.next();
247 				appendage.append(entry.getKey()).append(symbol);
248 
249 				if(entry.getValue().indexOf('.') != -1 ||
250 						entry.getValue().indexOf(',') != -1) {
251 					appendage.append('"').append(entry.getValue()).append('"');
252 				} else {
253 					appendage.append(entry.getValue());
254 				}
255 				if(it.hasNext()) {
256 					appendage.append(';');
257 				}
258 			}
259 		}
260 	}
261 
262 
263 	/**
264 	 * <p>
265 	 * attributeOrDefault.
266 	 * </p>
267 	 *
268 	 * @param name a {@link java.lang.String} object.
269 	 * @param defaultValue a {@link java.lang.String} object.
270 	 * @return a {@link java.lang.String} object.
271 	 */
272 	public String attributeOrDefault(String name, String defaultValue)
273 	{
274 		String value = attribute(name);
275 		return (value == null) ? defaultValue : value;
276 	}
277 
278 
279 	/**
280 	 * <p>
281 	 * attribute.
282 	 * </p>
283 	 *
284 	 * @param name a {@link java.lang.String} object.
285 	 * @return a {@link java.lang.String} object.
286 	 */
287 	public String attribute(String name)
288 	{
289 		return attributes().get(name);
290 	}
291 }