com.almworks.jira.structure.api.attribute.AttributeSpecBuilder Maven / Gradle / Ivy
Show all versions of structure-api Show documentation
package com.almworks.jira.structure.api.attribute;
import com.almworks.jira.structure.api.util.JsonMapUtil;
import com.atlassian.annotations.PublicApi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* A builder for AttributeSpec.
*
* @param
*/
@PublicApi
public class AttributeSpecBuilder {
private String myId;
private ValueFormat myFormat;
private ParamsBuilder> myParams;
/**
* Creates an empty builder.
*
* @return builder
*/
@NotNull
public static AttributeSpecBuilder create() {
return new AttributeSpecBuilder<>();
}
/**
* Creates a builder with the given attribute ID.
*
* @param id attribute id
* @return builder
*/
@NotNull
public static AttributeSpecBuilder create(@Nullable String id) {
return new AttributeSpecBuilder().setId(id);
}
/**
* Creates a builder with the given attribute ID and format.
*
* @param id attribute id
* @param format value format
* @return builder
*/
@NotNull
public static AttributeSpecBuilder create(@Nullable String id, @Nullable ValueFormat format) {
return new AttributeSpecBuilder().setId(id).setFormat(format);
}
/**
* Creates a builder with the given attribute ID, format and parameters. The parameters are copied from the passed map, so it can be reused
* by the calling code.
*
* @param id attribute id
* @param format value format
* @param params parameters map
* @return builder
*/
@NotNull
public static AttributeSpecBuilder create(@Nullable String id, @Nullable ValueFormat format, @Nullable Map params) {
return new AttributeSpecBuilder()
.setId(id)
.setFormat(format)
.params().copyFrom(params).done();
}
/**
* Creates a builder based on the given sample. Copies all the fields from the attribute spec.
*
* @param sample sample attribute spec
* @return builder
*/
public static AttributeSpecBuilder create(AttributeSpec sample) {
if (sample == null) return new AttributeSpecBuilder<>();
return create(sample.getId(), sample.getFormat(), sample.getParamsMap());
}
/**
* Builds the attribute spec.
*
* @return attribute spec
* @throws IllegalArgumentException if there's anything wrong with id, format or parameters
*/
@NotNull
public AttributeSpec build() {
return new AttributeSpec<>(myId, myFormat, myParams == null ? null : myParams.buildMap(), true);
}
/**
* Sets the attribute id.
*
* @param id attribute id
* @return this builder
*/
public AttributeSpecBuilder setId(String id) {
myId = id;
return this;
}
/**
* Sets the value format.
*
* @param format value format
* @return this builder
*/
@SuppressWarnings("unchecked")
public AttributeSpecBuilder setFormat(ValueFormat format) {
myFormat = (ValueFormat) format;
return (AttributeSpecBuilder) this;
}
/**
* Provides access to {@link ParamsBuilder}, which is used to build parameter map.
*
* @return parameter builder
*/
public ParamsBuilder> params() {
if (myParams == null) {
myParams = new ParamsBuilder<>(this);
}
return myParams;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AttributeSpecBuilder> that = (AttributeSpecBuilder>) o;
if (myId != null ? !myId.equals(that.myId) : that.myId != null) return false;
if (myFormat != null ? !myFormat.equals(that.myFormat) : that.myFormat != null) return false;
return !(myParams != null ? !myParams.equals(that.myParams) : that.myParams != null);
}
@Override
public int hashCode() {
int result = myId != null ? myId.hashCode() : 0;
result = 31 * result + (myFormat != null ? myFormat.hashCode() : 0);
result = 31 * result + (myParams != null ? myParams.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "AttributeSpecBuilder('" + myId + "', " + myFormat + ", " + myParams + ")";
}
/**
* Parameter builder class, used to set specific parameters.
*
* @param parent builder type
*/
public class ParamsBuilder
{
private final P myParent;
private final Map myParams = new LinkedHashMap<>();
ParamsBuilder(P parent) {
myParent = parent;
}
/**
* Returns the parent builder.
*
* @return parent builder
*/
public P done() {
return myParent;
}
/**
* Removes the given parameter.
*
* @param key parameter name
* @return this builder
*/
public ParamsBuilder remove(String key) {
myParams.remove(key);
return this;
}
/**
* Creates a new builder for creating an object inside the current builder's parameter space. This builder becomes the
* parent of the new builder.
*
* @param key parameter name
* @return builder for the object that will be addressed by the given parameter name
*/
public ParamsBuilder> object(String key) {
Object existing = myParams.get(key);
ParamsBuilder> r;
if (existing instanceof ParamsBuilder) {
//noinspection unchecked
r = (ParamsBuilder>) existing;
} else {
r = new ParamsBuilder<>(this);
put(key, r);
}
return r;
}
/**
* Sets the parameter.
*
* @param key parameter name
* @param value parameter value
* @return this builder
*/
public ParamsBuilder set(String key, Object value) {
if (value == null) return this;
if (value instanceof AttributeSpec) {
return setAttribute(key, (AttributeSpec) value);
}
JsonMapUtil.checkValidParameter(value);
return setValidated(key, value);
}
/**
* Special method to set the parameter "attribute" to the given attribute spec.
*
* @param value attribute spec
* @return this builder
* @see CoreAttributeSpecs.Param#ATTRIBUTE
*/
public ParamsBuilder
setAttribute(AttributeSpec> value) {
return setAttribute(SharedAttributeSpecs.Param.ATTRIBUTE, value);
}
/**
* Special method to set a parameter to the given attribute spec.
*
* @param key attribute name
* @param value attribute spec
* @return this builder
*/
public ParamsBuilder
setAttribute(String key, AttributeSpec> value) {
return object(key)
.set(SharedAttributeSpecs.Param.ID, value.getId())
.set(SharedAttributeSpecs.Param.FORMAT, value.getFormat().getFormatId())
.setValidatedMap(SharedAttributeSpecs.Param.PARAMS, value.getParamsMap())
.done();
}
/**
* Copies the parameters from the given map.
*
* @param map map with parameters
* @return this builder
*/
public ParamsBuilder
copyFrom(@Nullable Map map) {
if (map == null || map.isEmpty()) return this;
JsonMapUtil.checkValidParameter(map);
return copyFromValidated(map);
}
/**
* Builds the attribute spec.
*
* @return attribute spec
*/
public AttributeSpec build() {
return AttributeSpecBuilder.this.build();
}
private ParamsBuilder setValidated(String key, Object value) {
if (value instanceof Map) {
//noinspection unchecked
return setValidatedMap(key, (Map) value);
} else {
put(key, value);
}
return this;
}
private ParamsBuilder
setValidatedMap(String key, Map map) {
if (map == null || map.isEmpty()) return this;
return object(key).copyFromValidated(map).done();
}
@NotNull
private ParamsBuilder copyFromValidated(Map map) {
if (map != null) {
for (Map.Entry e : map.entrySet()) {
setValidated(e.getKey(), e.getValue());
}
}
return this;
}
private void put(String key, Object r) {
if (key == null) {
throw new IllegalArgumentException("null key is not allowed");
}
myParams.put(key, r);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ParamsBuilder> that = (ParamsBuilder>) o;
return myParams.equals(that.myParams);
}
@Override
public int hashCode() {
return myParams.hashCode();
}
@Override
public String toString() {
return myParams.toString();
}
@Nullable
private Map buildMap() {
if (myParams.isEmpty()) return null;
LinkedHashMap r = new LinkedHashMap<>(myParams);
for (Iterator> ii = r.entrySet().iterator(); ii.hasNext(); ) {
Map.Entry e = ii.next();
Object value = e.getValue();
if (value instanceof ParamsBuilder) {
//noinspection unchecked
value = ((ParamsBuilder>)value).buildMap();
if (value == null) {
ii.remove();
} else {
e.setValue(value);
}
}
}
return r;
}
}
}