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

com.almworks.jira.structure.api2g.item.ItemIdentity Maven / Gradle / Ivy

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

import com.almworks.jira.structure.api2g.Limits;
import com.atlassian.annotations.PublicApi;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.annotation.concurrent.Immutable;
import java.io.Serializable;
import java.text.ParseException;

@PublicApi
@Immutable
// todo make sure all type ID Strings are intern()ed
public abstract class ItemIdentity implements Serializable {
  // todo do we really need it?
  public static final ItemIdentity ITEM_ZERO = longId("0", 0);

  @NotNull
  private final String myItemType;

  private ItemIdentity(@NotNull String itemType) {
    if (StringUtils.isBlank(itemType)) {
      throw new IllegalArgumentException("item type must not be empty");
    }
    if (itemType.length() > Limits.MAX_MODULE_KEY_LENGTH) {
      throw new IllegalArgumentException("item type must not be longer than " + Limits.MAX_MODULE_KEY_LENGTH + " chars");
    }
    myItemType = itemType;
  }

  @NotNull
  public String getItemType() {
    return myItemType;
  }

  public boolean isStringId() {
    return false;
  }

  @NotNull
  public String getStringId() {
    throw new UnsupportedOperationException("Not a string ID");
  }

  public boolean isLongId() {
    return false;
  }

  public long getLongId() {
    throw new UnsupportedOperationException("Not a long ID");
  }

  @NotNull
  public static ItemIdentity stringId(@NotNull String itemType, @NotNull String stringId) {
    return new StringIdentity(itemType, stringId);
  }

  @NotNull
  public static ItemIdentity longId(@NotNull String itemType, long longId) {
    return new LongIdentity(itemType, longId);
  }

  /**
   * Creates either longId or stringId depending on the value of stringId.
   */
  public static ItemIdentity id(@NotNull String itemType, long longId, @Nullable String stringId) {
    if (StringUtils.isBlank(stringId)) {
      return longId(itemType, longId);
    } else if (longId == 0) {
      return stringId(itemType, stringId);
    } else {
      throw new IllegalArgumentException("item identity cannot have both string (" + stringId + ") and long (" + longId + ") components");
    }
  }

  // todo maybe move to tests if there's no need for canonical representation of item id
  // Must be compatible with ItemSerializer and Deserializer.js
  @NotNull
  public static ItemIdentity parse(String id) throws ParseException {
    if (id == null || id.isEmpty()) {
      throw new ParseException("cannot parse empty id", 0);
    }
    int k = id.indexOf('/');
    if (k < 0) {
      try {
        long longId = Long.parseLong(id);
        return CoreIdentities.issue(longId);
      } catch (NumberFormatException  e) {
        throw new ParseException("unknown id format [" + id + "]", id.length());
      }
    }
    if (k == 0) {
      throw new ParseException("empty type id [" + id + "]", 0);
    }
    if (k == id.length() - 1) {
      throw new ParseException("unexpected end of line [" + id + "]", id.length());
    }
    String typeId = id.substring(0, k);
    if (id.charAt(k + 1) == '/') {
      String sid = id.substring(k + 2);
      if (sid.isEmpty()) {
        throw new ParseException("empty sid [" + id + "]", k + 2);
      }
      try {
        return stringId(typeId, sid);
      } catch (IllegalArgumentException e) {
        throw new ParseException(e.getMessage(), k + 1);
      }
    } else {
      String lid = id.substring(k + 1);
      if (lid.isEmpty()) {
        throw new ParseException("empty id [" + id + "]", k + 1);
      }
      try {
        return longId(typeId, Long.parseLong(lid));
      } catch (NumberFormatException e) {
        throw new ParseException("bad id format [" + id + "]", k + 1);
      } catch (IllegalArgumentException e) {
        throw new ParseException(e.getMessage(), k + 1);
      }
    }
  }


  @PublicApi
  public static final class StringIdentity extends ItemIdentity implements Serializable {
    @NotNull
    private final String myStringId;

    private StringIdentity(@NotNull String itemType, @NotNull String stringId) {
      super(itemType);
      if (StringUtils.isBlank(stringId)) {
        throw new IllegalArgumentException("string id must not be empty");
      }
      if (stringId.length() > Limits.MAX_ITEM_STRING_ID_LENGTH) {
        throw new IllegalArgumentException("string id must not be longer than " + Limits.MAX_ITEM_STRING_ID_LENGTH + " chars");
      }
      myStringId = stringId;
    }

    @Override
    public boolean isStringId() {
      return true;
    }

    @Override
    @NotNull
    public String getStringId() {
      return myStringId;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      StringIdentity that = (StringIdentity) o;
      return myStringId.equals(that.myStringId) && getItemType().equals(that.getItemType());
    }

    @Override
    public int hashCode() {
      return myStringId.hashCode() * 31 + getItemType().hashCode();
    }

    @Override
    public String toString() {
      return getItemType() + "//" + myStringId;
    }
  }


  @PublicApi
  public static final class LongIdentity extends ItemIdentity implements Serializable {
    private final long myLongId;

    private LongIdentity(@NotNull String itemType, long longId) {
      super(itemType);
      myLongId = longId;
    }

    @Override
    public boolean isLongId() {
      return true;
    }

    @Override
    public long getLongId() {
      return myLongId;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }
      LongIdentity that = (LongIdentity) o;
      return myLongId == that.myLongId && getItemType().equals(that.getItemType());
    }

    @Override
    public int hashCode() {
      return (int) (myLongId ^ (myLongId >>> 32)) * 31 + getItemType().hashCode();
    }

    @Override
    public String toString() {
      return getItemType() + "/" + myLongId;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy