class ShardId implements Writeable, Comparable<ShardId> {

    private final Index index;
    private final int shardId;
    private final int hashCode;

    public ShardId(Index index, int shardId) {
        this.index = index;
        this.shardId = shardId;
        this.hashCode = computeHashCode();
    }

    public ShardId(String index, String indexUUID, int shardId) {
        this(new Index(index, indexUUID), shardId);
    }

    public ShardId(StreamInput in) throws IOException {
        index = new Index(in);
        shardId = in.readVInt();
        hashCode = computeHashCode();
    }

    @Override
    public void writeTo(StreamOutput out) throws IOException {
        index.writeTo(out);
        out.writeVInt(shardId);
    }

    public Index getIndex() {
        return index;
    }

    public String getIndexName() {
        return index.getName();
    }

    public int id() {
        return this.shardId;
    }

    @Override
    public String toString() {
        return "[" + index.getName() + "][" + shardId + "]";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ShardId shardId1 = (ShardId) o;
        return shardId == shardId1.shardId && index.equals(shardId1.index);
    }

    @Override
    public int hashCode() {
        return hashCode;
    }

    private int computeHashCode() {<FILL_FUNCTION_BODY>}

    @Override
    public int compareTo(ShardId o) {
        if (o.id() == shardId) {
            int compare = index.getName().compareTo(o.getIndex().getName());
            if (compare != 0) {
                return compare;
            }
            return index.getUUID().compareTo(o.getIndex().getUUID());
        }
        return Integer.compare(shardId, o.id());
    }
}

        int result = index != null ? index.hashCode() : 0;
        result = 31 * result + shardId;
        return result;
    
<no_super_class>