001package org.unix4j.util.sort;
002
003import org.unix4j.line.Line;
004import org.unix4j.util.sort.TrimBlanksStringComparator.Mode;
005
006import java.text.Collator;
007import java.util.Comparator;
008import java.util.Objects;
009
010/**
011 * Comparator for a {@link Line} without line ending; forwards the comparison of
012 * the content string to a delegate string comparator. Some constants exist for
013 * common line comparators.
014 */
015public class LineComparator implements Comparator<Line> {
016
017        private final Comparator<? super String> comparator;
018
019        /**
020         * Constructor for a line comparator that uses the specified
021         * {@code comparator} to compare the {@link Line#getContent() content}
022         * string of the line.
023         * 
024         * @param comparator
025         *            the comparator used to compare the line content string
026         */
027        public LineComparator(Comparator<? super String> comparator) {
028                this.comparator = Objects.requireNonNull(comparator);
029        }
030
031        /**
032         * Constructor with options for line comparision.
033         *
034         * @param ignoreCase                    true to ignore case, false for case sensitive comparison
035         * @param ignoreLeadingBlanks   true if leading blanks shall be trimmed before the comparison
036         * @param onlyDictionaryChars   true if only blanks and alphanumeric characters shall be considered
037     */
038        public LineComparator(boolean ignoreCase, boolean ignoreLeadingBlanks, boolean onlyDictionaryChars) {
039                this(getCollator(ignoreCase, ignoreLeadingBlanks, onlyDictionaryChars));
040        }
041
042        @Override
043        public int compare(Line line1, Line line2) {
044                return comparator.compare(line1.getContent(), line2.getContent());
045        }
046
047        private static Comparator<? super String> getCollator(boolean ignoreCase, boolean ignoreLeadingBlanks, boolean onlyDictionaryChars) {
048                final Collator collator = Collator.getInstance();
049                collator.setStrength(ignoreCase ? Collator.SECONDARY : Math.max(Collator.TERTIARY, collator.getStrength()));
050                final Comparator<? super String> comparator;
051                if (ignoreLeadingBlanks) {
052                        comparator = new TrimBlanksStringComparator(Mode.Leading, collator);
053                } else {
054                        comparator = collator;
055                }
056                if (onlyDictionaryChars) {
057                        return new DictionaryStringComparator(comparator);
058                }
059                return comparator;
060        };
061}