apply new code formatter and save action
This commit is contained in:
@@ -8,106 +8,106 @@ import java.time.temporal.TemporalUnit;
|
||||
|
||||
public class DateTimeRange {
|
||||
|
||||
private static final DateTimeRange MAX = new DateTimeRange(
|
||||
OffsetDateTime.of(1900, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC),
|
||||
OffsetDateTime.of(2100, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC));
|
||||
private static final DateTimeRange MAX = new DateTimeRange(
|
||||
OffsetDateTime.of(1900, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC),
|
||||
OffsetDateTime.of(2100, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC));
|
||||
|
||||
private final OffsetDateTime start;
|
||||
private final OffsetDateTime end;
|
||||
private final OffsetDateTime start;
|
||||
private final OffsetDateTime end;
|
||||
|
||||
public DateTimeRange(final OffsetDateTime start, final OffsetDateTime end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
public DateTimeRange(final OffsetDateTime start, final OffsetDateTime end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public static DateTimeRange max() {
|
||||
return MAX;
|
||||
}
|
||||
public static DateTimeRange max() {
|
||||
return MAX;
|
||||
}
|
||||
|
||||
public static DateTimeRange now() {
|
||||
return relativeMillis(0);
|
||||
}
|
||||
public static DateTimeRange now() {
|
||||
return relativeMillis(0);
|
||||
}
|
||||
|
||||
public static DateTimeRange relative(final long amount, final TemporalUnit unit) {
|
||||
final OffsetDateTime now = OffsetDateTime.now();
|
||||
return new DateTimeRange(now.minus(amount, unit), now);
|
||||
}
|
||||
public static DateTimeRange relative(final long amount, final TemporalUnit unit) {
|
||||
final OffsetDateTime now = OffsetDateTime.now();
|
||||
return new DateTimeRange(now.minus(amount, unit), now);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeMillis(final long amount) {
|
||||
return relative(amount, ChronoUnit.MILLIS);
|
||||
}
|
||||
public static DateTimeRange relativeMillis(final long amount) {
|
||||
return relative(amount, ChronoUnit.MILLIS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeSeconds(final long amount) {
|
||||
return relative(amount, ChronoUnit.SECONDS);
|
||||
}
|
||||
public static DateTimeRange relativeSeconds(final long amount) {
|
||||
return relative(amount, ChronoUnit.SECONDS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeMinutes(final long amount) {
|
||||
return relative(amount, ChronoUnit.MINUTES);
|
||||
}
|
||||
public static DateTimeRange relativeMinutes(final long amount) {
|
||||
return relative(amount, ChronoUnit.MINUTES);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeHours(final long amount) {
|
||||
return relative(amount, ChronoUnit.HOURS);
|
||||
}
|
||||
public static DateTimeRange relativeHours(final long amount) {
|
||||
return relative(amount, ChronoUnit.HOURS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeDays(final long amount) {
|
||||
return relative(amount, ChronoUnit.DAYS);
|
||||
}
|
||||
public static DateTimeRange relativeDays(final long amount) {
|
||||
return relative(amount, ChronoUnit.DAYS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeMonths(final long amount) {
|
||||
return relative(amount, ChronoUnit.MONTHS);
|
||||
}
|
||||
public static DateTimeRange relativeMonths(final long amount) {
|
||||
return relative(amount, ChronoUnit.MONTHS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeYears(final long amount) {
|
||||
return relative(amount, ChronoUnit.YEARS);
|
||||
}
|
||||
public static DateTimeRange relativeYears(final long amount) {
|
||||
return relative(amount, ChronoUnit.YEARS);
|
||||
}
|
||||
|
||||
public OffsetDateTime getStart() {
|
||||
return start;
|
||||
}
|
||||
public OffsetDateTime getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public long getStartEpochMilli() {
|
||||
return start.toInstant().toEpochMilli();
|
||||
}
|
||||
public long getStartEpochMilli() {
|
||||
return start.toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
public OffsetDateTime getEnd() {
|
||||
return end;
|
||||
}
|
||||
public OffsetDateTime getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public long getEndEpochMilli() {
|
||||
return end.toInstant().toEpochMilli();
|
||||
}
|
||||
public long getEndEpochMilli() {
|
||||
return end.toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return start + "-" + end;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return start + "-" + end;
|
||||
}
|
||||
|
||||
public static DateTimeRange ofDay(final OffsetDateTime day) {
|
||||
final OffsetDateTime from = day.truncatedTo(ChronoUnit.DAYS);
|
||||
final OffsetDateTime to = from.plusDays(1).minusNanos(1);
|
||||
public static DateTimeRange ofDay(final OffsetDateTime day) {
|
||||
final OffsetDateTime from = day.truncatedTo(ChronoUnit.DAYS);
|
||||
final OffsetDateTime to = from.plusDays(1).minusNanos(1);
|
||||
|
||||
return new DateTimeRange(from, to);
|
||||
}
|
||||
return new DateTimeRange(from, to);
|
||||
}
|
||||
|
||||
public Duration duration() {
|
||||
return Duration.between(start, end);
|
||||
}
|
||||
public Duration duration() {
|
||||
return Duration.between(start, end);
|
||||
}
|
||||
|
||||
public boolean inRange(final long epochMilli) {
|
||||
final long fromEpochMilli = start.toInstant().toEpochMilli();
|
||||
final long toEpochMilli = end.toInstant().toEpochMilli();
|
||||
public boolean inRange(final long epochMilli) {
|
||||
final long fromEpochMilli = start.toInstant().toEpochMilli();
|
||||
final long toEpochMilli = end.toInstant().toEpochMilli();
|
||||
|
||||
return fromEpochMilli <= epochMilli && epochMilli <= toEpochMilli;
|
||||
}
|
||||
return fromEpochMilli <= epochMilli && epochMilli <= toEpochMilli;
|
||||
}
|
||||
|
||||
public boolean inRange(final OffsetDateTime date) {
|
||||
return start.compareTo(date) <= 0 && end.compareTo(date) >= 0;
|
||||
}
|
||||
public boolean inRange(final OffsetDateTime date) {
|
||||
return start.compareTo(date) <= 0 && end.compareTo(date) >= 0;
|
||||
}
|
||||
|
||||
public boolean intersect(final DateTimeRange timeRange) {
|
||||
return inRange(timeRange.start) //
|
||||
|| inRange(timeRange.end) //
|
||||
|| timeRange.inRange(start)//
|
||||
|| timeRange.inRange(end);
|
||||
}
|
||||
public boolean intersect(final DateTimeRange timeRange) {
|
||||
return inRange(timeRange.start) //
|
||||
|| inRange(timeRange.end) //
|
||||
|| timeRange.inRange(start)//
|
||||
|| timeRange.inRange(end);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,36 +7,36 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class Entries implements Iterable<Entry> {
|
||||
/**
|
||||
* A special {@link Entries} instance that can be used as poison object for
|
||||
* {@link BlockingQueueIterator}.
|
||||
*/
|
||||
public static final Entries POISON = new Entries(0);
|
||||
/**
|
||||
* A special {@link Entries} instance that can be used as poison object for
|
||||
* {@link BlockingQueueIterator}.
|
||||
*/
|
||||
public static final Entries POISON = new Entries(0);
|
||||
|
||||
private final List<Entry> entries;
|
||||
private final List<Entry> entries;
|
||||
|
||||
public Entries(final int initialSize) {
|
||||
entries = new ArrayList<>(initialSize);
|
||||
}
|
||||
public Entries(final int initialSize) {
|
||||
entries = new ArrayList<>(initialSize);
|
||||
}
|
||||
|
||||
public Entries(final Entry... entries) {
|
||||
this.entries = new ArrayList<>(Arrays.asList(entries));
|
||||
}
|
||||
public Entries(final Entry... entries) {
|
||||
this.entries = new ArrayList<>(Arrays.asList(entries));
|
||||
}
|
||||
|
||||
public Entries(final Collection<Entry> entries) {
|
||||
this.entries = new ArrayList<>(entries);
|
||||
}
|
||||
public Entries(final Collection<Entry> entries) {
|
||||
this.entries = new ArrayList<>(entries);
|
||||
}
|
||||
|
||||
public void add(final Entry entry) {
|
||||
entries.add(entry);
|
||||
}
|
||||
public void add(final Entry entry) {
|
||||
entries.add(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry> iterator() {
|
||||
return entries.iterator();
|
||||
}
|
||||
@Override
|
||||
public Iterator<Entry> iterator() {
|
||||
return entries.iterator();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return entries.size();
|
||||
}
|
||||
public int size() {
|
||||
return entries.size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,65 +7,65 @@ import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class Entry {
|
||||
|
||||
private final long value;
|
||||
private final long value;
|
||||
|
||||
private final Tags tags;
|
||||
private final Tags tags;
|
||||
|
||||
private final long epochMilli;
|
||||
private final long epochMilli;
|
||||
|
||||
public Entry(final long epochMilli, final long value, final Tags tags) {
|
||||
this.epochMilli = epochMilli;
|
||||
this.tags = tags;
|
||||
this.value = value;
|
||||
}
|
||||
public Entry(final long epochMilli, final long value, final Tags tags) {
|
||||
this.epochMilli = epochMilli;
|
||||
this.tags = tags;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public long getEpochMilli() {
|
||||
return epochMilli;
|
||||
}
|
||||
public long getEpochMilli() {
|
||||
return epochMilli;
|
||||
}
|
||||
|
||||
public Tags getTags() {
|
||||
return tags;
|
||||
}
|
||||
public Tags getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
final OffsetDateTime date = Instant.ofEpochMilli(epochMilli).atOffset(ZoneOffset.UTC);
|
||||
return date.format(DateTimeFormatter.ISO_ZONED_DATE_TIME) + " = " + value + " (" + tags.asString() + ")";
|
||||
}
|
||||
final OffsetDateTime date = Instant.ofEpochMilli(epochMilli).atOffset(ZoneOffset.UTC);
|
||||
return date.format(DateTimeFormatter.ISO_ZONED_DATE_TIME) + " = " + value + " (" + tags.asString() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (epochMilli ^ (epochMilli >>> 32));
|
||||
result = prime * result + ((tags == null) ? 0 : tags.hashCode());
|
||||
result = prime * result + (int) (value ^ (value >>> 32));
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (epochMilli ^ (epochMilli >>> 32));
|
||||
result = prime * result + ((tags == null) ? 0 : tags.hashCode());
|
||||
result = prime * result + (int) (value ^ (value >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Entry other = (Entry) obj;
|
||||
if (epochMilli != other.epochMilli)
|
||||
return false;
|
||||
if (tags == null) {
|
||||
if (other.tags != null)
|
||||
return false;
|
||||
} else if (!tags.equals(other.tags))
|
||||
return false;
|
||||
if (value != other.value)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Entry other = (Entry) obj;
|
||||
if (epochMilli != other.epochMilli)
|
||||
return false;
|
||||
if (tags == null) {
|
||||
if (other.tags != null)
|
||||
return false;
|
||||
} else if (!tags.equals(other.tags))
|
||||
return false;
|
||||
if (value != other.value)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,31 +6,31 @@ import org.lucares.collections.LongList;
|
||||
|
||||
public class GroupResult {
|
||||
|
||||
private final Tags groupedBy;
|
||||
private final Tags groupedBy;
|
||||
|
||||
private final Stream<LongList> timeValueStream;
|
||||
private final Stream<LongList> timeValueStream;
|
||||
|
||||
public GroupResult(final Stream<LongList> entries, final Tags groupedBy) {
|
||||
this.timeValueStream = entries;
|
||||
this.groupedBy = groupedBy;
|
||||
}
|
||||
public GroupResult(final Stream<LongList> entries, final Tags groupedBy) {
|
||||
this.timeValueStream = entries;
|
||||
this.groupedBy = groupedBy;
|
||||
}
|
||||
|
||||
public Tags getGroupedBy() {
|
||||
return groupedBy;
|
||||
}
|
||||
public Tags getGroupedBy() {
|
||||
return groupedBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link Stream}
|
||||
*/
|
||||
public Stream<LongList> asStream() {
|
||||
return timeValueStream;
|
||||
}
|
||||
/**
|
||||
* @return {@link Stream}
|
||||
*/
|
||||
public Stream<LongList> asStream() {
|
||||
return timeValueStream;
|
||||
}
|
||||
|
||||
public LongList flatMap() {
|
||||
final LongList result = new LongList();
|
||||
public LongList flatMap() {
|
||||
final LongList result = new LongList();
|
||||
|
||||
timeValueStream.forEachOrdered(result::addAll);
|
||||
timeValueStream.forEachOrdered(result::addAll);
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,74 +4,74 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Query {
|
||||
private final String query;
|
||||
private final String query;
|
||||
|
||||
private final DateTimeRange dateRange;
|
||||
private final DateTimeRange dateRange;
|
||||
|
||||
public Query(final String query, final DateTimeRange dateRange) {
|
||||
super();
|
||||
this.query = query;
|
||||
this.dateRange = dateRange;
|
||||
}
|
||||
public Query(final String query, final DateTimeRange dateRange) {
|
||||
super();
|
||||
this.query = query;
|
||||
this.dateRange = dateRange;
|
||||
}
|
||||
|
||||
public Query relativeMillis(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeMillis(amount));
|
||||
}
|
||||
public Query relativeMillis(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeMillis(amount));
|
||||
}
|
||||
|
||||
public Query relativeSeconds(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeSeconds(amount));
|
||||
}
|
||||
public Query relativeSeconds(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeSeconds(amount));
|
||||
}
|
||||
|
||||
public Query relativeMinutes(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeMinutes(amount));
|
||||
}
|
||||
public Query relativeMinutes(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeMinutes(amount));
|
||||
}
|
||||
|
||||
public Query relativeHours(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeHours(amount));
|
||||
}
|
||||
public Query relativeHours(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeHours(amount));
|
||||
}
|
||||
|
||||
public Query relativeDays(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeDays(amount));
|
||||
}
|
||||
public Query relativeDays(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeDays(amount));
|
||||
}
|
||||
|
||||
public Query relativeMonths(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeMonths(amount));
|
||||
}
|
||||
public Query relativeMonths(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeMonths(amount));
|
||||
}
|
||||
|
||||
public static Query createQuery(final String query, final DateTimeRange dateRange) {
|
||||
return new Query(query, dateRange);
|
||||
}
|
||||
public static Query createQuery(final String query, final DateTimeRange dateRange) {
|
||||
return new Query(query, dateRange);
|
||||
}
|
||||
|
||||
public static Query createQuery(final Tags tags, final DateTimeRange dateRange) {
|
||||
public static Query createQuery(final Tags tags, final DateTimeRange dateRange) {
|
||||
|
||||
final List<String> terms = new ArrayList<>();
|
||||
final List<String> terms = new ArrayList<>();
|
||||
|
||||
for (final String key : tags.getKeys()) {
|
||||
final String value = tags.getValue(key);
|
||||
for (final String key : tags.getKeys()) {
|
||||
final String value = tags.getValue(key);
|
||||
|
||||
final StringBuilder term = new StringBuilder();
|
||||
term.append(key);
|
||||
term.append("=");
|
||||
term.append(value);
|
||||
term.append(" ");
|
||||
final StringBuilder term = new StringBuilder();
|
||||
term.append(key);
|
||||
term.append("=");
|
||||
term.append(value);
|
||||
term.append(" ");
|
||||
|
||||
terms.add(term.toString());
|
||||
}
|
||||
terms.add(term.toString());
|
||||
}
|
||||
|
||||
return new Query(String.join(" and ", terms), dateRange);
|
||||
}
|
||||
return new Query(String.join(" and ", terms), dateRange);
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public DateTimeRange getDateRange() {
|
||||
return dateRange;
|
||||
}
|
||||
public DateTimeRange getDateRange() {
|
||||
return dateRange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "'" + query + "' [" + dateRange + "]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "'" + query + "' [" + dateRange + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package org.lucares.pdb.api;
|
||||
|
||||
public interface QueryConstants {
|
||||
String CARET_MARKER = "\ue001"; // character in the private use area
|
||||
String CARET_MARKER = "\ue001"; // character in the private use area
|
||||
}
|
||||
|
||||
@@ -2,28 +2,28 @@ package org.lucares.pdb.api;
|
||||
|
||||
public class QueryWithCaretMarker extends Query implements QueryConstants {
|
||||
|
||||
public enum ResultMode {
|
||||
CUT_AT_DOT, FULL_VALUES
|
||||
}
|
||||
public enum ResultMode {
|
||||
CUT_AT_DOT, FULL_VALUES
|
||||
}
|
||||
|
||||
private final int caretIndex;
|
||||
private final ResultMode resultMode;
|
||||
private final int caretIndex;
|
||||
private final ResultMode resultMode;
|
||||
|
||||
public QueryWithCaretMarker(final String query, final DateTimeRange dateRange, final int caretIndex,
|
||||
final ResultMode resultMode) {
|
||||
super(query, dateRange);
|
||||
this.caretIndex = caretIndex;
|
||||
this.resultMode = resultMode;
|
||||
}
|
||||
public QueryWithCaretMarker(final String query, final DateTimeRange dateRange, final int caretIndex,
|
||||
final ResultMode resultMode) {
|
||||
super(query, dateRange);
|
||||
this.caretIndex = caretIndex;
|
||||
this.resultMode = resultMode;
|
||||
}
|
||||
|
||||
public String getQueryWithCaretMarker() {
|
||||
final StringBuilder queryBuilder = new StringBuilder(getQuery());
|
||||
final StringBuilder queryWithCaretMarker = queryBuilder.insert(caretIndex, CARET_MARKER);
|
||||
return queryWithCaretMarker.toString();
|
||||
}
|
||||
public String getQueryWithCaretMarker() {
|
||||
final StringBuilder queryBuilder = new StringBuilder(getQuery());
|
||||
final StringBuilder queryWithCaretMarker = queryBuilder.insert(caretIndex, CARET_MARKER);
|
||||
return queryWithCaretMarker.toString();
|
||||
}
|
||||
|
||||
public ResultMode getResultMode() {
|
||||
return resultMode;
|
||||
}
|
||||
public ResultMode getResultMode() {
|
||||
return resultMode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,24 +7,24 @@ import java.util.List;
|
||||
|
||||
public class Result {
|
||||
|
||||
private final List<GroupResult> groupResults;
|
||||
private final List<GroupResult> groupResults;
|
||||
|
||||
public Result(final GroupResult... groupResults) {
|
||||
this(Arrays.asList(groupResults));
|
||||
}
|
||||
public Result(final GroupResult... groupResults) {
|
||||
this(Arrays.asList(groupResults));
|
||||
}
|
||||
|
||||
public Result(final Collection<GroupResult> groupResults) {
|
||||
this.groupResults = new ArrayList<>(groupResults);
|
||||
}
|
||||
public Result(final Collection<GroupResult> groupResults) {
|
||||
this.groupResults = new ArrayList<>(groupResults);
|
||||
}
|
||||
|
||||
public GroupResult singleGroup() {
|
||||
if (groupResults.size() != 1) {
|
||||
throw new IllegalStateException("the result does not contain exactly one group");
|
||||
}
|
||||
return groupResults.get(0);
|
||||
}
|
||||
public GroupResult singleGroup() {
|
||||
if (groupResults.size() != 1) {
|
||||
throw new IllegalStateException("the result does not contain exactly one group");
|
||||
}
|
||||
return groupResults.get(0);
|
||||
}
|
||||
|
||||
public List<GroupResult> getGroups() {
|
||||
return new ArrayList<>(groupResults);
|
||||
}
|
||||
public List<GroupResult> getGroups() {
|
||||
return new ArrayList<>(groupResults);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package org.lucares.pdb.api;
|
||||
|
||||
public class RuntimeIOException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public RuntimeIOException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
public RuntimeIOException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,34 +7,34 @@ import java.nio.file.Path;
|
||||
*/
|
||||
public class StringCompressor {
|
||||
|
||||
private final UniqueStringIntegerPairs usip;
|
||||
private final UniqueStringIntegerPairs usip;
|
||||
|
||||
public StringCompressor(final UniqueStringIntegerPairs usip) throws RuntimeIOException {
|
||||
this.usip = usip;
|
||||
}
|
||||
public StringCompressor(final UniqueStringIntegerPairs usip) throws RuntimeIOException {
|
||||
this.usip = usip;
|
||||
}
|
||||
|
||||
public static StringCompressor create(final Path path) {
|
||||
final UniqueStringIntegerPairs mapsi = new UniqueStringIntegerPairs(path);
|
||||
return new StringCompressor(mapsi);
|
||||
}
|
||||
public static StringCompressor create(final Path path) {
|
||||
final UniqueStringIntegerPairs mapsi = new UniqueStringIntegerPairs(path);
|
||||
return new StringCompressor(mapsi);
|
||||
}
|
||||
|
||||
public int put(final String string) {
|
||||
public int put(final String string) {
|
||||
|
||||
return usip.computeIfAbsent(string, s -> usip.getHighestInteger() + 1);
|
||||
}
|
||||
return usip.computeIfAbsent(string, s -> usip.getHighestInteger() + 1);
|
||||
}
|
||||
|
||||
public int put(final byte[] bytes, final int start, final int endExclusive) {
|
||||
return usip.computeIfAbsent(bytes, start, endExclusive);
|
||||
}
|
||||
public int put(final byte[] bytes, final int start, final int endExclusive) {
|
||||
return usip.computeIfAbsent(bytes, start, endExclusive);
|
||||
}
|
||||
|
||||
public String get(final int integer) {
|
||||
public String get(final int integer) {
|
||||
|
||||
return usip.getKey(integer);
|
||||
}
|
||||
return usip.getKey(integer);
|
||||
}
|
||||
|
||||
public int getIfPresent(final String string) {
|
||||
final Integer integer = usip.get(string);
|
||||
return integer != null ? integer : -1;
|
||||
}
|
||||
public int getIfPresent(final String string) {
|
||||
final Integer integer = usip.get(string);
|
||||
return integer != null ? integer : -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,89 +6,89 @@ package org.lucares.pdb.api;
|
||||
* 'Sam' is the value.
|
||||
*/
|
||||
public class Tag implements Comparable<Tag> {
|
||||
private final int field;
|
||||
private final int field;
|
||||
|
||||
private final int value;
|
||||
private final int value;
|
||||
|
||||
/**
|
||||
* Create a new tag with field and value specified as int. See
|
||||
* {@link Tags#STRING_COMPRESSOR} for the mapping between Strings and ints.
|
||||
*
|
||||
* @param field the field as int
|
||||
* @param value the value as int
|
||||
*/
|
||||
public Tag(final int field, final int value) {
|
||||
this.field = field;
|
||||
this.value = value;
|
||||
}
|
||||
/**
|
||||
* Create a new tag with field and value specified as int. See
|
||||
* {@link Tags#STRING_COMPRESSOR} for the mapping between Strings and ints.
|
||||
*
|
||||
* @param field the field as int
|
||||
* @param value the value as int
|
||||
*/
|
||||
public Tag(final int field, final int value) {
|
||||
this.field = field;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Tag} for the given field and value.
|
||||
*
|
||||
* @param field the field
|
||||
* @param value the value
|
||||
*/
|
||||
public Tag(final String field, final String value) {
|
||||
this.field = field != null ? Tags.STRING_COMPRESSOR.getIfPresent(field) : -1;
|
||||
this.value = value != null ? Tags.STRING_COMPRESSOR.getIfPresent(value) : -1;
|
||||
}
|
||||
/**
|
||||
* Create a new {@link Tag} for the given field and value.
|
||||
*
|
||||
* @param field the field
|
||||
* @param value the value
|
||||
*/
|
||||
public Tag(final String field, final String value) {
|
||||
this.field = field != null ? Tags.STRING_COMPRESSOR.getIfPresent(field) : -1;
|
||||
this.value = value != null ? Tags.STRING_COMPRESSOR.getIfPresent(value) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final Tag o) {
|
||||
@Override
|
||||
public int compareTo(final Tag o) {
|
||||
|
||||
if (field != o.field) {
|
||||
return field - o.field;
|
||||
} else if (value != o.value) {
|
||||
return value - o.value;
|
||||
}
|
||||
if (field != o.field) {
|
||||
return field - o.field;
|
||||
} else if (value != o.value) {
|
||||
return value - o.value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getKey() {
|
||||
return field;
|
||||
}
|
||||
public int getKey() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public String getKeyAsString() {
|
||||
return Tags.STRING_COMPRESSOR.get(field);
|
||||
}
|
||||
public String getKeyAsString() {
|
||||
return Tags.STRING_COMPRESSOR.get(field);
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getValueAsString() {
|
||||
return Tags.STRING_COMPRESSOR.get(value);
|
||||
}
|
||||
public String getValueAsString() {
|
||||
return Tags.STRING_COMPRESSOR.get(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Tags.STRING_COMPRESSOR.get(field) + "=" + Tags.STRING_COMPRESSOR.get(value);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return Tags.STRING_COMPRESSOR.get(field) + "=" + Tags.STRING_COMPRESSOR.get(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + field;
|
||||
result = prime * result + value;
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + field;
|
||||
result = prime * result + value;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Tag other = (Tag) obj;
|
||||
if (field != other.field)
|
||||
return false;
|
||||
if (value != other.value)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Tag other = (Tag) obj;
|
||||
if (field != other.field)
|
||||
return false;
|
||||
if (value != other.value)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@ import java.util.Comparator;
|
||||
|
||||
public class TagByKeyAndValueComparator {
|
||||
|
||||
public static final Comparator<Tag> INSTANCE = Comparator.comparing(Tag::getKey).thenComparing(Tag::getValue);
|
||||
public static final Comparator<Tag> INSTANCE = Comparator.comparing(Tag::getKey).thenComparing(Tag::getValue);
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@ import java.util.Comparator;
|
||||
|
||||
public class TagByKeyComparator {
|
||||
|
||||
public static final Comparator<Tag> INSTANCE = Comparator.comparing(Tag::getKey);
|
||||
public static final Comparator<Tag> INSTANCE = Comparator.comparing(Tag::getKey);
|
||||
}
|
||||
|
||||
@@ -14,264 +14,264 @@ import org.lucares.utils.byteencoder.VariableByteEncoder;
|
||||
|
||||
public class Tags implements Comparable<Tags> {
|
||||
|
||||
public static StringCompressor STRING_COMPRESSOR = null;
|
||||
private static final byte[] EMPTY_BYTES = new byte[0];
|
||||
public static final Tags EMPTY = new Tags();
|
||||
public static StringCompressor STRING_COMPRESSOR = null;
|
||||
private static final byte[] EMPTY_BYTES = new byte[0];
|
||||
public static final Tags EMPTY = new Tags();
|
||||
|
||||
private final List<Tag> tags;
|
||||
private final List<Tag> tags;
|
||||
|
||||
public Tags() {
|
||||
tags = new ArrayList<>();
|
||||
}
|
||||
public Tags() {
|
||||
tags = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Tags(final List<Tag> tags) {
|
||||
Collections.sort(tags, TagByKeyAndValueComparator.INSTANCE);
|
||||
this.tags = tags;
|
||||
}
|
||||
public Tags(final List<Tag> tags) {
|
||||
Collections.sort(tags, TagByKeyAndValueComparator.INSTANCE);
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public static Tags create(final List<Tag> tags) {
|
||||
public static Tags create(final List<Tag> tags) {
|
||||
|
||||
return new Tags(tags);
|
||||
}
|
||||
return new Tags(tags);
|
||||
}
|
||||
|
||||
public static Tags create() {
|
||||
return EMPTY;
|
||||
}
|
||||
public static Tags create() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
public static Tags create(final int key, final int value) {
|
||||
public static Tags create(final int key, final int value) {
|
||||
|
||||
return TagsBuilder.create().add(key, value).build();
|
||||
}
|
||||
return TagsBuilder.create().add(key, value).build();
|
||||
}
|
||||
|
||||
public static Tags create(final int key1, final int value1, final int key2, final int value2) {
|
||||
public static Tags create(final int key1, final int value1, final int key2, final int value2) {
|
||||
|
||||
final Tags result = TagsBuilder.create().add(key1, value1).add(key2, value2).build();
|
||||
return result;
|
||||
}
|
||||
final Tags result = TagsBuilder.create().add(key1, value1).add(key2, value2).build();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Tags create(final int key1, final int value1, final int key2, final int value2, final int key3,
|
||||
final int value3) {
|
||||
final Tags result = TagsBuilder.create().add(key1, value1).add(key2, value2).add(key3, value3).build();
|
||||
return result;
|
||||
}
|
||||
public static Tags create(final int key1, final int value1, final int key2, final int value2, final int key3,
|
||||
final int value3) {
|
||||
final Tags result = TagsBuilder.create().add(key1, value1).add(key2, value2).add(key3, value3).build();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Tags createAndAddToDictionary(final String key, final String value) {
|
||||
public static Tags createAndAddToDictionary(final String key, final String value) {
|
||||
|
||||
return TagsBuilder.create().addAndAddToDictionary(key, value).build();
|
||||
}
|
||||
return TagsBuilder.create().addAndAddToDictionary(key, value).build();
|
||||
}
|
||||
|
||||
public static Tags createAndAddToDictionary(final String key1, final String value1, final String key2,
|
||||
final String value2) {
|
||||
public static Tags createAndAddToDictionary(final String key1, final String value1, final String key2,
|
||||
final String value2) {
|
||||
|
||||
final Tags result = TagsBuilder.create().addAndAddToDictionary(key1, value1).addAndAddToDictionary(key2, value2)
|
||||
.build();
|
||||
return result;
|
||||
}
|
||||
final Tags result = TagsBuilder.create().addAndAddToDictionary(key1, value1).addAndAddToDictionary(key2, value2)
|
||||
.build();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Tags createAndAddToDictionary(final String key1, final String value1, final String key2,
|
||||
final String value2, final String key3, final String value3) {
|
||||
final Tags result = TagsBuilder.create().addAndAddToDictionary(key1, value1).addAndAddToDictionary(key2, value2)
|
||||
.addAndAddToDictionary(key3, value3).build();
|
||||
return result;
|
||||
}
|
||||
public static Tags createAndAddToDictionary(final String key1, final String value1, final String key2,
|
||||
final String value2, final String key3, final String value3) {
|
||||
final Tags result = TagsBuilder.create().addAndAddToDictionary(key1, value1).addAndAddToDictionary(key2, value2)
|
||||
.addAndAddToDictionary(key3, value3).build();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Tags createAndAddToDictionary(final String key1, final String value1, final String key2,
|
||||
final String value2, final String key3, final String value3, final String key4, final String value4) {
|
||||
final Tags result = TagsBuilder.create().addAndAddToDictionary(key1, value1).addAndAddToDictionary(key2, value2)
|
||||
.addAndAddToDictionary(key3, value3).addAndAddToDictionary(key4, value4).build();
|
||||
return result;
|
||||
}
|
||||
public static Tags createAndAddToDictionary(final String key1, final String value1, final String key2,
|
||||
final String value2, final String key3, final String value3, final String key4, final String value4) {
|
||||
final Tags result = TagsBuilder.create().addAndAddToDictionary(key1, value1).addAndAddToDictionary(key2, value2)
|
||||
.addAndAddToDictionary(key3, value3).addAndAddToDictionary(key4, value4).build();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Tags fromBytes(final byte[] bytes) {
|
||||
final List<Tag> result = new ArrayList<>();
|
||||
public static Tags fromBytes(final byte[] bytes) {
|
||||
final List<Tag> result = new ArrayList<>();
|
||||
|
||||
final LongList keyValuesAsLongs = VariableByteEncoder.decode(bytes);
|
||||
final LongList keyValuesAsLongs = VariableByteEncoder.decode(bytes);
|
||||
|
||||
for (int i = 0; i < keyValuesAsLongs.size(); i += 2) {
|
||||
for (int i = 0; i < keyValuesAsLongs.size(); i += 2) {
|
||||
|
||||
final long keyAsLong = keyValuesAsLongs.get(i);
|
||||
final long valueAsLong = keyValuesAsLongs.get(i + 1);
|
||||
final long keyAsLong = keyValuesAsLongs.get(i);
|
||||
final long valueAsLong = keyValuesAsLongs.get(i + 1);
|
||||
|
||||
final int key = (int) keyAsLong;
|
||||
final int value = (int) valueAsLong;
|
||||
result.add(new Tag(key, value));
|
||||
}
|
||||
final int key = (int) keyAsLong;
|
||||
final int value = (int) valueAsLong;
|
||||
result.add(new Tag(key, value));
|
||||
}
|
||||
|
||||
return new Tags(result);
|
||||
}
|
||||
return new Tags(result);
|
||||
}
|
||||
|
||||
public byte[] toBytes() {
|
||||
final byte[] result;
|
||||
public byte[] toBytes() {
|
||||
final byte[] result;
|
||||
|
||||
if (tags.size() > 0) {
|
||||
final LongList keyValuesAsLongs = new LongList(tags.size() * 2);
|
||||
for (final Tag tag : tags) {
|
||||
final long keyAsLong = tag.getKey();
|
||||
final long valueAsLong = tag.getValue();
|
||||
if (tags.size() > 0) {
|
||||
final LongList keyValuesAsLongs = new LongList(tags.size() * 2);
|
||||
for (final Tag tag : tags) {
|
||||
final long keyAsLong = tag.getKey();
|
||||
final long valueAsLong = tag.getValue();
|
||||
|
||||
keyValuesAsLongs.add(keyAsLong);
|
||||
keyValuesAsLongs.add(valueAsLong);
|
||||
}
|
||||
keyValuesAsLongs.add(keyAsLong);
|
||||
keyValuesAsLongs.add(valueAsLong);
|
||||
}
|
||||
|
||||
result = VariableByteEncoder.encode(keyValuesAsLongs);
|
||||
} else {
|
||||
result = EMPTY_BYTES;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
result = VariableByteEncoder.encode(keyValuesAsLongs);
|
||||
} else {
|
||||
result = EMPTY_BYTES;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final Tags o) {
|
||||
@Override
|
||||
public int compareTo(final Tags o) {
|
||||
|
||||
if (tags.size() != o.tags.size()) {
|
||||
return tags.size() - o.tags.size();
|
||||
} else {
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
final int compareResult = tags.get(i).compareTo(o.tags.get(i));
|
||||
if (compareResult != 0) {
|
||||
return compareResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tags.size() != o.tags.size()) {
|
||||
return tags.size() - o.tags.size();
|
||||
} else {
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
final int compareResult = tags.get(i).compareTo(o.tags.get(i));
|
||||
if (compareResult != 0) {
|
||||
return compareResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getValue(final String key) {
|
||||
final Tag needle = new Tag(STRING_COMPRESSOR.put(key), 0);
|
||||
public String getValue(final String key) {
|
||||
final Tag needle = new Tag(STRING_COMPRESSOR.put(key), 0);
|
||||
|
||||
final int index = Collections.binarySearch(tags, needle, TagByKeyComparator.INSTANCE);
|
||||
if (index >= 0) {
|
||||
final Tag tag = tags.get(index);
|
||||
return STRING_COMPRESSOR.get(tag.getValue());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final int index = Collections.binarySearch(tags, needle, TagByKeyComparator.INSTANCE);
|
||||
if (index >= 0) {
|
||||
final Tag tag = tags.get(index);
|
||||
return STRING_COMPRESSOR.get(tag.getValue());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getValueAsInt(final String key) {
|
||||
final Tag needle = new Tag(STRING_COMPRESSOR.put(key), 0);
|
||||
public int getValueAsInt(final String key) {
|
||||
final Tag needle = new Tag(STRING_COMPRESSOR.put(key), 0);
|
||||
|
||||
final int index = Collections.binarySearch(tags, needle, TagByKeyComparator.INSTANCE);
|
||||
if (index >= 0) {
|
||||
final Tag tag = tags.get(index);
|
||||
return tag.getValue();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
final int index = Collections.binarySearch(tags, needle, TagByKeyComparator.INSTANCE);
|
||||
if (index >= 0) {
|
||||
final Tag tag = tags.get(index);
|
||||
return tag.getValue();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Set<String> getKeys() {
|
||||
final TreeSet<String> result = new TreeSet<>();
|
||||
for (final Tag tag : tags) {
|
||||
result.add(STRING_COMPRESSOR.get(tag.getKey()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public Set<String> getKeys() {
|
||||
final TreeSet<String> result = new TreeSet<>();
|
||||
for (final Tag tag : tags) {
|
||||
result.add(STRING_COMPRESSOR.get(tag.getKey()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public IntList getKeysAsInt() {
|
||||
final IntList result = new IntList();
|
||||
for (final Tag tag : tags) {
|
||||
result.add(tag.getKey());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public IntList getKeysAsInt() {
|
||||
final IntList result = new IntList();
|
||||
for (final Tag tag : tags) {
|
||||
result.add(tag.getKey());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Tag> toTags() {
|
||||
return Collections.unmodifiableList(tags);
|
||||
}
|
||||
public List<Tag> toTags() {
|
||||
return Collections.unmodifiableList(tags);
|
||||
}
|
||||
|
||||
public void forEach(final BiConsumer<String, String> keyValueConsumer) {
|
||||
public void forEach(final BiConsumer<String, String> keyValueConsumer) {
|
||||
|
||||
for (final Tag tag : tags) {
|
||||
final String key = STRING_COMPRESSOR.get(tag.getKey());
|
||||
final String value = STRING_COMPRESSOR.get(tag.getValue());
|
||||
keyValueConsumer.accept(key, value);
|
||||
}
|
||||
}
|
||||
for (final Tag tag : tags) {
|
||||
final String key = STRING_COMPRESSOR.get(tag.getKey());
|
||||
final String value = STRING_COMPRESSOR.get(tag.getValue());
|
||||
keyValueConsumer.accept(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public Tags mapTags(final Function<Tag, Tag> tagMapFuntion) {
|
||||
final List<Tag> mappedTags = new ArrayList<>(tags.size());
|
||||
for (final Tag tag : tags) {
|
||||
mappedTags.add(tagMapFuntion.apply(tag));
|
||||
}
|
||||
return Tags.create(mappedTags);
|
||||
}
|
||||
public Tags mapTags(final Function<Tag, Tag> tagMapFuntion) {
|
||||
final List<Tag> mappedTags = new ArrayList<>(tags.size());
|
||||
for (final Tag tag : tags) {
|
||||
mappedTags.add(tagMapFuntion.apply(tag));
|
||||
}
|
||||
return Tags.create(mappedTags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(tags);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(tags);
|
||||
}
|
||||
|
||||
public String toCsv() {
|
||||
final List<String> tagsAsStrings = new ArrayList<>();
|
||||
for (final Tag tag : tags) {
|
||||
tagsAsStrings.add(tag.getKeyAsString() + "=" + tag.getValueAsString());
|
||||
}
|
||||
public String toCsv() {
|
||||
final List<String> tagsAsStrings = new ArrayList<>();
|
||||
for (final Tag tag : tags) {
|
||||
tagsAsStrings.add(tag.getKeyAsString() + "=" + tag.getValueAsString());
|
||||
}
|
||||
|
||||
return String.join(",", tagsAsStrings);
|
||||
}
|
||||
return String.join(",", tagsAsStrings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((tags == null) ? 0 : tags.hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((tags == null) ? 0 : tags.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Tags other = (Tags) obj;
|
||||
if (tags == null) {
|
||||
if (other.tags != null)
|
||||
return false;
|
||||
} else if (!tags.equals(other.tags))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Tags other = (Tags) obj;
|
||||
if (tags == null) {
|
||||
if (other.tags != null)
|
||||
return false;
|
||||
} else if (!tags.equals(other.tags))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public Tags subset(final List<String> groupByFields) {
|
||||
public Tags subset(final List<String> groupByFields) {
|
||||
|
||||
final TagsBuilder result = TagsBuilder.create();
|
||||
final TagsBuilder result = TagsBuilder.create();
|
||||
|
||||
for (final String field : groupByFields) {
|
||||
final int value = getValueAsInt(field);
|
||||
for (final String field : groupByFields) {
|
||||
final int value = getValueAsInt(field);
|
||||
|
||||
if (value >= 0) {
|
||||
final int fieldAsInt = STRING_COMPRESSOR.getIfPresent(field);
|
||||
result.add(fieldAsInt, value);
|
||||
}
|
||||
}
|
||||
if (value >= 0) {
|
||||
final int fieldAsInt = STRING_COMPRESSOR.getIfPresent(field);
|
||||
result.add(fieldAsInt, value);
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return tags.isEmpty();
|
||||
}
|
||||
public boolean isEmpty() {
|
||||
return tags.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User facing readable representation
|
||||
*/
|
||||
public String asString() {
|
||||
/**
|
||||
* @return User facing readable representation
|
||||
*/
|
||||
public String asString() {
|
||||
|
||||
final StringBuilder result = new StringBuilder();
|
||||
final StringBuilder result = new StringBuilder();
|
||||
|
||||
for (final Tag tag : tags) {
|
||||
if (result.length() > 0) {
|
||||
result.append(", ");
|
||||
}
|
||||
for (final Tag tag : tags) {
|
||||
if (result.length() > 0) {
|
||||
result.append(", ");
|
||||
}
|
||||
|
||||
result.append(STRING_COMPRESSOR.get(tag.getKey()));
|
||||
result.append("=");
|
||||
result.append(STRING_COMPRESSOR.get(tag.getValue()));
|
||||
}
|
||||
result.append(STRING_COMPRESSOR.get(tag.getKey()));
|
||||
result.append("=");
|
||||
result.append(STRING_COMPRESSOR.get(tag.getValue()));
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,30 +5,30 @@ import java.util.List;
|
||||
|
||||
public class TagsBuilder {
|
||||
|
||||
final List<Tag> tags = new ArrayList<>();
|
||||
final List<Tag> tags = new ArrayList<>();
|
||||
|
||||
public static TagsBuilder create() {
|
||||
return new TagsBuilder();
|
||||
}
|
||||
public static TagsBuilder create() {
|
||||
return new TagsBuilder();
|
||||
}
|
||||
|
||||
public TagsBuilder add(final int key, final int value) {
|
||||
tags.add(new Tag(key, value));
|
||||
return this;
|
||||
}
|
||||
public TagsBuilder add(final int key, final int value) {
|
||||
tags.add(new Tag(key, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public TagsBuilder add(final String key, final String value) {
|
||||
final int keyAsInt = Tags.STRING_COMPRESSOR.getIfPresent(key);
|
||||
final int valueAsInt = Tags.STRING_COMPRESSOR.getIfPresent(value);
|
||||
return add(keyAsInt, valueAsInt);
|
||||
}
|
||||
public TagsBuilder add(final String key, final String value) {
|
||||
final int keyAsInt = Tags.STRING_COMPRESSOR.getIfPresent(key);
|
||||
final int valueAsInt = Tags.STRING_COMPRESSOR.getIfPresent(value);
|
||||
return add(keyAsInt, valueAsInt);
|
||||
}
|
||||
|
||||
public TagsBuilder addAndAddToDictionary(final String key, final String value) {
|
||||
final int keyAsInt = Tags.STRING_COMPRESSOR.put(key);
|
||||
final int valueAsInt = Tags.STRING_COMPRESSOR.put(value);
|
||||
return add(keyAsInt, valueAsInt);
|
||||
}
|
||||
public TagsBuilder addAndAddToDictionary(final String key, final String value) {
|
||||
final int keyAsInt = Tags.STRING_COMPRESSOR.put(key);
|
||||
final int valueAsInt = Tags.STRING_COMPRESSOR.put(value);
|
||||
return add(keyAsInt, valueAsInt);
|
||||
}
|
||||
|
||||
public Tags build() {
|
||||
return Tags.create(tags);
|
||||
}
|
||||
public Tags build() {
|
||||
return Tags.create(tags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,182 +31,182 @@ import java.util.regex.Pattern;
|
||||
* retrievals.
|
||||
*/
|
||||
public class UniqueStringIntegerPairs {
|
||||
private static final String SEPARATOR = "\t";
|
||||
private static final String SEPARATOR = "\t";
|
||||
|
||||
private static final boolean APPEND = true;
|
||||
private static final boolean APPEND = true;
|
||||
|
||||
private static final class ByteArray implements Comparable<ByteArray> {
|
||||
private final byte[] array;
|
||||
private final int start;
|
||||
private final int endExclusive;
|
||||
private static final class ByteArray implements Comparable<ByteArray> {
|
||||
private final byte[] array;
|
||||
private final int start;
|
||||
private final int endExclusive;
|
||||
|
||||
public ByteArray(final byte[] array, final int start, final int endExclusive) {
|
||||
super();
|
||||
this.array = array;
|
||||
this.start = start;
|
||||
this.endExclusive = endExclusive;
|
||||
}
|
||||
public ByteArray(final byte[] array, final int start, final int endExclusive) {
|
||||
super();
|
||||
this.array = array;
|
||||
this.start = start;
|
||||
this.endExclusive = endExclusive;
|
||||
}
|
||||
|
||||
public ByteArray(final byte[] bytes) {
|
||||
this.array = bytes;
|
||||
this.start = 0;
|
||||
this.endExclusive = bytes.length;
|
||||
}
|
||||
public ByteArray(final byte[] bytes) {
|
||||
this.array = bytes;
|
||||
this.start = 0;
|
||||
this.endExclusive = bytes.length;
|
||||
}
|
||||
|
||||
// custom hashcode!
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 1;
|
||||
final byte[] a = array;
|
||||
final int end = endExclusive;
|
||||
for (int i = start; i < end; i++) {
|
||||
result = 31 * result + a[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// custom hashcode!
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 1;
|
||||
final byte[] a = array;
|
||||
final int end = endExclusive;
|
||||
for (int i = start; i < end; i++) {
|
||||
result = 31 * result + a[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// custom equals!
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
final ByteArray other = (ByteArray) obj;
|
||||
if (!Arrays.equals(array, start, endExclusive, other.array, other.start, other.endExclusive))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// custom equals!
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
final ByteArray other = (ByteArray) obj;
|
||||
if (!Arrays.equals(array, start, endExclusive, other.array, other.start, other.endExclusive))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final ByteArray o) {
|
||||
return Arrays.compare(array, start, endExclusive, o.array, o.start, o.endExclusive);
|
||||
}
|
||||
@Override
|
||||
public int compareTo(final ByteArray o) {
|
||||
return Arrays.compare(array, start, endExclusive, o.array, o.start, o.endExclusive);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a string to an integer. E.g. "myLongValue" -> 123
|
||||
*/
|
||||
private final Map<String, Integer> stringToInt = new HashMap<>();
|
||||
/**
|
||||
* Maps a string to an integer. E.g. "myLongValue" -> 123
|
||||
*/
|
||||
private final Map<String, Integer> stringToInt = new HashMap<>();
|
||||
|
||||
private final Map<ByteArray, Integer> bytesToInt = new HashMap<>();
|
||||
private final Map<ByteArray, Integer> bytesToInt = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Maps an integer to a string. E.g. 123 -> "myLongValue"
|
||||
*/
|
||||
private final List<String> intToString = new ArrayList<>();
|
||||
/**
|
||||
* Maps an integer to a string. E.g. 123 -> "myLongValue"
|
||||
*/
|
||||
private final List<String> intToString = new ArrayList<>();
|
||||
|
||||
private final Path file;
|
||||
private final Path file;
|
||||
|
||||
public UniqueStringIntegerPairs() {
|
||||
this(null);
|
||||
}
|
||||
public UniqueStringIntegerPairs() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public UniqueStringIntegerPairs(final Path file) {
|
||||
this.file = file;
|
||||
if (file != null) {
|
||||
init(file);
|
||||
}
|
||||
}
|
||||
public UniqueStringIntegerPairs(final Path file) {
|
||||
this.file = file;
|
||||
if (file != null) {
|
||||
init(file);
|
||||
}
|
||||
}
|
||||
|
||||
private void init(final Path file) throws RuntimeIOException {
|
||||
private void init(final Path file) throws RuntimeIOException {
|
||||
|
||||
try {
|
||||
Files.createDirectories(file.getParent());
|
||||
if (!Files.exists(file)) {
|
||||
Files.createFile(file);
|
||||
}
|
||||
try {
|
||||
Files.createDirectories(file.getParent());
|
||||
if (!Files.exists(file)) {
|
||||
Files.createFile(file);
|
||||
}
|
||||
|
||||
try (final BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(new FileInputStream(file.toFile()), StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try (final BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(new FileInputStream(file.toFile()), StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
|
||||
final String[] tokens = line.split(Pattern.quote(SEPARATOR));
|
||||
final String[] tokens = line.split(Pattern.quote(SEPARATOR));
|
||||
|
||||
if (tokens.length == 2) {
|
||||
final String string = tokens[0];
|
||||
final int integer = Integer.parseInt(tokens[1]);
|
||||
intToStringPut(integer, string);
|
||||
stringToInt.put(string, integer);
|
||||
bytesToInt.put(new ByteArray(string.getBytes(StandardCharsets.UTF_8)), integer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeIOException(e);
|
||||
}
|
||||
}
|
||||
if (tokens.length == 2) {
|
||||
final String string = tokens[0];
|
||||
final int integer = Integer.parseInt(tokens[1]);
|
||||
intToStringPut(integer, string);
|
||||
stringToInt.put(string, integer);
|
||||
bytesToInt.put(new ByteArray(string.getBytes(StandardCharsets.UTF_8)), integer);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void intToStringPut(final int value, final String string) {
|
||||
if (intToString.size() <= value) {
|
||||
// list is not long enough -> grow list
|
||||
while (intToString.size() <= value) {
|
||||
intToString.add(null);
|
||||
}
|
||||
}
|
||||
intToString.set(value, string);
|
||||
}
|
||||
private void intToStringPut(final int value, final String string) {
|
||||
if (intToString.size() <= value) {
|
||||
// list is not long enough -> grow list
|
||||
while (intToString.size() <= value) {
|
||||
intToString.add(null);
|
||||
}
|
||||
}
|
||||
intToString.set(value, string);
|
||||
}
|
||||
|
||||
void put(final String string, final int integer) {
|
||||
void put(final String string, final int integer) {
|
||||
|
||||
if (stringToInt.containsKey(string) || (intToString.size() > integer && intToString.get(integer) != null)) {
|
||||
throw new IllegalArgumentException("Unique key constraint violation for (" + string + ", " + integer + ")");
|
||||
}
|
||||
if (file != null) {
|
||||
try (final Writer writer = new OutputStreamWriter(new FileOutputStream(file.toFile(), APPEND),
|
||||
StandardCharsets.UTF_8)) {
|
||||
if (stringToInt.containsKey(string) || (intToString.size() > integer && intToString.get(integer) != null)) {
|
||||
throw new IllegalArgumentException("Unique key constraint violation for (" + string + ", " + integer + ")");
|
||||
}
|
||||
if (file != null) {
|
||||
try (final Writer writer = new OutputStreamWriter(new FileOutputStream(file.toFile(), APPEND),
|
||||
StandardCharsets.UTF_8)) {
|
||||
|
||||
writer.write(string + SEPARATOR + integer + "\n");
|
||||
writer.write(string + SEPARATOR + integer + "\n");
|
||||
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeIOException(e);
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
intToStringPut(integer, string);
|
||||
stringToInt.put(string, integer);
|
||||
bytesToInt.put(new ByteArray(string.getBytes(StandardCharsets.UTF_8)), integer);
|
||||
}
|
||||
intToStringPut(integer, string);
|
||||
stringToInt.put(string, integer);
|
||||
bytesToInt.put(new ByteArray(string.getBytes(StandardCharsets.UTF_8)), integer);
|
||||
}
|
||||
|
||||
public Integer get(final String string) {
|
||||
public Integer get(final String string) {
|
||||
|
||||
return stringToInt.get(string);
|
||||
}
|
||||
return stringToInt.get(string);
|
||||
}
|
||||
|
||||
public String getKey(final int second) {
|
||||
return intToString.get(second);
|
||||
}
|
||||
public String getKey(final int second) {
|
||||
return intToString.get(second);
|
||||
}
|
||||
|
||||
public Integer getHighestInteger() {
|
||||
return intToString.size() == 0 ? -1 : intToString.size() - 1;
|
||||
}
|
||||
public Integer getHighestInteger() {
|
||||
return intToString.size() == 0 ? -1 : intToString.size() - 1;
|
||||
}
|
||||
|
||||
public Integer computeIfAbsent(final String string, final Function<String, Integer> mappingFunction) {
|
||||
if (!stringToInt.containsKey(string)) {
|
||||
synchronized (stringToInt) {
|
||||
if (!stringToInt.containsKey(string)) {
|
||||
final Integer second = mappingFunction.apply(string);
|
||||
put(string, second);
|
||||
}
|
||||
}
|
||||
}
|
||||
public Integer computeIfAbsent(final String string, final Function<String, Integer> mappingFunction) {
|
||||
if (!stringToInt.containsKey(string)) {
|
||||
synchronized (stringToInt) {
|
||||
if (!stringToInt.containsKey(string)) {
|
||||
final Integer second = mappingFunction.apply(string);
|
||||
put(string, second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stringToInt.get(string);
|
||||
}
|
||||
return stringToInt.get(string);
|
||||
}
|
||||
|
||||
public Integer computeIfAbsent(final byte[] bytes, final int start, final int endExclusive) {
|
||||
public Integer computeIfAbsent(final byte[] bytes, final int start, final int endExclusive) {
|
||||
|
||||
final ByteArray byteArray = new ByteArray(bytes, start, endExclusive);
|
||||
Integer result = bytesToInt.get(byteArray);
|
||||
if (result == null) {
|
||||
synchronized (stringToInt) {
|
||||
if (!bytesToInt.containsKey(byteArray)) {
|
||||
final String string = new String(bytes, start, endExclusive - start, StandardCharsets.UTF_8);
|
||||
final Integer integer = intToString.size();
|
||||
put(string, integer);
|
||||
}
|
||||
result = bytesToInt.get(byteArray);
|
||||
}
|
||||
}
|
||||
final ByteArray byteArray = new ByteArray(bytes, start, endExclusive);
|
||||
Integer result = bytesToInt.get(byteArray);
|
||||
if (result == null) {
|
||||
synchronized (stringToInt) {
|
||||
if (!bytesToInt.containsKey(byteArray)) {
|
||||
final String string = new String(bytes, start, endExclusive - start, StandardCharsets.UTF_8);
|
||||
final Integer integer = intToString.size();
|
||||
put(string, integer);
|
||||
}
|
||||
result = bytesToInt.get(byteArray);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user