ClauseParameters.java
/*-
* #%L
* io.earcam.instrumental.module.osgi
* %%
* Copyright (C) 2018 earcam
* %%
* SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
*
* You <b>must</b> choose to accept, in full - any individual or combination of
* the following licenses:
* <ul>
* <li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
* <li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
* <li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
* <li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
* </ul>
* #L%
*/
package io.earcam.instrumental.module.osgi;
import static io.earcam.instrumental.module.osgi.OsgiAttributeConstants.VERSION_ATTRIBUTE;
import static java.util.Collections.emptyMap;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import io.earcam.instrumental.fluent.Fluent;
import io.earcam.unexceptional.Exceptional;
/**
* <p>
* ClauseParameters class.
* </p>
*
* @see ClauseParameter for construction
*/
public final class ClauseParameters {
public static final class ClauseParameter {
private ClauseParameter()
{}
@Fluent
public static ClauseParameters directive(String key, String value)
{
ClauseParameters parameters = new ClauseParameters();
parameters.directive(key, value);
return parameters;
}
@Fluent
public static ClauseParameters attribute(String key, String value)
{
ClauseParameters parameters = new ClauseParameters();
parameters.attribute(key, value);
return parameters;
}
@Fluent
public static ClauseParameters version(int major, int minor, int micro)
{
ClauseParameters parameters = new ClauseParameters();
parameters.attribute(VERSION_ATTRIBUTE.value, major + "." + minor + "." + micro);
return parameters;
}
}
/**
* Empty parameters, immutably so
*/
public static final ClauseParameters EMPTY_PARAMETERS = new ClauseParameters(emptyMap(), emptyMap());
private final Map<String, String> attributes;
private final Map<String, String> directives;
/**
* <p>
* Constructor for ClauseParameters.
* </p>
*/
public ClauseParameters()
{
this(new HashMap<>(), new HashMap<>());
}
/**
* <p>
* Constructor for ClauseParameters.
* </p>
*
* @param attributes a {@link java.util.Map} object.
* @param directives a {@link java.util.Map} object.
* @see ClauseParameter#attribute(String, String)
* @see ClauseParameter#directive(String, String)
* @see ClauseParameter#attribute(String, String)
* @see ClauseParameter#directive(String, String)
*/
public ClauseParameters(Map<String, String> attributes, Map<String, String> directives)
{
this.attributes = attributes;
this.directives = directives;
}
@Override
public String toString()
{
return Exceptional.apply(this::appendTo, new StringBuilder()).toString();
}
@Override
public boolean equals(Object other)
{
return other instanceof ClauseParameters && equals((ClauseParameters) other);
}
/**
* <p>
* equals.
* </p>
*
* @param that a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
* @return a boolean.
*/
public boolean equals(ClauseParameters that)
{
return that != null
&& that.attributes.equals(this.attributes)
&& that.directives.equals(this.directives);
}
@Override
public int hashCode()
{
return Objects.hash(attributes, directives);
}
/**
* <p>
* isEmpty.
* </p>
*
* @return a boolean.
*/
public boolean isEmpty()
{
return attributes().isEmpty()
&& directives().isEmpty();
}
/**
* <p>
* directives.
* </p>
*
* @return a {@link java.util.Map} object.
*/
public Map<String, String> directives()
{
return directives;
}
/**
* <p>
* directive.
* </p>
*
* @param key a {@link java.lang.String} object.
* @param value a {@link java.lang.String} object.
* @return a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
*/
public ClauseParameters directive(String key, String value)
{
directives.put(key, value);
return this;
}
/**
* <p>
* attributes.
* </p>
*
* @return a modifiable {@link Map}.
*/
public Map<String, String> attributes()
{
return attributes;
}
/**
* <p>
* attribute.
* </p>
*
* @param key a {@link java.lang.String} object.
* @param value a {@link java.lang.String} object.
* @return a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
*/
public ClauseParameters attribute(String key, String value)
{
attributes.put(key, value);
return this;
}
/**
* <p>
* appendTo.
* </p>
*
* @param appendix a {@link java.lang.Appendable} object.
* @return a {@link java.lang.Appendable} object.
* @throws java.io.IOException if any.
*/
public Appendable appendTo(Appendable appendix) throws IOException
{
appendTo(appendix, attributes, "=");
appendTo(appendix, directives, ":=");
return appendix;
}
private void appendTo(Appendable appendage, Map<String, String> source, String symbol) throws IOException
{
if(!source.isEmpty()) {
appendage.append(';');
for(Iterator<Entry<String, String>> it = source.entrySet().iterator(); it.hasNext();) {
Entry<String, String> entry = it.next();
appendage.append(entry.getKey()).append(symbol);
if(entry.getValue().indexOf('.') != -1 ||
entry.getValue().indexOf(',') != -1) {
appendage.append('"').append(entry.getValue()).append('"');
} else {
appendage.append(entry.getValue());
}
if(it.hasNext()) {
appendage.append(';');
}
}
}
}
/**
* <p>
* attributeOrDefault.
* </p>
*
* @param name a {@link java.lang.String} object.
* @param defaultValue a {@link java.lang.String} object.
* @return a {@link java.lang.String} object.
*/
public String attributeOrDefault(String name, String defaultValue)
{
String value = attribute(name);
return (value == null) ? defaultValue : value;
}
/**
* <p>
* attribute.
* </p>
*
* @param name a {@link java.lang.String} object.
* @return a {@link java.lang.String} object.
*/
public String attribute(String name)
{
return attributes().get(name);
}
}