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

com.imsweb.validation.entities.ContextTableIndex Maven / Gradle / Ivy

/*
 * Copyright (C) 2017 Information Management Services, Inc.
 */
package com.imsweb.validation.entities;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;

/**
 * This class represent a table index in the Genedits framework.
 * 

* When a value is found, the row index in the corresponding table is returned; this is a 0-based value that doesn't take into account the table headers * (so if value 0 is returned, it means the first row of data in the table). */ public class ContextTableIndex { // index name private String _name; // data structure used for unique keys private NavigableMap _uniqueKeysData; // data structure used for non-unique keys private List> _nonUniqueKeysData; /** * Constructor * @param name index name * @param table parent table * @param indexedColumns columns (header) that make up this index */ public ContextTableIndex(String name, ContextTable table, List indexedColumns) { _name = name; List colIdx = new ArrayList<>(); for (String column : indexedColumns) { int idx = table.getHeaders().indexOf(column.trim()); if (idx == -1) throw new RuntimeException("Unable to find column \"" + column + "\" to index on table \"" + table.getName() + "\""); colIdx.add(idx); } Set keysAdded = new HashSet<>(); boolean keysAreUnique = true; Pattern pattern = Pattern.compile("\\s+$"); _nonUniqueKeysData = new ArrayList<>(); for (int rowIdx = 0; rowIdx < table.getData().size(); rowIdx++) { List row = table.getData().get(rowIdx); // I *think* the index keys are right-trimmed in Genedits (I can't really prove it though) String key = pattern.matcher(StringUtils.join(colIdx.stream().map(row::get).toArray(String[]::new))).replaceAll(""); if (keysAdded.contains(key)) keysAreUnique = false; keysAdded.add(key); _nonUniqueKeysData.add(new ImmutablePair<>(key, rowIdx)); } if (keysAreUnique) { _uniqueKeysData = new TreeMap<>(); for (Pair pair : _nonUniqueKeysData) _uniqueKeysData.put(pair.getKey(), pair.getValue()); _nonUniqueKeysData = null; } else _nonUniqueKeysData.sort(Comparator.comparing((Function, String>)Pair::getKey).thenComparingInt(Pair::getValue)); } /** * Returns the row number of the requested value in the parent table, -1 if not found. * @param value value to look for * @return corresponding row number in the parent table, -1 if not found */ public int find(String value) { int result = -1; if (_uniqueKeysData != null) result = _uniqueKeysData.getOrDefault(value, -1); else { for (Pair pair : _nonUniqueKeysData) { int comp = value.compareTo(pair.getKey()); if (comp == 0) { result = pair.getValue(); break; } else if (comp < 0) break; // values in the list are sorted, so we can stop the iteration sooner... } } return result; } /** * Returns the number of the first row that is equals or greater than the requested value, -1 if not found. * @param value value to look for * @return corresponding row number in the parent table, -1 if not found */ public int findFloor(String value) { int result = -1; // if the value is smaller than the smaller index key, return not found (-1) // if the value is greater than the greatest index key, return the last index value // if the value is equals to an index key, return that index value // if a value is not equals to any index keys (but within the range of the keys), return the value of the first key that is greater than the value if (_uniqueKeysData != null) { if (value.compareTo(_uniqueKeysData.firstKey()) >= 0) { Entry entry = _uniqueKeysData.floorEntry(value); if (entry != null) result = entry.getValue(); else if (value.compareTo(_uniqueKeysData.lastKey()) > 0) result = _uniqueKeysData.lastEntry().getValue(); } } else { if (value.compareTo(_nonUniqueKeysData.get(0).getKey()) >= 0) { for (int indexIdx = 0; indexIdx < _nonUniqueKeysData.size(); indexIdx++) { Pair pair = _nonUniqueKeysData.get(indexIdx); int comp = value.compareTo(pair.getKey()); if (comp == 0) { result = pair.getValue(); break; } else if (comp < 0) { result = _nonUniqueKeysData.get(indexIdx - 1).getValue(); break; } } if (result == -1) if (value.compareTo(_nonUniqueKeysData.get(_nonUniqueKeysData.size() - 1).getKey()) > 0) result = _nonUniqueKeysData.get(_nonUniqueKeysData.size() - 1).getValue(); } } return result; } /** * Returns true if the index has unique values, false otherwise. * @return true if the index has unique values, false otherwise. */ public boolean hasUniqueKeys() { return _uniqueKeysData != null; } @Override public String toString() { return _name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ContextTableIndex that = (ContextTableIndex)o; return Objects.equals(_name, that._name); } @Override public int hashCode() { return Objects.hash(_name); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy