All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.almworks.jira.structure.api.attribute.AttributeSpec Maven / Gradle / Ivy

There is a newer version: 17.25.3
Show newest version
package com.almworks.jira.structure.api.attribute;

import com.almworks.jira.structure.api.util.*;
import com.atlassian.annotations.PublicApi;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.annotation.concurrent.Immutable;
import java.util.Collections;
import java.util.Map;

/**
 * 

{@code AttributeSpec} is the "attribute specification", a composite identifier of an attribute. See * {@link com.almworks.jira.structure.api.attribute package documentation} for the definition of an attribute.

* *

Attribute specification contains the following parts:

* *
    *
  1. A unique {@code String} identifier. Attributes that have the same identifier are considered to be semantically * same or similar.
  2. * *
  3. An unbounded parameters map, which should be serializable to JSON (contain only simple types, maps * and arrays). Two specifications with the same ID and parameters are considered to be * semantically same.
  4. * *
  5. {@link ValueFormat}, which defines the type and possible operations on the resulting value.
  6. *
* *

Use {@link AttributeSpecBuilder} to build an instance of {@code AttributeSpec} in the code.

* *

Parameter normalization

* *

Attribute spec parameters are normalized. This means that if the value of a parameter is the default for that * parameter, it is not stored in the map. For example, {@code int} parameters have default equal to {@code 0}. If you try * to build an attribute spec and set an {@code int} parameter to 0, the resulting attribute spec will not have that * value.

* *

This is done to avoid unequal instances of {@code AttributeSpec} to represent the same attribute. If not normalized, * multiple versions of the same attribute spec could lead to bugs.

* *

See {@link AttributeSpecNormalization} for more details.

* * @param type of the value expected for this attribute * @see StructureAttributeService * @see AttributeSpecBuilder */ @PublicApi @Immutable public final class AttributeSpec { @NotNull private final String myId; @NotNull private final ValueFormat myFormat; @NotNull private final Map myParams; private transient int myHashCode; private transient SpecParams myParamsObject; private transient String myStringRepresentation; /** * Constructs an attribute spec with the given ID and format, without parameters. * * @param id attribute ID * @param format value format */ public AttributeSpec(String id, ValueFormat format) { this(id, format, null, false); } /** * Constructs an attribute spec with the given ID, format and parameters. The latter should contain only simple types * and collections, the things serializable into JSON. * * @param id attribute ID * @param format value format * @param params parameters map */ public AttributeSpec(@NotNull String id, @NotNull ValueFormat format, @Nullable Map params) { this(id, format, params, false); } AttributeSpec(@NotNull String id, @NotNull ValueFormat format, @Nullable Map params, boolean reuseParams) { if (StringUtils.isBlank(id)) { throw new IllegalArgumentException("attribute id must not be empty"); } if (id.length() > Limits.MAX_SPEC_ID_LENGTH) { throw new IllegalArgumentException("attribute id must not be longer than " + Limits.MAX_SPEC_ID_LENGTH + " chars"); } if (id.indexOf(':') >= 0) { throw new IllegalArgumentException("attribute id must not contain colon"); } if (format == null) { throw new IllegalArgumentException("attribute format must not be null"); } myId = id; myFormat = format; Map map = reuseParams ? params : JsonMapUtil.copyParameters(params, true, true, true); myParams = AttributeSpecNormalization.normalizeParams(id, map != null ? map : Collections.emptyMap()); } /** * Returns the attribute's ID. */ @NotNull public String getId() { return myId; } /** * Returns the attribute's format. */ @NotNull public ValueFormat getFormat() { return myFormat; } /** * Returns the attribute's parameters as a read-only map. If there are no parameters, empty map is returned. */ @NotNull public Map getParamsMap() { return myParams; } /** * Returns the same as {@link #getParamsMap()}, but wrapped into accessor object. */ @NotNull public SpecParams getParams() { SpecParams paramsObject = myParamsObject; if (paramsObject == null) { myParamsObject = paramsObject = new SpecParams(myParams); } return paramsObject; } /** * Checks if this attribute specification is for the given attribute ID. * * @param id attribute's ID * @return true if this attribute has the same ID */ public boolean is(String id) { return myId.equals(id); } /** * Checks if this attribute specification contains the given format. * * @param format value format * @return true if this attribute has this format */ public boolean is(ValueFormat format) { return myFormat.equals(format); } /** * Checks if this attribute specification is for the given ID and format. * * @param id attribute's ID * @param format value format * @return true if this attribute has this ID and format */ public boolean is(String id, ValueFormat format) { return is(id) && is(format); } /** * Returns an attribute spec with the same ID and parameters, but with the given {@code ValueFormat}. * * @param format the format for a new {@code AttributeSpec} */ public AttributeSpec as(ValueFormat format) { return is(format) ? format.cast(this) : new AttributeSpec(myId, format, myParams); } /** * Returns a new attribute spec with added parameter. * * @param name parameter name * @param value parameter value * @return a new, adjusted attribute specification */ public AttributeSpec withParam(String name, Object value) { return AttributeSpecBuilder.create(this) .params().set(name, value).done() .build(); } /** * Returns a new attribute spec with parameters replaced with a new map. * * @param newParams replacement parameters */ public AttributeSpec replaceParams(Map newParams) { return new AttributeSpec<>(getId(), getFormat(), newParams, true); } /** * Returns a new attribute spec with all parameters removed. */ public AttributeSpec noParams() { return new AttributeSpec<>(getId(), getFormat()); } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AttributeSpec that = (AttributeSpec) o; if (!myFormat.equals(that.myFormat)) return false; if (!myId.equals(that.myId)) return false; if (!myParams.equals(that.myParams)) return false; return true; } public int hashCode() { int result = myHashCode; if (result == 0) { result = myId.hashCode(); result = 31 * result + myFormat.hashCode(); result = 31 * result + (myParams.hashCode()); myHashCode = result; } return result; } public String toString() { String r = myStringRepresentation; if (r == null) { StringBuilder builder = new StringBuilder(); builder.append(myId); if (!myParams.isEmpty()) { builder.append(':').append(JsonUtil.toJson(myParams)); } builder.append(':').append(myFormat); myStringRepresentation = r = builder.toString(); } return r; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy