X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=src%2Fcom%2Fhughes%2Fandroid%2Fdictionary%2Fengine%2FPairEntry.java;h=a0bcfeeac0a8e793071149cb2fc3e5bc456b222d;hb=5f7b259669237dad4cbfdec8536537815846979b;hp=7d30310bb9572bc3ac9072a4d2034524b7dafd4b;hpb=4b031e28dc75b564ae405ea4ce6d323dff75898c;p=Dictionary.git diff --git a/src/com/hughes/android/dictionary/engine/PairEntry.java b/src/com/hughes/android/dictionary/engine/PairEntry.java index 7d30310..a0bcfee 100644 --- a/src/com/hughes/android/dictionary/engine/PairEntry.java +++ b/src/com/hughes/android/dictionary/engine/PairEntry.java @@ -1,118 +1,279 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package com.hughes.android.dictionary.engine; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.PrintStream; -import java.io.RandomAccessFile; - -import com.hughes.util.raf.RAFSerializable; -import com.hughes.util.raf.RAFSerializer; - -public class PairEntry extends Entry implements RAFSerializable { - - public static final class Pair { - - public final String lang1; - public final String lang2; - - public Pair(final String lang1, final String lang2) { - this.lang1 = lang1; - this.lang2 = lang2; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; + +import com.hughes.util.StringUtil; +import com.hughes.util.raf.RAFListSerializerSkippable; +import com.ibm.icu.text.Transliterator; + +public class PairEntry extends AbstractEntry implements Comparable { + + public final List pairs; + + public PairEntry(final EntrySource entrySource) { + super(entrySource); + pairs = new ArrayList<>(1); } - - public String toString() { - return lang1 + " :: " + lang2; + + public PairEntry(final EntrySource entrySource, final String lang1, final String lang2) { + this(entrySource); + this.pairs.add(new Pair(lang1, lang2)); } - public String toStringTab() { - return lang1 + "\t" + lang2; + public PairEntry(final Dictionary dictionary, final DataInput raf, final int index) + throws IOException { + super(dictionary, raf, index); + final int size = dictionary.dictFileVersion >= 7 ? StringUtil.readVarInt(raf) : raf.readInt(); + // Use singletonList for better performance in common case + if (size == 1) pairs = Collections.singletonList(new Pair(raf.readUTF(), raf.readUTF())); + else + { + pairs = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + pairs.add(new Pair(raf.readUTF(), raf.readUTF())); + } + } } - } - - public final Pair[] pairs; - - public PairEntry(final Pair[] pairs) { - this.pairs = pairs; - } - - public PairEntry(final RandomAccessFile raf) throws IOException { - pairs = new Pair[raf.readInt()]; - for (int i = 0; i < pairs.length; ++i) { - pairs[i] = new Pair(raf.readUTF(), raf.readUTF()); + @Override + public void write(DataOutput raf) throws IOException { + super.write(raf); + StringUtil.writeVarInt(raf, pairs.size()); + for (Pair p : pairs) { + assert p.lang1.length() > 0; + raf.writeUTF(p.lang1); + raf.writeUTF(p.lang2); + } } - } - @Override - public void write(RandomAccessFile raf) throws IOException { - // TODO: this could be a short. - raf.writeInt(pairs.length); - for (int i = 0; i < pairs.length; ++i) { - raf.writeUTF(pairs[i].lang1); - raf.writeUTF(pairs[i].lang2); + + static final class Serializer implements RAFListSerializerSkippable { + + final Dictionary dictionary; + + Serializer(Dictionary dictionary) { + this.dictionary = dictionary; + } + + @Override + public PairEntry read(DataInput raf, int index) throws IOException { + return new PairEntry(dictionary, raf, index); + } + + @Override + public void skip(DataInput raf, int index) throws IOException { + final int size; + if (dictionary.dictFileVersion >= 7) + { + StringUtil.readVarInt(raf); + size = StringUtil.readVarInt(raf); + } + else + { + raf.skipBytes(2); + size = raf.readInt(); + } + for (int i = 0; i < 2*size; ++i) { + int l = raf.readUnsignedShort(); + raf.skipBytes(l); + } + } + + @Override + public void write(DataOutput raf, PairEntry t) throws IOException { + t.write(raf); + } } - } - - static final RAFSerializer SERIALIZER = new RAFSerializer() { + @Override - public PairEntry read(RandomAccessFile raf) throws IOException { - return new PairEntry(raf); + public void addToDictionary(final Dictionary dictionary) { + assert index == -1; + dictionary.pairEntries.add(this); + index = dictionary.pairEntries.size() - 1; } @Override - public void write(RandomAccessFile raf, PairEntry t) throws IOException { - t.write(raf); - } - }; - - - public static class Row extends RowBase { - - Row(final RandomAccessFile raf, final int thisRowIndex, - final Index index) throws IOException { - super(raf, thisRowIndex, index); + public RowBase CreateRow(int rowIndex, Index dictionaryIndex) { + return new Row(this.index, rowIndex, dictionaryIndex); } - Row(final int referenceIndex, final int thisRowIndex, - final Index index) { - super(referenceIndex, thisRowIndex, index); + // -------------------------------------------------------------------- + + public static class Row extends RowBase { + + Row(final DataInput raf, final int thisRowIndex, + final Index index, int extra) throws IOException { + super(raf, thisRowIndex, index, extra); + } + + Row(final int referenceIndex, final int thisRowIndex, + final Index index) { + super(referenceIndex, thisRowIndex, index); + } + + @Override + public String toString() { + return getRawText(false); + } + + public PairEntry getEntry() { + return index.dict.pairEntries.get(referenceIndex); + } + + @Override + public void print(PrintStream out) { + final PairEntry pairEntry = getEntry(); + for (int i = 0; i < pairEntry.pairs.size(); ++i) { + out.print((i == 0 ? " " : " ") + pairEntry.pairs.get(i)); + out.println(); + } + } + + @Override + public String getRawText(boolean compact) { + final PairEntry pairEntry = getEntry(); + return pairEntry.getRawText(compact); + } + + @Override + public RowMatchType matches(final List searchTokens, + final Pattern orderedMatchPattern, final Transliterator normalizer, + final boolean swapPairEntries) { + final int side = swapPairEntries ? 1 : 0; + final List pairs = getEntry().pairs; + final String[] pairSides = new String[pairs.size()]; + for (int i = 0; i < pairs.size(); ++i) { + pairSides[i] = normalizer.transform(pairs.get(i).get(side)); + } + for (int i = searchTokens.size() - 1; i >= 0; --i) { + final String searchToken = searchTokens.get(i); + boolean found = false; + for (final String pairSide : pairSides) { + found |= pairSide.contains(searchToken); + } + if (!found) { + return RowMatchType.NO_MATCH; + } + } + for (final String pairSide : pairSides) { + if (orderedMatchPattern.matcher(pairSide).find()) { + return RowMatchType.ORDERED_MATCH; + } + } + return RowMatchType.BAG_OF_WORDS_MATCH; + } + + @Override + public int getSideLength(boolean swapPairEntries) { + int result = 0; + final int side = swapPairEntries ? 1 : 0; + for (final Pair pair : getEntry().pairs) { + result += pair.get(side).length(); + } + return result; + } + } - public PairEntry getEntry() { - return index.dict.pairEntries.get(referenceIndex); + private String getRawText(final boolean compact) { + if (compact) { + return this.pairs.get(0).toStringTab(); + } + final StringBuilder builder = new StringBuilder(); + for (int i = 0; i < this.pairs.size(); ++i) { + if (i > 0) { + builder.append(" | "); + } + builder.append(this.pairs.get(i).lang1); + } + builder.append("\t"); + for (int i = 0; i < this.pairs.size(); ++i) { + if (i > 0) { + builder.append(" | "); + } + builder.append(this.pairs.get(i).lang2); + } + return builder.toString(); } - + @Override - public void print(PrintStream out) { - final PairEntry pairEntry = getEntry(); - for (int i = 0; i < pairEntry.pairs.length; ++i) { - out.print((i == 0 ? " " : " ") + pairEntry.pairs[i]); - out.println(); - } + public int compareTo(/*@NonNull*/ final PairEntry that) { + return this.getRawText(false).compareTo(that.getRawText(false)); } @Override - public String getRawText(boolean compact) { - final PairEntry pairEntry = getEntry(); - if (compact) { - return pairEntry.pairs[0].toStringTab(); - } - final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < pairEntry.pairs.length; ++i) { - if (i > 0) { - builder.append(" | "); - } - builder.append(pairEntry.pairs[i].lang1); - } - builder.append("\t"); - for (int i = 0; i < pairEntry.pairs.length; ++i) { - if (i > 0) { - builder.append(" | "); - } - builder.append(pairEntry.pairs[i].lang2); - } - return builder.toString(); + public String toString() { + return getRawText(false); } - } + // ----------------------------------------------------------------------- + public static final class Pair { + public final String lang1; + public final String lang2; + + @SuppressWarnings("WeakerAccess") + public Pair(final String lang1, final String lang2) { + this.lang1 = lang1; + this.lang2 = lang2; + assert lang1.trim().length() > 0 && lang2.trim().length() > 0 : "Empty pair!!!"; + } + + public Pair(final String lang1, final String lang2, final boolean swap) { + this(swap ? lang2 : lang1, swap ? lang1 : lang2); + } + + public String toString() { + return lang1 + " :: " + lang2; + } + + String toStringTab() { + return lang1 + "\t" + lang2; + } + + public String get(int i) { + if (i == 0) { + return lang1; + } else if (i == 1) { + return lang2; + } + throw new IllegalArgumentException(); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (!(o instanceof Pair)) return false; + Pair p = (Pair)o; + return p.lang1.equals(lang1) && p.lang2.equals(lang2); + } + + @Override + public int hashCode() + { + return (lang1 + "|" + lang2).hashCode(); + } + } }