<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

package lux.xpath;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import lux.ExpressionVisitor;
import lux.api.LuxException;
import lux.api.ValueType;

public class LiteralExpression extends AbstractExpression {
    
    private Object value;
    private ValueType valueType;
    
    public LiteralExpression () {
        this (null);
    }
    
    public LiteralExpression (Object value, ValueType valueType) {
        super(Type.Literal);
        this.value = value;
        this.valueType = valueType;
    }

    public LiteralExpression (Object value) {
        super(Type.Literal);
        this.value = value;
        if (value != null) {
            valueType = computeType (value);
        } else {
            valueType = ValueType.VALUE;
        }
    }

    public static final LiteralExpression ONE = new LiteralExpression (1);
    
    private static ValueType computeType (Object value) {
        // TODO: duration
        if (value instanceof String) {
            return ValueType.STRING;
        } else if (value instanceof Integer || value instanceof Long) {
            return ValueType.INT;
        } else if (value instanceof Double) {
            return ValueType.DOUBLE;
        } else if (value instanceof Float) {
            return ValueType.FLOAT;
        } else if (value instanceof BigDecimal) {
            return ValueType.DECIMAL;
        } else if (value instanceof Boolean) {
            return ValueType.BOOLEAN;
        } else if (value instanceof Date) {
            return ValueType.DATE;
        }
        throw new LuxException ("unsupported java object type: " + value.getClass().getSimpleName());
    }
        
    /**
     * @return 100
     */
    @Override public int getPrecedence () {
        return 100;
    }

    public ValueType getValueType () {
        return valueType;
    }

    public Object getValue() {
        return value;
    }
    
    @Override
    public void toString(StringBuilder buf) {
        if (value == null) {
            buf.append ("()");
            return;
        }
        switch (valueType) {
        case STRING:
            escapeString(value.toString(), buf);
            break;
        case BOOLEAN:
            buf.append (value).append("()");
            break;
        case FLOAT:
            Float f = (Float) value;
            if (f.isInfinite()) {
                if (f > 0)
                    buf.append ("xs:float('INF')");
                else
                    buf.append ("xs:float('-INF')");
            }
            else if (f.isNaN()) {
                buf.append ("xs:float('NaN')");
            }
            else {
                buf.append ("xs:float(").append(f).append(')');
            }
            break;
        case DOUBLE:
            Double d = (Double) value;
            if (d.isInfinite()) {
                if (d > 0)
                    buf.append ("xs:double('INF')");
                else
                    buf.append ("xs:double('-INF')");
            }
            else if (d.isNaN()) {
                buf.append ("xs:double('NaN')");
            }
            else {
                buf.append ("xs:double(").append(d).append(')');
            }
            break;
        case DATE:
            buf.append("xs:date(\"").append (calendarToXsDate(getCalendar())).append("\")");
            break;
        case DATE_TIME:
            buf.append("xs:dateTime(\"").append (calendarToXsDateTime(getCalendar())).append("\")");
            break;
        case TIME:
            buf.append("xs:time(\"").append (value).append("\")");
            break;
        case DECIMAL:
            buf.append("xs:decimal(\"").append (value).append("\")");
            break;
        case NUMBER:
        default:
            buf.append (value);
        }
    }

    private Calendar getCalendar() {
        Calendar dt = Calendar.getInstance();
        dt.setTimeZone(TimeZone.getTimeZone("UT"));
        dt.setTime((Date) value);
        return dt;
    }
    
    public static String calendarToXsDateTime (Calendar cal)
    {
        String tz="";
        int offset = cal.get(Calendar.ZONE_OFFSET);
        String sgn;
        if (offset < 0) {
            sgn = "-";
            offset = -offset;
        } else {
            sgn = "+";
        }
        int minutes = offset / 60000;
        int hours = minutes / 60;
        minutes = minutes % 60;
        tz = String.format ("%s%02d:%02d", sgn, hours, minutes);
        return String.format("%04d-%02d-%02dT%02d:%02d:%02d%s",
                cal.get(Calendar.YEAR),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.DAY_OF_MONTH),
                cal.get(Calendar.HOUR_OF_DAY),
                cal.get(Calendar.MINUTE),
                cal.get(Calendar.SECOND),
                tz
        );
    }

    public static String calendarToXsDate(Calendar cal)
    {
        return String.format("%04d-%02d-%02dZ",
                cal.get(Calendar.YEAR),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.DAY_OF_MONTH)
        );
    }

    public static void escapeString(String s, StringBuilder buf) {
        buf.append('"');
        for (char c : s.toCharArray()) {
            switch (c) {
            case '"': buf.append ("\"\""); break;
            case '&': buf.append ("&amp;"); break;
            default: buf.append (c);
            }
        }
        buf.append('"');
    }

    public AbstractExpression accept(ExpressionVisitor visitor) {
        return visitor.visit(this);
    }
    
    @Override 
    public boolean equals (Object other) {
        if (other instanceof LiteralExpression) {
            return value.equals(((LiteralExpression)other).value);
        }
        return false;
    }
    
    @Override
    public int hashCode () {
        return value.hashCode();
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
<commit_msg>xs:decimal serialization fix<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

package lux.xpath;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import lux.ExpressionVisitor;
import lux.api.LuxException;
import lux.api.ValueType;

public class LiteralExpression extends AbstractExpression {
    
    private Object value;
    private ValueType valueType;
    
    public LiteralExpression () {
        this (null);
    }
    
    public LiteralExpression (Object value, ValueType valueType) {
        super(Type.Literal);
        this.value = value;
        this.valueType = valueType;
    }

    public LiteralExpression (Object value) {
        super(Type.Literal);
        this.value = value;
        if (value != null) {
            valueType = computeType (value);
        } else {
            valueType = ValueType.VALUE;
        }
    }

    public static final LiteralExpression ONE = new LiteralExpression (1);
    
    private static ValueType computeType (Object value) {
        // TODO: duration
        if (value instanceof String) {
            return ValueType.STRING;
        } else if (value instanceof Integer || value instanceof Long) {
            return ValueType.INT;
        } else if (value instanceof Double) {
            return ValueType.DOUBLE;
        } else if (value instanceof Float) {
            return ValueType.FLOAT;
        } else if (value instanceof BigDecimal) {
            return ValueType.DECIMAL;
        } else if (value instanceof Boolean) {
            return ValueType.BOOLEAN;
        } else if (value instanceof Date) {
            return ValueType.DATE;
        }
        throw new LuxException ("unsupported java object type: " + value.getClass().getSimpleName());
    }
        
    /**
     * @return 100
     */
    @Override public int getPrecedence () {
        return 100;
    }

    public ValueType getValueType () {
        return valueType;
    }

    public Object getValue() {
        return value;
    }
    
    @Override
    public void toString(StringBuilder buf) {
        if (value == null) {
            buf.append ("()");
            return;
        }
        switch (valueType) {
        case STRING:
            escapeString(value.toString(), buf);
            break;
        case BOOLEAN:
            buf.append (value).append("()");
            break;
        case FLOAT:
            Float f = (Float) value;
            if (f.isInfinite()) {
                if (f > 0)
                    buf.append ("xs:float('INF')");
                else
                    buf.append ("xs:float('-INF')");
            }
            else if (f.isNaN()) {
                buf.append ("xs:float('NaN')");
            }
            else {
                buf.append ("xs:float(").append(f).append(')');
            }
            break;
        case DOUBLE:
            Double d = (Double) value;
            if (d.isInfinite()) {
                if (d > 0)
                    buf.append ("xs:double('INF')");
                else
                    buf.append ("xs:double('-INF')");
            }
            else if (d.isNaN()) {
                buf.append ("xs:double('NaN')");
            }
            else {
                buf.append ("xs:double(").append(d).append(')');
            }
            break;
        case DATE:
            buf.append("xs:date(\"").append (calendarToXsDate(getCalendar())).append("\")");
            break;
        case DATE_TIME:
            buf.append("xs:dateTime(\"").append (calendarToXsDateTime(getCalendar())).append("\")");
            break;
        case TIME:
            buf.append("xs:time(\"").append (value).append("\")");
            break;
        case DECIMAL:
            buf.append("xs:decimal(").append (value).append(")");
            break;
        case NUMBER:
        default:
            buf.append (value);
        }
    }

    private Calendar getCalendar() {
        Calendar dt = Calendar.getInstance();
        dt.setTimeZone(TimeZone.getTimeZone("UT"));
        dt.setTime((Date) value);
        return dt;
    }
    
    public static String calendarToXsDateTime (Calendar cal)
    {
        String tz="";
        int offset = cal.get(Calendar.ZONE_OFFSET);
        String sgn;
        if (offset < 0) {
            sgn = "-";
            offset = -offset;
        } else {
            sgn = "+";
        }
        int minutes = offset / 60000;
        int hours = minutes / 60;
        minutes = minutes % 60;
        tz = String.format ("%s%02d:%02d", sgn, hours, minutes);
        return String.format("%04d-%02d-%02dT%02d:%02d:%02d%s",
                cal.get(Calendar.YEAR),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.DAY_OF_MONTH),
                cal.get(Calendar.HOUR_OF_DAY),
                cal.get(Calendar.MINUTE),
                cal.get(Calendar.SECOND),
                tz
        );
    }

    public static String calendarToXsDate(Calendar cal)
    {
        return String.format("%04d-%02d-%02dZ",
                cal.get(Calendar.YEAR),
                cal.get(Calendar.MONTH) + 1,
                cal.get(Calendar.DAY_OF_MONTH)
        );
    }

    public static void escapeString(String s, StringBuilder buf) {
        buf.append('"');
        for (char c : s.toCharArray()) {
            switch (c) {
            case '"': buf.append ("\"\""); break;
            case '&': buf.append ("&amp;"); break;
            default: buf.append (c);
            }
        }
        buf.append('"');
    }

    public AbstractExpression accept(ExpressionVisitor visitor) {
        return visitor.visit(this);
    }
    
    @Override 
    public boolean equals (Object other) {
        if (other instanceof LiteralExpression) {
            return value.equals(((LiteralExpression)other).value);
        }
        return false;
    }
    
    @Override
    public int hashCode () {
        return value.hashCode();
    }
}

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

{'fraction_non_alphanumeric': 0.12216694306246545, 'fraction_numerical': 0.008054963278843875, 'mean_word_length': 1.6268409043766854, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3305598', 'n_tokens_mistral': 3623, 'n_tokens_neox': 3469, 'n_words': 878}