/** * License Agreement for OpenSearchServer * * Copyright (C) 2012 Emmanuel Keller / Jaeksoft * * http://www.open-search-server.com * * This file is part of OpenSearchServer. * * OpenSearchServer is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenSearchServer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenSearchServer. * If not, see <http://www.gnu.org/licenses/>. **/ package com.jaeksoft.searchlib.analysis.filter; import java.io.IOException; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.ParseException; import java.util.Locale; import org.apache.lucene.analysis.TokenStream; import com.jaeksoft.searchlib.SearchLibException; import com.jaeksoft.searchlib.analysis.ClassPropertyEnum; import com.jaeksoft.searchlib.analysis.FilterFactory; public class DegreesRadiansFilter extends FilterFactory { final private static NumberFormat getNumberFormat(int integer, int fraction) { DecimalFormat df = (DecimalFormat) DecimalFormat .getNumberInstance(Locale.US); df.setMaximumIntegerDigits(integer); df.setMinimumIntegerDigits(integer); df.setMinimumFractionDigits(fraction); df.setMaximumFractionDigits(fraction); df.setNegativePrefix("N"); df.setPositivePrefix("P"); df.setDecimalSeparatorAlwaysShown(true); return df; } final public static NumberFormat getDegreesFormat() { return getNumberFormat(3, 5); } final public static String NEGATIVE_RADIAN_ZERO = "N0.0000000"; final public static String POSITIVE_RADIAN_ZERO = "P0.0000000"; final public static NumberFormat getRadiansFormat() { return getNumberFormat(1, 7); } public final static void main(String[] argv) throws ParseException { System.out.println(getDegreesFormat().format(33.6564353435)); System.out.println(getRadiansFormat().format(-0.675757575575)); System.out.println(getRadiansFormat().format(0)); System.out.println(getRadiansFormat().format(-0)); System.out.println(getRadiansFormat().parse("N0.67576")); System.out.println(getRadiansFormat().parse("P0.7986312")); } abstract private class CheckTokenFilter extends AbstractTermFilter { private NumberFormat nf; protected CheckTokenFilter(TokenStream input, NumberFormat nf) { super(input); this.nf = nf; } final protected Double checkValue(double min, double max) { try { Double number = new Double(termAtt.toString()); if (number < min || number > max) return null; return number; } catch (NumberFormatException e) { if (faultTolerant) return null; throw e; } } protected abstract Double checkNumber(); final protected void createToken(double number) { createToken(nf.format(number)); } @Override public boolean incrementToken() throws IOException { for (;;) { if (!input.incrementToken()) return false; Double number = checkNumber(); if (number == null) return false; createToken(number); return true; } } } private double DEGREES_MAX = 360; private double DEGREES_MIN = -360; public class CheckDegreesTokenFilter extends CheckTokenFilter { private CheckDegreesTokenFilter(TokenStream input, NumberFormat nf) { super(input, nf); } private CheckDegreesTokenFilter(TokenStream input) { super(input, getDegreesFormat()); } @Override protected final Double checkNumber() { return checkValue(DEGREES_MIN, DEGREES_MAX); } } private double RADIANS_MAX = Math.PI * 2; private double RADIANS_MIN = -Math.PI * 2; public class DegreesToRadiansTokenFilter extends CheckDegreesTokenFilter { private DegreesToRadiansTokenFilter(TokenStream input) { super(input, getRadiansFormat()); } @Override public final boolean incrementToken() throws IOException { for (;;) { if (!input.incrementToken()) return false; Double degrees = checkNumber(); if (degrees == null) return false; double radians = Math.toRadians(degrees); createToken(radians); return true; } } } public class CheckRadiansTokenFilter extends CheckTokenFilter { private CheckRadiansTokenFilter(TokenStream input, NumberFormat nf) { super(input, nf); } private CheckRadiansTokenFilter(TokenStream input) { this(input, getRadiansFormat()); } @Override protected final Double checkNumber() { return checkValue(RADIANS_MIN, RADIANS_MAX); } } public class RadiansToDegreeTokenFilter extends CheckRadiansTokenFilter { private RadiansToDegreeTokenFilter(TokenStream input) { super(input, getDegreesFormat()); } @Override public final boolean incrementToken() throws IOException { for (;;) { if (!input.incrementToken()) return false; Double radians = checkNumber(); if (radians == null) return false; double degrees = Math.toDegrees(radians); createToken(degrees); return true; } } } private boolean faultTolerant = true; private int conversion = 0; @Override protected void initProperties() throws SearchLibException { super.initProperties(); addProperty(ClassPropertyEnum.DEGREES_RADIANS_CONVERSION, ClassPropertyEnum.DEGREES_RADIANS_CONVERSION_LIST[0], ClassPropertyEnum.DEGREES_RADIANS_CONVERSION_LIST, 0, 0); addProperty(ClassPropertyEnum.FAULT_TOLERANT, ClassPropertyEnum.BOOLEAN_LIST[0], ClassPropertyEnum.BOOLEAN_LIST, 0, 0); } @Override protected void checkValue(ClassPropertyEnum prop, String value) throws SearchLibException { if (prop == ClassPropertyEnum.DEGREES_RADIANS_CONVERSION) { conversion = 0; int i = 0; for (String v : ClassPropertyEnum.DEGREES_RADIANS_CONVERSION_LIST) { if (value.equals(v)) { conversion = i; break; } i++; } } else if (prop == ClassPropertyEnum.FAULT_TOLERANT) faultTolerant = Boolean.parseBoolean(value); } @Override public TokenStream create(TokenStream tokenStream) { switch (conversion) { default: return new DegreesToRadiansTokenFilter(tokenStream); case 1: return new RadiansToDegreeTokenFilter(tokenStream); case 2: return new CheckDegreesTokenFilter(tokenStream); case 3: return new CheckRadiansTokenFilter(tokenStream); } } }