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

org.apache.abdera.i18n.templates.Operation Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  The ASF licenses this file to You
 * 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.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */
package org.apache.abdera.i18n.templates;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.abdera.i18n.text.CharUtils;
import org.apache.abdera.i18n.text.Normalizer;
import org.apache.abdera.i18n.text.UrlEncoding;

@SuppressWarnings("unchecked")
public abstract class Operation implements Serializable {

    protected final String name;
    protected final boolean multivar;

    protected Operation(String name) {
        this(name, false);
    }

    protected Operation(String name, boolean multivar) {
        this.name = name;
        this.multivar = multivar;
    }

    public final String name() {
        return name;
    }

    public abstract String evaluate(String var, String arg, Context context);

    public abstract void explain(String var, String arg, Appendable buf) throws IOException;

    public String[] getVariables(String var) {
        List list = new ArrayList();
        if (!multivar) {
            String name = tokenName(var);
            if (!list.contains(name))
                list.add(name);
        } else {
            String[] vardefs = var.split("\\+?\\s*,\\s*");
            for (int n = 0; n < vardefs.length; n++) {
                String vardef = vardefs[n];
                String name = vardef.split("=", 2)[0];
                if (!list.contains(name))
                    list.add(name);
            }
        }
        return list.toArray(new String[list.size()]);
    }

    private static Map operations = getOperations();

    private static Map getOperations() {
        Map ops = new HashMap();
        ops.put("", new DefaultOperation());
        ops.put("prefix", new PrefixOperation());
        ops.put("suffix", new AppendOperation());
        ops.put("join", new JoinOperation());
        ops.put("list", new ListJoinOperation());
        ops.put("opt", new OptOperation());
        ops.put("neg", new NegOperation());
        ops.put("append", ops.get("suffix")); // for backwards compatibility
        ops.put("listjoin", ops.get("list")); // for backwards compatibility
        return ops;
    }

    public static void register(Operation operation) {
        operations.put(operation.name(), operation);
    }

    public static Operation get(String name) {
        if (name == null)
            name = "";
        Operation op = operations.get(name);
        if (op != null)
            return op;
        throw new UnsupportedOperationException(name);
    }

    private static String tokenName(String token) {
        String[] vardef = token.split("=", 2);
        return vardef[0];
    }

    private static String evallist(String token, Context context, String sep) {
        StringBuilder buf = new StringBuilder();
        Object value = context.resolve(token);
        if (value != null) {
            if (value instanceof String) {
                String val = toString(value, context);
                if (val != null)
                    buf.append(val);
            } else if (value.getClass().isArray()) {
                Object[] values = (Object[])value;
                for (Object obj : values) {
                    String val = toString(obj, context);
                    if (val != null) {
                        if (buf.length() > 0)
                            buf.append(sep);
                        buf.append(val);
                    }
                }
            } else if (value instanceof Iterable) {
                Iterable iterable = (Iterable)value;
                for (Object obj : iterable) {
                    String val = toString(obj, context);
                    if (val != null) {
                        if (buf.length() > 0)
                            buf.append(sep);
                        buf.append(val);
                    }
                }
            }
        } else
            return null;
        return buf.toString();
    }

    protected static String eval(String token, Context context) {
        String[] vardef = token.split("=", 2);
        String var = vardef[0];
        String def = vardef.length > 1 ? vardef[1] : null;
        Object rep = context.resolve(var);
        String val = toString(rep, context);
        return val != null ? val : def != null ? def : null;
    }

    private static String toString(Object val, Context context) {
        if (val == null)
            return null;
        if (val.getClass().isArray()) {
            if (val instanceof byte[]) {
                return UrlEncoding.encode((byte[])val);
            } else if (val instanceof char[]) {
                String chars = new String((char[])val);
                return UrlEncoding.encode(Normalizer.normalize(chars, Normalizer.Form.KC).toString(), context.isIri()
                    ? CharUtils.Profile.IUNRESERVED.filter() : CharUtils.Profile.UNRESERVED.filter());
            } else if (val instanceof short[]) {
                StringBuilder buf = new StringBuilder();
                short[] array = (short[])val;
                for (short obj : array) {
                    if (buf.length() > 0)
                        buf.append("%2C");
                    buf.append(String.valueOf(obj));
                }
                return buf.toString();
            } else if (val instanceof int[]) {
                StringBuilder buf = new StringBuilder();
                int[] array = (int[])val;
                for (int obj : array) {
                    if (buf.length() > 0)
                        buf.append("%2C");
                    buf.append(String.valueOf(obj));
                }
                return buf.toString();
            } else if (val instanceof long[]) {
                StringBuilder buf = new StringBuilder();
                long[] array = (long[])val;
                for (long obj : array) {
                    if (buf.length() > 0)
                        buf.append("%2C");
                    buf.append(String.valueOf(obj));
                }
                return buf.toString();
            } else if (val instanceof double[]) {
                StringBuilder buf = new StringBuilder();
                double[] array = (double[])val;
                for (double obj : array) {
                    if (buf.length() > 0)
                        buf.append("%2C");
                    buf.append(String.valueOf(obj));
                }
                return buf.toString();
            } else if (val instanceof float[]) {
                StringBuilder buf = new StringBuilder();
                float[] array = (float[])val;
                for (float obj : array) {
                    if (buf.length() > 0)
                        buf.append("%2C");
                    buf.append(String.valueOf(obj));
                }
                return buf.toString();
            } else if (val instanceof boolean[]) {
                StringBuilder buf = new StringBuilder();
                boolean[] array = (boolean[])val;
                for (boolean obj : array) {
                    if (buf.length() > 0)
                        buf.append("%2C");
                    buf.append(String.valueOf(obj));
                }
                return buf.toString();
            } else {
                StringBuilder buf = new StringBuilder();
                Object[] array = (Object[])val;
                for (Object obj : array)
                    buf.append(toString(obj, context));
                return buf.toString();
            }
        } else if (val instanceof Template) {
            return toString(((Template)val).getPattern(), context);
        } else if (val instanceof InputStream) {
            try {
                return UrlEncoding.encode((InputStream)val);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else if (val instanceof Readable) {
            try {
                return UrlEncoding.encode((Readable)val, "UTF-8", context.isIri() ? CharUtils.Profile.IUNRESERVED
                    .filter() : CharUtils.Profile.UNRESERVED.filter());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else if (val instanceof CharSequence) {
            return encode((CharSequence)val, context.isIri());
        } else if (val instanceof Byte) {
            return UrlEncoding.encode(((Byte)val).byteValue());
        } else if (val instanceof Iterable) {
            StringBuilder buf = new StringBuilder();
            Iterable i = (Iterable)val;
            for (Object obj : i)
                buf.append(toString(obj, context));
            return buf.toString();
        } else {
            return encode(val != null ? val.toString() : null, context.isIri());
        }
    }

    protected static String eval(String token, String arg, Context context) {
        String[] vardef = token.split("=", 2);
        String var = vardef[0];
        String def = vardef.length > 1 ? vardef[1] : null;
        Object rep = context.resolve(var);
        if (rep != null) {
            StringBuilder buf = new StringBuilder();
            if (rep.getClass().isArray()) {
                if (rep instanceof byte[]) {
                    String val = toString(rep, context);
                    if (val != null) {
                        buf.append(var);
                        buf.append("=");
                        buf.append(val);
                    }
                } else if (rep instanceof char[]) {
                    String val = toString(rep, context);
                    if (val != null) {
                        buf.append(var);
                        buf.append("=");
                        buf.append(val);
                    }
                } else if (rep instanceof short[]) {
                    String val = toString(rep, context);
                    if (val != null) {
                        buf.append(var);
                        buf.append("=");
                        buf.append(val);
                    }
                } else if (rep instanceof int[]) {
                    String val = toString(rep, context);
                    if (val != null) {
                        buf.append(var);
                        buf.append("=");
                        buf.append(val);
                    }
                } else if (rep instanceof long[]) {
                    String val = toString(rep, context);
                    if (val != null) {
                        buf.append(var);
                        buf.append("=");
                        buf.append(val);
                    }
                } else if (rep instanceof double[]) {
                    String val = toString(rep, context);
                    if (val != null) {
                        buf.append(var);
                        buf.append("=");
                        buf.append(val);
                    }
                } else if (rep instanceof float[]) {
                    String val = toString(rep, context);
                    if (val != null) {
                        buf.append(var);
                        buf.append("=");
                        buf.append(val);
                    }
                } else if (rep instanceof boolean[]) {
                    String val = toString(rep, context);
                    if (val != null) {
                        buf.append(var);
                        buf.append("=");
                        buf.append(val);
                    }
                } else {
                    Object[] array = (Object[])rep;
                    for (Object obj : array) {
                        String val = toString(obj, context);
                        if (val != null) {
                            if (buf.length() > 0)
                                buf.append(arg);
                            buf.append(var);
                            buf.append("=");
                            buf.append(val);
                        }
                    }
                }
            } else if (rep instanceof Iterable) {
                Iterable list = (Iterable)rep;
                for (Object obj : list) {
                    String val = toString(obj, context);
                    if (val != null) {
                        if (buf.length() > 0)
                            buf.append(arg);
                        buf.append(var);
                        buf.append("=");
                        buf.append(val);
                    }
                }
            } else {
                String val = toString(rep, context);
                if (val != null) {
                    buf.append(var);
                    buf.append("=");
                    buf.append(val);
                }
            }
            return buf.toString();
        } else if (def != null && def.length() > 0) {
            StringBuilder buf = new StringBuilder();
            buf.append(var);
            buf.append("=");
            buf.append(def);
            return buf.toString();
        } else
            return null;
    }

    protected static boolean isdefined(String token, Context context) {
        String[] vardef = token.split("=", 2);
        String var = vardef[0];
        String def = vardef.length > 1 ? vardef[1] : null;
        Object rep = context.resolve(var);
        if (rep == null)
            rep = def;
        if (rep == null)
            return false;
        if (rep.getClass().isArray()) {
            if (rep instanceof byte[])
                return ((byte[])rep).length > 0;
            else if (rep instanceof short[])
                return ((short[])rep).length > 0;
            else if (rep instanceof char[])
                return ((char[])rep).length > 0;
            else if (rep instanceof int[])
                return ((int[])rep).length > 0;
            else if (rep instanceof long[])
                return ((long[])rep).length > 0;
            else if (rep instanceof double[])
                return ((double[])rep).length > 0;
            else if (rep instanceof float[])
                return ((float[])rep).length > 0;
            else if (rep instanceof boolean[])
                return ((boolean[])rep).length > 0;
            else if (rep instanceof Object[])
                return ((Object[])rep).length > 0;
        }
        return true;
    }

    private static String encode(CharSequence val, boolean isiri) {
        return UrlEncoding.encode(Normalizer.normalize(val, Normalizer.Form.KC).toString(), isiri
            ? CharUtils.Profile.IUNRESERVED.filter() : CharUtils.Profile.UNRESERVED.filter());
    }

    private static final class DefaultOperation extends Operation {
        private static final long serialVersionUID = -1279818778391836528L;

        public DefaultOperation() {
            super("");
        }

        public String evaluate(String var, String arg, Context context) {
            return eval(var, context);
        }

        public void explain(String var, String arg, Appendable buf) throws IOException {
            buf.append("Replaced with the value of '").append(var).append("'");
        }
    }

    private static final class PrefixOperation extends Operation {
        private static final long serialVersionUID = 2738115969196268525L;

        public PrefixOperation() {
            super("prefix");
        }

        public String evaluate(String var, String arg, Context context) {
            String value = evallist(var, context, arg);
            return value == null || value.length() == 0 ? "" : arg != null ? arg + value : value;
        }

        public void explain(String var, String arg, Appendable buf) throws IOException {
            buf.append("If '").append(var).append("' is defined then prefix the value of '").append(var)
                .append("' with '").append(arg).append("'");
        }
    }

    private static final class AppendOperation extends Operation {
        private static final long serialVersionUID = -2742793539643289075L;

        public AppendOperation() {
            super("suffix");
        }

        public String evaluate(String var, String arg, Context context) {
            String value = evallist(var, context, arg);
            return value == null || value.length() == 0 ? "" : arg != null ? value + arg : value;
        }

        public void explain(String var, String arg, Appendable buf) throws IOException {
            buf.append("If '").append(var).append("' is defined then append '").append(arg)
                .append("' to the value of '").append(var).append("'");
        }
    }

    private static final class JoinOperation extends Operation {
        private static final long serialVersionUID = -4102440981071994082L;

        public JoinOperation() {
            super("join", true);
        }

        public String evaluate(String var, String arg, Context context) {
            StringBuilder buf = new StringBuilder();
            String[] vardefs = var.split("\\+?\\s*,\\s*");
            String val = null;
            for (int n = 0; n < vardefs.length; n++) {
                String vardef = vardefs[n];
                val = eval(vardef, arg, context);
                if (val != null) {
                    if (buf.length() > 0)
                        buf.append(arg);
                    buf.append(val);
                }
            }
            String value = buf.toString();
            return value;
        }

        public void explain(String var, String arg, Appendable buf) throws IOException {
            buf.append("Join 'var=value' with '" + arg + "' for each variable in [");
            String[] vars = getVariables(var);
            boolean b = false;
            for (String v : vars) {
                if (b)
                    buf.append(',');
                else
                    b = true;
                buf.append("'").append(v).append("'");
            }
            buf.append("]");
        }
    }

    private static final class ListJoinOperation extends Operation {
        private static final long serialVersionUID = -8314383556644740425L;

        public ListJoinOperation() {
            super("list");
        }

        public String evaluate(String var, String arg, Context context) {
            return evallist(var, context, arg);
        }

        public void explain(String var, String arg, Appendable buf) throws IOException {
            buf.append("Join the members of the list '").append(var).append("' together with '").append(arg)
                .append("'");
        }
    }

    private static final class OptOperation extends Operation {
        private static final long serialVersionUID = 7808433764609641180L;

        public OptOperation() {
            super("opt", true);
        }

        public String evaluate(String var, String arg, Context context) {
            String[] vardefs = var.split("\\s*,\\s*");
            for (String v : vardefs) {
                if (isdefined(v, context))
                    return arg;
            }
            return null;
        }

        public void explain(String var, String arg, Appendable buf) throws IOException {
            buf.append("If [");
            String[] vars = getVariables(var);
            boolean b = false;
            for (String v : vars) {
                if (b)
                    buf.append(',');
                else
                    b = true;
                buf.append("'").append(v).append("'");
            }
            buf.append("] is defined and a string, or a list with one or more members, then insert '").append(arg)
                .append("'");
        }
    }

    private static final class NegOperation extends Operation {
        private static final long serialVersionUID = 1936380358902743528L;

        public NegOperation() {
            super("neg", true);
        }

        public String evaluate(String var, String arg, Context context) {
            String[] vardefs = var.split("\\s*,\\s*");
            for (String v : vardefs) {
                if (isdefined(v, context))
                    return null;
            }
            return arg;
        }

        public void explain(String var, String arg, Appendable buf) throws IOException {
            buf.append("If [");
            String[] vars = getVariables(var);
            boolean b = false;
            for (String v : vars) {
                if (b)
                    buf.append(',');
                else
                    b = true;
                buf.append("'").append(v).append("'");
            }
            buf.append("] is undefined, or a zero length list, then insert '").append(arg).append("'");
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy