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

cz.vutbr.web.domassign.decode.Decoder Maven / Gradle / Ivy

Go to download

jStyleParser is a CSS parser written in Java. It has its own application interface that is designed to allow an efficient CSS processing in Java and mapping the values to the Java data types. It parses CSS 2.1 style sheets into structures that can be efficiently assigned to DOM elements. It is intended be the primary CSS parser for the CSSBox library. While handling errors, it is user agent conforming according to the CSS specification.

The newest version!
/**
 * 
 */
package cz.vutbr.web.domassign.decode;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cz.vutbr.web.css.CSSFactory;
import cz.vutbr.web.css.CSSProperty;
import cz.vutbr.web.css.Declaration;
import cz.vutbr.web.css.RuleFactory;
import cz.vutbr.web.css.Term;
import cz.vutbr.web.css.Term.Operator;
import cz.vutbr.web.css.TermColor;
import cz.vutbr.web.css.TermFactory;
import cz.vutbr.web.css.TermFloatValue;
import cz.vutbr.web.css.TermIdent;
import cz.vutbr.web.css.TermInteger;
import cz.vutbr.web.css.TermLength;
import cz.vutbr.web.css.TermList;
import cz.vutbr.web.css.TermNumber;
import cz.vutbr.web.css.TermPercent;
import cz.vutbr.web.css.TermTime;

/**
 * A base class for repeaters and variators.
 * 
 * @author burgetr
 */
public class Decoder
{

    /**
     * A hint about the allowed value range when processing numeric values. 
     */
    public enum ValueRange {
        /** Allow all values */
        ALLOW_ALL,
        /** Treat negative values as invalid */
        DISALLOW_NEGATIVE,
        /** Truncate negative values to zero */
        TRUNCATE_NEGATIVE,
        /** Treat zero as invalid */
        DISALLOW_ZERO
    }
    
    /**
     * Inherit acceptance flags
     */
    public static final boolean AVOID_INH = true;
    public static final boolean ALLOW_INH = false;
    
    public static final RuleFactory rf = CSSFactory.getRuleFactory();
    public static final TermFactory tf = CSSFactory.getTermFactory();

    
    /**
     * Converts TermIdent into CSSProperty using intersection set.
     * CSSProperty.Translator is used.
     * 
     * @param 
     *            Subclass of CSSProperty to be returned
     * @param type
     *            Class of property to be used to retrieve value
     * @param intersection
     *            Intersection set or null if no intersection is
     *            used
     * @param term
     *            TermIdent to be transferred to property
     * @return CSSProperty of type <T> or null
     */
    public static  T genericPropertyRaw(Class type,
            Set intersection, TermIdent term) {

        try {
            String name = term.getValue().replace("-", "_").toUpperCase();
            T property = CSSProperty.Translator.valueOf(type, name);
            if (intersection != null && intersection.contains(property))
                return property;
            return property;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Converts TermIdent into value of enum of given class and stores it into
     * properties map under key property
     * 
     * @param 
     *            Enum & CSSProperty limitation
     * @param type
     *            Type of enum which instance is retrieved
     * @param term
     *            Term with value to be converted
     * @param avoidInherit
     *            If true inherit value is not considered valid
     * @param properties
     *            Properties map where to store value
     * @param propertyName
     *            Name under which property is stored in map
     * @return true in case of success, false
     *         otherwise
     */
    public static  boolean genericProperty(Class type,
            TermIdent term, boolean avoidInherit,
            Map properties, String propertyName) {

        T property = genericPropertyRaw(type, null, term);
        if (property == null || (avoidInherit && property.equalsInherit()))
            return false;

        properties.put(propertyName, property);
        return true;
    }

    /**
     * Converts TermIdent into value of CSSProperty for given class
     * 
     */
    public static  boolean genericTermIdent(Class type,
            Term term, boolean avoidInherit, String propertyName,
            Map properties) {

        if (term instanceof TermIdent) {
            return genericProperty(type, (TermIdent) term, avoidInherit,
                    properties, propertyName);
        }
        return false;
    }

    /**
     * Converts term into Color and stored values and types in maps
     * 
     * @param 
     *            CSSProperty
     * @param term
     *            Term to be parsed
     * @param propertyName
     *            How to store colorIdentificiton
     * @param colorIdentification
     *            What to store under propertyName
     * @param properties
     *            Map to store property types
     * @param values
     *            Map to store property values
     * @return true in case of success, false
     *         otherwise
     */
    public static  boolean genericTermColor(Term term,
            String propertyName, T colorIdentification,
            Map properties, Map> values) {

        if (term instanceof TermColor) {
            properties.put(propertyName, colorIdentification);
            values.put(propertyName, term);
            return true;
        }

        return false;

    }

    /**
     * Converts term into TermLength and stores values and types in maps
     * 
     * @param 
     *            CSSProperty
     * @param term
     *            Term to be parsed
     * @param propertyName
     *            How to store colorIdentificiton
     * @param lengthIdentification
     *            What to store under propertyName
     * @param properties
     *            Map to store property types
     * @param values
     *            Map to store property values
     * @return true in case of success, false
     *         otherwise
     */
    public static  boolean genericTermLength(Term term,
            String propertyName, T lengthIdentification, ValueRange range,
            Map properties, Map> values) {

        if (term instanceof TermInteger  && ((TermInteger) term).getUnit().equals(TermNumber.Unit.none)) {
            if (CSSFactory.getImplyPixelLength() || ((TermInteger) term).getValue() == 0) { //0 is always allowed with no units
                // convert to length with units of px
                TermLength tl = tf.createLength(((TermInteger) term).getValue(), TermNumber.Unit.px);
                return genericTerm(TermLength.class, tl, propertyName, lengthIdentification, range, properties, values);
            } else {
                return false;
            }
        }
        else if (term instanceof TermLength) { 
            return genericTerm(TermLength.class, term, propertyName, lengthIdentification, range, properties, values); 
        }

        return false;

    }

    /**
     * Check whether given declaration contains one term of given type. It is
     * able to check even whether is above zero for numeric values
     * 
     * @param 
     *            Class of CSSProperty to be used for result
     * @param termType
     *            Supposed type of term
     * @param term
     *            Term of which is supposed to be of type termType,
     *            that is input data
     * @param propertyName
     *            Name under which property's value and type is stored in maps
     * @param typeIdentification
     *            How this type of term is described in type T
     * @param sanify
     *            Check if value is positive
     * @param properties
     *            Where to store property type
     * @param values
     *            Where to store property value
     * @return true if succeeded in recognition, false
     *         otherwise
     */
    public static  boolean genericTerm(
            Class> termType, Term term,
            String propertyName, T typeIdentification, ValueRange range,
            Map properties, Map> values) {

        // check type
        if (termType.isInstance(term)) {
            // sanity check
            if (range != ValueRange.ALLOW_ALL) {
                // check for integer
                if (term.getValue() instanceof Integer) {
                    final Integer zero = 0;
                    int result = zero.compareTo((Integer) term.getValue());
                    if (result > 0) {
                        // return false is also possibility
                        // but we will change to zero
                        if (range == ValueRange.TRUNCATE_NEGATIVE)
                            ((TermInteger) term).setZero();
                        else
                            return false;
                    } else if(result == 0) {
                        if(range == ValueRange.DISALLOW_ZERO) {
                            return false;
                        }
                    }
                }
                // check for float
                else if (term.getValue() instanceof java.lang.Float) {
                    final java.lang.Float zero = 0f;
                    int result = zero.compareTo((java.lang.Float) term.getValue());
                    if (result > 0) {
                        // return false is also possibility
                        // but we will change to zero
                        if (range == ValueRange.TRUNCATE_NEGATIVE)
                            ((TermFloatValue) term).setZero();
                        else
                            return false;
                    } else if(result == 0) {
                        if(range == ValueRange.DISALLOW_ZERO) {
                            return false;
                        }
                    }
                }
            }
            // passed both type check and range check,
            // store
            properties.put(propertyName, typeIdentification);
            values.put(propertyName, term);
            return true;

        }
        return false;

    }

    /**
     * Processes declaration which is supposed to contain one identification
     * term
     * 
     * @param 
     *            Type of CSSProperty
     * @param type
     *            Class of CSSProperty to be stored
     * @param d
     *            Declaration to be parsed
     * @param properties
     *            Properties map where to store enum
     * @return true in case of success, false
     *         elsewhere
     */
    public static  boolean genericOneIdent(Class type,
            Declaration d, Map properties) {

        if (d.size() != 1)
            return false;

        return genericTermIdent(type, d.get(0), ALLOW_INH, d.getProperty(),
                properties);
    }

    /**
     * Processes declaration which is supposed to contain one identification
     * term or one TermColor
     * 
     * @param 
     *            Type of CSSProperty
     * @param type
     *            Class of enum to be stored
     * @param colorIdentification
     *            Instance of CSSProperty stored into properties to indicate
     *            that additional value of type TermColor is stored in values
     * @param d
     *            Declaration to be parsed
     * @param properties
     *            Properties map where to store enum
     * @param values
     * @return true in case of success, false
     *         elsewhere
     */
    public static  boolean genericOneIdentOrColor(
            Class type, T colorIdentification, Declaration d,
            Map properties, Map> values) {

        if (d.size() != 1)
            return false;

        return genericTermIdent(type, d.get(0), ALLOW_INH, d.getProperty(),
                properties)
                || genericTermColor(d.get(0), d.getProperty(),
                        colorIdentification, properties, values);
    }

    public static  boolean genericOneIdentOrInteger(
            Class type, T integerIdentification, ValueRange range,
            Declaration d, Map properties,
            Map> values) {

        if (d.size() != 1)
            return false;

        return genericTermIdent(type, d.get(0), ALLOW_INH, d.getProperty(),
                properties)
                || genericTerm(TermInteger.class, d.get(0), d.getProperty(),
                        integerIdentification, range, properties, values);
    }

    public static  boolean genericOneIdentOrIntegerOrNumber(
            Class type, T integerIdentification, T numberIdentification, ValueRange range,
            Declaration d, Map properties,
            Map> values) {

        if (d.size() != 1)
            return false;

        return genericTermIdent(type, d.get(0), ALLOW_INH, d.getProperty(), properties)
                || genericTerm(TermInteger.class, d.get(0), d.getProperty(),
                        integerIdentification, range, properties, values)
                || genericTerm(TermNumber.class, d.get(0), d.getProperty(),
                        numberIdentification, range, properties, values);
    }
    
    public static  boolean genericOneIdentOrLength(
            Class type, T lengthIdentification, ValueRange range,
            Declaration d, Map properties,
            Map> values) {

        if (d.size() != 1)
            return false;

        return genericTermIdent(type, d.get(0), ALLOW_INH, d.getProperty(),
                properties)
                || genericTermLength(d.get(0), d.getProperty(),
                        lengthIdentification, range, properties, values);
    }
    
    public static  boolean genericTime(
            Class type, T integerIdentification, ValueRange range,
            Declaration d, Map properties,
            Map> values) {
        if (d.size() != 1)
            return false;
        
        Term term = d.get(0);
        if (term instanceof TermIdent) {
            T property = genericPropertyRaw(type, null, (TermIdent) term);
            if (!property.equalsInherit())
                return false;
            else
            {
                properties.put(d.getProperty(), property);
                return true;
            }
        }
        return genericTerm(TermTime.class, term, d.getProperty(), integerIdentification, range, properties, values);
    }
    
    public static  boolean genericInteger(
            Class type, T integerIdentification, ValueRange range,
            Declaration d, Map properties,
            Map> values) {

        if (d.size() != 1)
            return false;
        
        Term term = d.get(0);
        if (term instanceof TermIdent)
        {
            T property = genericPropertyRaw(type, null, (TermIdent) term);
            if (!property.equalsInherit())
                return false;
            else
            {
                properties.put(d.getProperty(), property);
                return true;
            }
        }
        else
        {
            return genericTerm(TermInteger.class, term, d.getProperty(), integerIdentification, range, properties, values);
        }
    }
    
    public static  boolean genericIntegerOrLength(
            Class type, T integerIdentification, T lengthIdentification, ValueRange range,
            Declaration d, Map properties,
            Map> values) {

        if (d.size() != 1)
            return false;
        
        Term term = d.get(0);
        if (term instanceof TermIdent)
        {
            T property = genericPropertyRaw(type, null, (TermIdent) term);
            if (!property.equalsInherit())
                return false;
            else
            {
                properties.put(d.getProperty(), property);
                return true;
            }
        }
        else
        {
            return genericTerm(TermInteger.class, term, d.getProperty(),
                            integerIdentification, range, properties, values)
                    || genericTermLength(term, d.getProperty(), lengthIdentification, range, properties, values);
        }
    }
    
    public static  & CSSProperty> boolean genericOneIdentOrLengthOrPercent(
            Class type, T lengthIdentification, T percentIdentification,
            ValueRange range, Declaration d, Map properties,
            Map> values) {

        if (d.size() != 1)
            return false;

        return genericTermIdent(type, d.get(0), ALLOW_INH, d.getProperty(),
                properties)
                || genericTermLength(d.get(0), d.getProperty(),
                        lengthIdentification, range, properties, values)
                || genericTerm(TermPercent.class, d.get(0), d.getProperty(),
                        percentIdentification, range, properties, values);
    }

    public static  & CSSProperty> boolean genericTwoIdentsOrLengthsOrPercents(
            Class type, T listIdentification,
            ValueRange range, Declaration d, Map properties,
            Map> values) {

        if (d.size() == 1) {
            Term term = d.get(0);
            String propertyName = d.getProperty();
            // is it identifier or length ?
            if (genericTermIdent(type, term, ALLOW_INH, propertyName, properties)
                || genericTermLength(term, propertyName,
                        listIdentification, range, properties, values)
                || genericTerm(TermPercent.class, term, propertyName,
                        listIdentification, range, properties, values)) {
                // one term with length was inserted, double it
                if (properties.get(propertyName) == listIdentification) {
                    TermList terms = tf.createList(2);
                    terms.add(term);
                    terms.add(term);
                    values.put(propertyName, terms);
                }
                return true;
            }
            else
                return false;
        }
        // two numerical values
        else if (d.size() == 2) {
            Term term1 = d.get(0);
            Term term2 = d.get(1);
            String propertyName = d.getProperty();
            // two lengths ?
            if ((genericTermLength(term1, propertyName,
                            listIdentification, range, properties, values)
                    || genericTerm(TermPercent.class, term1, propertyName,
                            listIdentification, range, properties, values))
                 && (genericTermLength(term2, propertyName,
                            listIdentification, range, properties, values)
                    || genericTerm(TermPercent.class, term2, propertyName,
                            listIdentification, range, properties, values))) {
                TermList terms = tf.createList(2);
                terms.add(term1);
                terms.add(term2);
                values.put(propertyName, terms);
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }
    
    /**
     * Splits a declaration to multiple declarations by a separating term.
     * @param src the source declarations
     * @param separator separating operator
     * @return a list of declarations where each of them contains a sub-list of terms of the source declaration
     */
    public static List splitDeclarations(Declaration src, Operator sepOperator)
    {
        final List ret = new ArrayList<>();
        Declaration current = rf.createDeclaration();
        current.unlock();
        for (Term t : src.asList()) {
            if (t.getOperator() == sepOperator) {
                ret.add(current);
                current = rf.createDeclaration();
                current.unlock();
            }
            current.add(t);
        }
        ret.add(current);
        return ret;
    }

    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy