package fr.neamar.kiss.pojo;
import android.util.Pair;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import fr.neamar.kiss.normalizer.StringNormalizer;
public abstract class Pojo {
// Globally unique ID.
// Usually starts with provider scheme, e.g. "app://" or "contact://" to
// ensure unique constraint
public String id = "(none)";
// Name for this pojo, e.g. app name
public String name = "";
// Lower-cased name, for faster search
public String nameNormalized = "";
// Name displayed on the screen, may contain HTML (for instance, to put
// query text in blue)
public String displayName = "";
// How relevant is this record ? The higher, the most probable it will be
// displayed
public int relevance = 0;
// Array that contains the non-normalized positions for every normalized
// character entry
private int[] namePositionMap = null;
// Tags assigned to this pojo
public String tags;
// Variable to store the formated (user selection in bold) tag
public String displayTags = "";
/**
* Map a position in the normalized name to a position in the standard name string
*
* @param position Position in normalized name
* @return Position in non-normalized string
*/
public int mapPosition(int position) {
if (this.namePositionMap != null) {
if (position < this.namePositionMap.length) {
return this.namePositionMap[position];
} else {
return this.name.length();
}
} else {
// No mapping defined
if (position < this.name.length()) {
return position;
} else {
return this.name.length();
}
}
}
/**
* Set the user-displayable name of this container
* <p/>
* When this method a searchable version of the name will be generated for the name and stored
* as `nameNormalized`. Additionally a mapping from the positions in the searchable name
* to the positions in the displayable name will be stored (as `namePositionMap`).
*
* @param name User-friendly name of this container
*/
public void setName(String name) {
// Set the actual user-friendly name
this.name = name;
if (name != null) {
this.name = this.name.replaceAll("<", "<");
// Normalize name for faster searching
Pair<String, int[]> normalized = StringNormalizer.normalizeWithMap(this.name);
this.nameNormalized = normalized.first;
this.namePositionMap = normalized.second;
}
}
/**
* Set which area of the display name should marked as highlighted in the `displayName`
* attribute
* <p/>
* The start and end positions should be offsets in the normalized string and will be converted
* to their non-normalized positions before they are used.
*
* @param positionNormalizedStart Highlighting start position in normalized name
* @param positionNormalizedEnd Highlighting end position in normalized name
*/
public void setDisplayNameHighlightRegion(int positionNormalizedStart, int positionNormalizedEnd) {
int positionStart = this.mapPosition(positionNormalizedStart);
int positionEnd = this.mapPosition(positionNormalizedEnd);
this.displayName = this.name.substring(0, positionStart)
+ '{' + this.name.substring(positionStart, positionEnd) + '}'
+ this.name.substring(positionEnd);
}
public void setDisplayNameHighlightRegion(List<Pair<Integer, Integer>> positions) {
this.displayName = "";
int lastPositionEnd = 0;
for (Pair<Integer, Integer> position : positions) {
int positionStart = this.mapPosition(position.first);
int positionEnd = this.mapPosition(position.second);
this.displayName += this.name.substring(lastPositionEnd, positionStart)
+ '{' + this.name.substring(positionStart, positionEnd) + '}';
lastPositionEnd = positionEnd;
}
this.displayName += this.name.substring(lastPositionEnd);
}
public void setTagHighlight(int positionStart, int positionEnd) {
this.displayTags = this.tags.substring(0, positionStart)
+ '{' + this.tags.substring(positionStart, positionEnd) + '}'
+ this.tags.substring(positionEnd);
}
/**
* Item comparer for sorting Pojos based on their human-readable text
* description
*/
public static class NameComparator implements Comparator<Pojo> {
private final Collator collator = Collator.getInstance();
public final int compare(Pojo a, Pojo b) {
int result = this.collator.compare(a.name, b.name);
if(result == 0) {
// Fall back to ID-based ordering if names match exactly
result = this.collator.compare(a.id, b.id);
}
return result;
}
}
}