All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.galenframework.parser.ExpectRange Maven / Gradle / Ivy

There is a newer version: 2.4.4
Show newest version
/*******************************************************************************
* Copyright 2017 Ivan Shubin http://galenframework.com
* 
* 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.galenframework.parser;

import static com.galenframework.parser.Expectations.isDelimeter;
import static com.galenframework.parser.Expectations.isNumeric;

import com.galenframework.config.GalenConfig;
import com.galenframework.specs.RangeValue;
import com.galenframework.specs.Range;

public class ExpectRange implements Expectation{

    private String endingWord = "px";
    private boolean shouldUseEndingWord = true;

    public void setNoEndingWord() {
        shouldUseEndingWord = false;
    }

    private enum RangeType {
		NOTHING, APPROXIMATE, LESS_THAN, GREATER_THAN, LESS_THAN_OR_EQUALS, GREATER_THAN_OR_EQUALS
	}

    @Override
    public Range read(StringCharReader reader) {
        RangeType rangeType = identifyRangeType(reader);
        
        RangeValue firstValue = new ExpectRangeValue().read(reader);
        
        String text = expectNonNumeric(reader);

        if (shouldUseEndingWord && text.equals(endingWord)) {
            return createRange(firstValue, rangeType);
        }

        if (text.equals("%")) {
            return createRange(firstValue, rangeType).withPercentOf(readPercentageOf(reader));
        }
        else if (rangeType != RangeType.NOTHING) {
            return createRange(firstValue, rangeType);
        }
        else {
            Range range;

            if (text.equals("to")) {
                RangeValue secondValue =  new ExpectRangeValue().read(reader);
                range = Range.between(firstValue, secondValue);
            }
            else if (shouldUseEndingWord) {
                throw new SyntaxException("Expecting \"px\", \"to\" or \"%\", got \"" + text + "\"");
            } else {
                range = Range.exact(firstValue);
            }
            
            String end = expectNonNumeric(reader);
            if (shouldUseEndingWord && end.equals(endingWord)) {
                return range;
            } else if (end.equals("%")) {
                return range.withPercentOf(readPercentageOf(reader));
            } else if (shouldUseEndingWord) {
                throw new SyntaxException("Expecting \"" + endingWord + "\", got \"" + end + "\"");
            } else {
                return range;
            }
        }
    }

    private RangeType identifyRangeType(StringCharReader reader) {
        RangeType rangeType = RangeType.NOTHING;

        char firstNonWhiteSpaceSymbol = reader.firstNonWhiteSpaceSymbol();
        if (firstNonWhiteSpaceSymbol == '~') {
            rangeType = RangeType.APPROXIMATE;
        }
        else if (firstNonWhiteSpaceSymbol == '>') {
        	rangeType = RangeType.GREATER_THAN;
            reader.readSafeUntilSymbol('>');
            if (reader.firstNonWhiteSpaceSymbol() == '=') {
                reader.readSafeUntilSymbol('=');
                rangeType = RangeType.GREATER_THAN_OR_EQUALS;
            }
        }
        else if (firstNonWhiteSpaceSymbol == '<') {
        	rangeType = RangeType.LESS_THAN;
            reader.readSafeUntilSymbol('<');
            if (reader.firstNonWhiteSpaceSymbol() == '=') {
                reader.readSafeUntilSymbol('=');
                rangeType = RangeType.LESS_THAN_OR_EQUALS;
            }
        }
        return rangeType;
    }

    private Range createRange(RangeValue firstValue, RangeType rangeType) {
        if (rangeType == RangeType.APPROXIMATE) {
            Double delta = (double) GalenConfig.getConfig().getRangeApproximation();

            Double firstValueAsDouble = firstValue.asDouble();
            int precision = firstValue.getPrecision();

            return Range.between(new RangeValue(firstValueAsDouble - delta, precision),
                    new RangeValue(firstValueAsDouble + delta, precision));
        }
        else if (rangeType == RangeType.GREATER_THAN) {
        	return Range.greaterThan(firstValue);
        }
        else if (rangeType == RangeType.LESS_THAN) {
        	return Range.lessThan(firstValue);
        }
        else if (rangeType == RangeType.LESS_THAN_OR_EQUALS) {
            return Range.lessThanOrEquals(firstValue);
        }
        else if (rangeType == RangeType.GREATER_THAN_OR_EQUALS) {
            return Range.greaterThanOrEquals(firstValue);
        }
        else {
            return Range.exact(firstValue);
        }
    }

    private String readPercentageOf(StringCharReader reader) {
        String firstWord = expectNonNumeric(reader);
        if (firstWord.equals("of")) {
            String valuePath = expectAnyWord(reader).trim();
            if (valuePath.isEmpty()) {
                throw new SyntaxException("Missing value path for relative range");
            }
            else return valuePath;
        }
        else throw new SyntaxException("Missing value path for relative range");
    }

    private String expectNonNumeric(StringCharReader reader) {
        boolean started = false;
        char symbol;
        StringBuffer buffer = new StringBuffer();
        while(reader.hasMore()) {
            symbol = reader.next();
            if (started && isDelimeter(symbol)) {
                break;
            }
            else if (isNumeric(symbol)) {
                reader.back();
                break;
            }
            else if (!isDelimeter(symbol)) {
                buffer.append(symbol);
                started = true;
            }
        }
        return buffer.toString();
    }
    
    private String expectAnyWord(StringCharReader reader) {
        boolean started = false;
        char symbol;
        StringBuffer buffer = new StringBuffer();
        while(reader.hasMore()) {
            symbol = reader.next();
            if (started && isDelimeter(symbol)) {
                break;
            }
            else if (!isDelimeter(symbol)) {
                buffer.append(symbol);
                started = true;
            }
        }
        return buffer.toString();
    }


    private String msgFor(String text) {
        return String.format("Cannot parse range: \"%s\"", text);
    }

    public String getEndingWord() {
        return endingWord;
    }

    public void setEndingWord(String endingWord) {
        this.endingWord = endingWord;
    }
         
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy