Search in sources :

Example 11 with ParserException

use of javax.measure.format.ParserException in project sis by apache.

the class UnitFormat method parseTerm.

/**
 * Parses a single unit symbol with its exponent.
 * The given symbol shall not contain multiplication or division operator.
 *
 * @param  symbols  the complete string specified by the user.
 * @param  lower    index where to begin parsing in the {@code symbols} string.
 * @param  upper    index after the last character to parse in the {@code symbols} string.
 * @return the parsed unit symbol (never {@code null}).
 * @throws ParserException if a problem occurred while parsing the given symbols.
 */
@SuppressWarnings("fallthrough")
private Unit<?> parseTerm(final CharSequence symbols, final int lower, final int upper) throws ParserException {
    final String uom = CharSequences.trimWhitespaces(symbols, lower, upper).toString();
    /*
         * Check for labels explicitly given by users. Those labels have precedence over the Apache SIS hard-coded
         * symbols. If no explicit label was found, check for symbols and names known to this UnitFormat instance.
         */
    Unit<?> unit = labelToUnit.get(uom);
    if (unit == null) {
        unit = getPrefixed(uom);
        if (unit == null) {
            final int length = uom.length();
            if (length == 0) {
                return Units.UNITY;
            } else {
                /*
                     * If the first character is a digit, presume that the term is a multiplication factor.
                     * The "*" character is used for raising the number on the left to the power on the right.
                     * Example: "10*6" is equal to one million.
                     *
                     * In principle, spaces are not allowed in unit symbols (in particular, UCUM specifies that
                     * spaces should not be interpreted as multication operators).  However in practice we have
                     * sometime units written in a form like "100 feet".
                     */
                final char c = uom.charAt(0);
                if (isDigit(c) || isSign(c)) {
                    final double multiplier;
                    try {
                        int s = uom.lastIndexOf(' ');
                        if (s >= 0) {
                            final int next = CharSequences.skipLeadingWhitespaces(uom, s, length);
                            if (next < length && AbstractUnit.isSymbolChar(uom.codePointAt(next))) {
                                multiplier = Double.parseDouble(uom.substring(0, s));
                                return parseTerm(uom, s, length).multiply(multiplier);
                            }
                        }
                        // Check standard UCUM symbol first.
                        s = uom.lastIndexOf(Style.EXPONENT_OR_MULTIPLY);
                        if (s >= 0 || (s = uom.lastIndexOf(Style.EXPONENT)) >= 0) {
                            final int base = Integer.parseInt(uom.substring(0, s));
                            final int exp = Integer.parseInt(uom.substring(s + 1));
                            multiplier = Math.pow(base, exp);
                        } else {
                            multiplier = Double.parseDouble(uom);
                        }
                    } catch (NumberFormatException e) {
                        throw (ParserException) new ParserException(Errors.format(Errors.Keys.UnknownUnit_1, uom), symbols, lower).initCause(e);
                    }
                    return Units.UNITY.multiply(multiplier);
                }
            }
            if (length >= 2) {
                /*
                     * If the symbol ends with a digit (normal script or superscript), presume that this is the unit
                     * exponent.  That exponent can be a Unicode character (only one character in current UnitFormat
                     * implementation) or a number parseable with Integer.parseInt(String).
                     */
                int power = 1;
                int i = length;
                char c = uom.charAt(--i);
                boolean canApply = false;
                if (Characters.isSuperScript(c)) {
                    c = Characters.toNormalScript(c);
                    if (isDigit(c)) {
                        power = c - '0';
                        canApply = true;
                    }
                } else if (isDigit(c)) {
                    do {
                        c = uom.charAt(--i);
                        if (!isDigit(c)) {
                            if (!isSign(c))
                                i++;
                            try {
                                power = Integer.parseInt(uom.substring(i));
                            } catch (NumberFormatException e) {
                                // Should never happen unless the number is larger than 'int' capacity.
                                throw (ParserException) new ParserException(Errors.format(Errors.Keys.UnknownUnit_1, uom), symbols, lower + i).initCause(e);
                            }
                            canApply = true;
                            break;
                        }
                    } while (i != 0);
                }
                if (canApply) {
                    /*
                         * At this point we have parsed the exponent. Before to parse the raw unit symbol,
                         * skip the exponent symbol (^, * or **) if any.
                         */
                    i = CharSequences.skipTrailingWhitespaces(uom, 0, i);
                    if (i != 0) {
                        switch(uom.charAt(i - 1)) {
                            case Style.EXPONENT_OR_MULTIPLY:
                                {
                                    if (i != 1 && uom.charAt(i - 2) == Style.EXPONENT_OR_MULTIPLY)
                                        i--;
                                // Fallthrough for skipping the next character and whitespaces.
                                }
                            case Style.EXPONENT:
                                {
                                    i = CharSequences.skipTrailingWhitespaces(uom, 0, i - 1);
                                    break;
                                }
                        }
                    }
                    unit = getPrefixed(uom.substring(CharSequences.skipLeadingWhitespaces(uom, 0, i), i));
                    if (unit != null) {
                        return unit.pow(power);
                    }
                }
            }
            /*
                 * At this point, we have determined that the label is not a known unit symbol.
                 * It may be a unit name, in which case the label is not case-sensitive anymore.
                 */
            unit = fromName(uom);
            if (unit == null) {
                if (CharSequences.regionMatches(symbols, lower, UNITY, true)) {
                    return Units.UNITY;
                }
                throw new ParserException(Errors.format(Errors.Keys.UnknownUnit_1, uom), symbols, lower);
            }
        }
    }
    return unit;
}
Also used : ParserException(javax.measure.format.ParserException)

Example 12 with ParserException

use of javax.measure.format.ParserException in project sis by apache.

the class Proj4 method createCRS.

/**
 * Creates a new CRS from the given {@literal Proj.4} definition string.
 * Some examples of definition strings are:
 * <ul>
 *   <li>{@code "+init=epsg:3395 +over"} (see warning below)</li>
 *   <li>{@code "+proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"}</li>
 *   <li>{@code "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +ellps=WGS84 +towgs84=0,0,0"}</li>
 * </ul>
 *
 * <b>Warning:</b> despite the {@code "epsg"} word, coordinate reference systems created by {@code "+init=epsg:"}
 * syntax are not necessarily compliant with EPSG definitions. In particular, the axis order is often different.
 * Units of measurement may also differ.
 *
 * @param  definition  the Proj.4 definition string.
 * @param  dimension   the number of dimension of the CRS to create (2 or 3).
 * @return a CRS created from the given definition string and number of dimensions.
 * @throws NullPointerException if the definition string is {@code null}.
 * @throws IllegalArgumentException if the definition string is empty or the dimension argument is out of range.
 * @throws UnavailableFactoryException if the Proj.4 native library is not available.
 * @throws FactoryException if the CRS creation failed for another reason.
 *
 * @see Proj4Factory#createCoordinateReferenceSystem(String)
 */
public static CoordinateReferenceSystem createCRS(String definition, final int dimension) throws FactoryException {
    ArgumentChecks.ensureNonEmpty("definition", definition);
    ArgumentChecks.ensureBetween("dimension", 2, 3, dimension);
    definition = definition.trim();
    try {
        return Proj4Factory.INSTANCE.createCRS(definition, dimension >= 3);
    } catch (IllegalArgumentException | ParserException e) {
        throw new InvalidGeodeticParameterException(canNotParse(definition), e);
    } catch (UnsatisfiedLinkError | NoClassDefFoundError e) {
        throw new UnavailableFactoryException(unavailable(e), e);
    }
}
Also used : ParserException(javax.measure.format.ParserException) InvalidGeodeticParameterException(org.apache.sis.referencing.factory.InvalidGeodeticParameterException) UnavailableFactoryException(org.apache.sis.referencing.factory.UnavailableFactoryException)

Example 13 with ParserException

use of javax.measure.format.ParserException in project sis by apache.

the class Proj4Factory method createCoordinateReferenceSystem.

/**
 * Creates a new CRS from the given {@literal Proj.4} definition.
 * The {@code "Proj4:"} prefix (ignoring case), if present, is ignored.
 *
 * <div class="section">Apache SIS extension</div>
 * Proj.4 unconditionally requires 3 letters for the {@code "+axis="} parameter — for example {@code "neu"} for
 * <cite>North</cite>, <cite>East</cite> and <cite>Up</cite> respectively — regardless the number of dimensions
 * in the CRS to create. Apache SIS makes the vertical direction optional:
 *
 * <ul>
 *   <li>If the vertical direction is present (as in {@code "neu"}), a three-dimensional CRS is created.</li>
 *   <li>If the vertical direction is absent (as in {@code "ne"}), a two-dimensional CRS is created.</li>
 * </ul>
 *
 * <div class="note"><b>Examples:</b>
 * <ul>
 *   <li>{@code "+init=epsg:4326"} (<strong>not</strong> equivalent to the standard EPSG::4326 definition)</li>
 *   <li>{@code "+proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"} (default to two-dimensional CRS)</li>
 *   <li>{@code "+proj=latlon +a=6378137.0 +b=6356752.314245179 +pm=0.0 +axis=ne"} (explicitely two-dimensional)</li>
 *   <li>{@code "+proj=latlon +a=6378137.0 +b=6356752.314245179 +pm=0.0 +axis=neu"} (three-dimensional)</li>
 * </ul>
 * </div>
 *
 * @param  code  the Proj.4 definition of the CRS object to create.
 * @return a CRS created from the given definition.
 * @throws FactoryException if the CRS object can not be created for the given definition.
 *
 * @see Proj4#createCRS(String, int)
 */
@Override
public CoordinateReferenceSystem createCoordinateReferenceSystem(String code) throws FactoryException {
    code = trimNamespace(code);
    boolean hasHeight = false;
    /*
         * Count the number of axes declared in the "+axis" parameter.
         * If there is only two axes, add a 'u' (up) direction even in the two-dimensional case.
         * We make this addition because Proj.4 seems to require the 3-letters code in all case.
         */
    int offset = code.indexOf(AXIS_ORDER_PARAM);
    if (offset >= 0) {
        offset += AXIS_ORDER_PARAM.length();
        final CharSequence orientation = CharSequences.token(code, offset);
        for (int i = orientation.length(); --i >= 0; ) {
            final char c = orientation.charAt(i);
            hasHeight = (c == 'u' || c == 'd');
            if (hasHeight)
                break;
        }
        if (!hasHeight && orientation.length() < 3) {
            offset = code.indexOf(orientation.toString(), offset);
            if (offset >= 0) {
                // Should never be -1, but we are paranoiac.
                offset += orientation.length();
                code = new StringBuilder(code).insert(offset, 'u').toString();
            }
        }
    }
    try {
        return createCRS(code, hasHeight);
    } catch (IllegalArgumentException | ParserException e) {
        throw new InvalidGeodeticParameterException(Proj4.canNotParse(code), e);
    } catch (UnsatisfiedLinkError | NoClassDefFoundError e) {
        throw new UnavailableFactoryException(Proj4.unavailable(e), e);
    }
}
Also used : ParserException(javax.measure.format.ParserException) UnavailableFactoryException(org.apache.sis.referencing.factory.UnavailableFactoryException) InvalidGeodeticParameterException(org.apache.sis.referencing.factory.InvalidGeodeticParameterException)

Example 14 with ParserException

use of javax.measure.format.ParserException in project uom-se by unitsofmeasurement.

the class EBNFUnitFormat method parse.

@Override
protected Unit<? extends Quantity<?>> parse(CharSequence csq, ParsePosition cursor) throws ParserException {
    // Parsing reads the whole character sequence from the parse position.
    int start = cursor != null ? cursor.getIndex() : 0;
    int end = csq.length();
    if (end <= start) {
        return AbstractUnit.ONE;
    }
    String source = csq.subSequence(start, end).toString().trim();
    if (source.length() == 0) {
        return AbstractUnit.ONE;
    }
    try {
        UnitFormatParser parser = new UnitFormatParser(symbolMap, new StringReader(source));
        Unit<?> result = parser.parseUnit();
        if (cursor != null)
            cursor.setIndex(end);
        return result;
    } catch (TokenException e) {
        if (e.currentToken != null) {
            cursor.setErrorIndex(start + e.currentToken.endColumn);
        } else {
            cursor.setErrorIndex(start);
        }
        throw new ParserException(e);
    } catch (TokenMgrError e) {
        cursor.setErrorIndex(start);
        throw new IllegalArgumentException(e.getMessage());
    }
}
Also used : ParserException(javax.measure.format.ParserException) TokenException(tec.uom.se.internal.format.TokenException) StringReader(java.io.StringReader) TokenMgrError(tec.uom.se.internal.format.TokenMgrError) UnitFormatParser(tec.uom.se.internal.format.UnitFormatParser)

Example 15 with ParserException

use of javax.measure.format.ParserException in project uom-se by unitsofmeasurement.

the class LocalUnitFormat method parse.

public Unit<?> parse(CharSequence csq, ParsePosition cursor) throws ParserException {
    // Parsing reads the whole character sequence from the parse position.
    int start = cursor.getIndex();
    int end = csq.length();
    if (end <= start) {
        return AbstractUnit.ONE;
    }
    String source = csq.subSequence(start, end).toString().trim();
    if (source.length() == 0) {
        return AbstractUnit.ONE;
    }
    try {
        LocalUnitFormatParser parser = new LocalUnitFormatParser(symbolMap, new StringReader(source));
        Unit<?> result = parser.parseUnit();
        cursor.setIndex(end);
        return result;
    } catch (TokenException e) {
        if (e.currentToken != null) {
            cursor.setErrorIndex(start + e.currentToken.endColumn);
        } else {
            cursor.setErrorIndex(start);
        }
        // TODO should we throw
        throw new IllegalArgumentException(e);
    // ParserException here,
    // too?
    } catch (TokenMgrError e) {
        cursor.setErrorIndex(start);
        throw new ParserException(e);
    }
}
Also used : ParserException(javax.measure.format.ParserException) TokenException(tec.uom.se.internal.format.TokenException) StringReader(java.io.StringReader) LocalUnitFormatParser(tec.uom.se.internal.format.LocalUnitFormatParser) TokenMgrError(tec.uom.se.internal.format.TokenMgrError)

Aggregations

ParserException (javax.measure.format.ParserException)15 Test (org.junit.Test)5 StringReader (java.io.StringReader)3 ParsePosition (java.text.ParsePosition)2 UnitFormat (javax.measure.format.UnitFormat)2 InvalidGeodeticParameterException (org.apache.sis.referencing.factory.InvalidGeodeticParameterException)2 UnavailableFactoryException (org.apache.sis.referencing.factory.UnavailableFactoryException)2 TokenException (tec.uom.se.internal.format.TokenException)2 TokenMgrError (tec.uom.se.internal.format.TokenMgrError)2 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 Unit (javax.measure.Unit)1 FactoryDataException (org.apache.sis.referencing.factory.FactoryDataException)1 Test (org.junit.jupiter.api.Test)1 LocalUnitFormatParser (tec.uom.se.internal.format.LocalUnitFormatParser)1 UnitFormatParser (tec.uom.se.internal.format.UnitFormatParser)1 LocalUnitFormat (tech.units.indriya.format.LocalUnitFormat)1 SimpleUnitFormat (tech.units.indriya.format.SimpleUnitFormat)1 LocalUnitFormatParser (tech.units.indriya.internal.format.LocalUnitFormatParser)1 TokenException (tech.units.indriya.internal.format.TokenException)1