001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.tagging.ac;
003
004/**
005 * Describes the priority of an item in an autocompletion list.
006 * The selected flag is currently only used in plugins.
007 *
008 * Instances of this class are not modifiable.
009 * @since 1762
010 */
011public class AutoCompletionItemPriority implements Comparable<AutoCompletionItemPriority> {
012
013    /**
014     * Indicates, that the value is standard and it is found in the data.
015     * This has higher priority than some arbitrary standard value that is
016     * usually not used by the user.
017     */
018    public static final AutoCompletionItemPriority IS_IN_STANDARD_AND_IN_DATASET = new AutoCompletionItemPriority(true, true, false);
019
020    /**
021     * Indicates that this is an arbitrary value from the data set, i.e.
022     * the value of a tag name=*.
023     */
024    public static final AutoCompletionItemPriority IS_IN_DATASET = new AutoCompletionItemPriority(true, false, false);
025
026    /**
027     * Indicates that this is a standard value, i.e. a standard tag name
028     * or a standard value for a given tag name (from the presets).
029     */
030    public static final AutoCompletionItemPriority IS_IN_STANDARD = new AutoCompletionItemPriority(false, true, false);
031
032    /**
033     * Indicates that this is a value from a selected object.
034     */
035    public static final AutoCompletionItemPriority IS_IN_SELECTION = new AutoCompletionItemPriority(false, false, true);
036
037    /** Unknown priority. This is the lowest priority. */
038    public static final AutoCompletionItemPriority UNKNOWN = new AutoCompletionItemPriority(false, false, false);
039
040    private static final int NO_USER_INPUT = Integer.MAX_VALUE;
041
042    private final int userInput;
043    private final boolean inDataSet;
044    private final boolean inStandard;
045    private final boolean selected;
046
047    /**
048     * Constructs a new {@code AutoCompletionItemPriority}.
049     *
050     * @param inDataSet true, if the item is found in the currently active data layer
051     * @param inStandard true, if the item is a standard tag, e.g. from the presets
052     * @param selected true, if it is found on an object that is currently selected
053     * @param userInput null, if the user hasn't entered this tag so far. A number when
054     * the tag key / value has been entered by the user before. A lower number means
055     * this happened more recently and beats a higher number in priority.
056     */
057    public AutoCompletionItemPriority(boolean inDataSet, boolean inStandard, boolean selected, Integer userInput) {
058        this.inDataSet = inDataSet;
059        this.inStandard = inStandard;
060        this.selected = selected;
061        this.userInput = userInput == null ? NO_USER_INPUT : userInput;
062    }
063
064    /**
065     * Constructs a new {@code AutoCompletionItemPriority}.
066     *
067     * @param inDataSet true, if the item is found in the currently active data layer
068     * @param inStandard true, if the item is a standard tag, e.g. from the presets
069     * @param selected true, if it is found on an object that is currently selected
070     */
071    public AutoCompletionItemPriority(boolean inDataSet, boolean inStandard, boolean selected) {
072        this(inDataSet, inStandard, selected, NO_USER_INPUT);
073    }
074
075    /**
076     * Determines if the item is found in the currently active data layer.
077     * @return {@code true} if the item is found in the currently active data layer
078     */
079    public boolean isInDataSet() {
080        return inDataSet;
081    }
082
083    /**
084     * Determines if the item is a standard tag, e.g. from the presets.
085     * @return {@code true} if the item is a standard tag, e.g. from the presets
086     */
087    public boolean isInStandard() {
088        return inStandard;
089    }
090
091    /**
092     * Determines if it is found on an object that is currently selected.
093     * @return {@code true} if it is found on an object that is currently selected
094     */
095    public boolean isSelected() {
096        return selected;
097    }
098
099    /**
100     * Returns a number when the tag key / value has been entered by the user before.
101     * A lower number means this happened more recently and beats a higher number in priority.
102     * @return a number when the tag key / value has been entered by the user before.
103     *         {@code null}, if the user hasn't entered this tag so far.
104     */
105    public Integer getUserInput() {
106        return userInput == NO_USER_INPUT ? null : userInput;
107    }
108
109    /**
110     * Imposes an ordering on the priorities.
111     * Currently, being in the current DataSet is worth more than being in the Presets.
112     */
113    @Override
114    public int compareTo(AutoCompletionItemPriority other) {
115        int ui = Integer.compare(other.userInput, userInput);
116        if (ui != 0)
117            return ui;
118
119        int sel = Boolean.compare(selected, other.selected);
120        if (sel != 0)
121            return sel;
122
123        int ds = Boolean.compare(inDataSet, other.inDataSet);
124        if (ds != 0)
125            return ds;
126
127        int std = Boolean.compare(inStandard, other.inStandard);
128        if (std != 0)
129            return std;
130
131        return 0;
132    }
133
134    /**
135     * Merges two priorities.
136     * The resulting priority is always &gt;= the original ones.
137     * @param other other priority
138     * @return the merged priority
139     */
140    public AutoCompletionItemPriority mergeWith(AutoCompletionItemPriority other) {
141        return new AutoCompletionItemPriority(
142                inDataSet || other.inDataSet,
143                inStandard || other.inStandard,
144                selected || other.selected,
145                Math.min(userInput, other.userInput));
146    }
147
148    @Override
149    public String toString() {
150        return String.format("<Priority; userInput: %s, inDataSet: %b, inStandard: %b, selected: %b>",
151                userInput == NO_USER_INPUT ? "no" : Integer.toString(userInput), inDataSet, inStandard, selected);
152    }
153}