org.structr.schema.action.Function.java Source code

Java tutorial

Introduction

Here is the source code for org.structr.schema.action.Function.java

Source

/**
 * Copyright (C) 2010-2016 Structr GmbH
 *
 * This file is part of Structr <http://structr.org>.
 *
 * Structr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Structr is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Structr.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.structr.schema.action;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang3.math.NumberUtils;
import org.structr.common.error.FrameworkException;
import org.structr.core.GraphObject;
import org.structr.core.GraphObjectMap;
import org.structr.core.Services;
import org.structr.core.app.StructrApp;
import org.structr.core.parser.Functions;
import org.structr.core.property.DateProperty;
import org.structr.core.property.StringProperty;
import org.structr.schema.parser.DatePropertyParser;

/**
 *
 *
 */
public abstract class Function<S, T> extends Hint {

    private static final Logger logger = Logger.getLogger(Functions.class.getName());

    public abstract T apply(ActionContext ctx, GraphObject entity, S[] sources) throws FrameworkException;

    public abstract String usage(boolean inJavaScriptContext);

    /**
     * Test if the given object array has a minimum length and all its elements are not null.
     *
     * @param array
     * @param minLength If null, don't do length check
     * @return true if array has min length and all elements are not null
     */
    protected boolean arrayHasMinLengthAndAllElementsNotNull(final Object[] array, final Integer minLength) {

        if (array != null && minLength != null && array.length >= minLength) {

            for (final Object element : array) {

                if (element == null) {
                    return false;
                }

            }

            return true;
        }

        return false;
    }

    /**
     * Test if the given object array has a minimum length and all its elements are not null.
     *
     * @param array
     * @param minLength
     * @param maxLength
     * @return true if array has min length and all elements are not null
     */
    protected boolean arrayHasMinLengthAndMaxLengthAndAllElementsNotNull(final Object[] array, final int minLength,
            final int maxLength) {

        if (array != null && array.length >= minLength && array.length <= maxLength) {

            for (final Object element : array) {

                if (element == null) {
                    return false;
                }

            }

            return true;
        }

        return false;
    }

    /**
     * Test if the given object array has exact the given length and all its elements are not null.
     *
     * @param array
     * @param length
     * @return true if array has exact length and all elements are not null
     */
    protected boolean arrayHasLengthAndAllElementsNotNull(final Object[] array, final int length) {

        if (array != null && array.length == length) {

            for (final Object element : array) {

                if (element == null) {
                    return false;
                }

            }

            return true;
        }

        return false;
    }

    protected Double getDoubleOrNull(final Object obj) {

        try {

            if (obj instanceof Date) {

                return (double) ((Date) obj).getTime();

            } else if (obj instanceof Number) {

                return ((Number) obj).doubleValue();

            } else {

                Date date = DatePropertyParser.parseISO8601DateString(obj.toString());

                if (date != null) {

                    return (double) (date).getTime();
                }

                return Double.parseDouble(obj.toString());

            }

        } catch (Throwable t) {

            t.printStackTrace();
        }

        return null;
    }

    protected Integer parseInt(final Object source) {

        if (source instanceof Integer) {

            return ((Integer) source);
        }

        if (source instanceof Number) {

            return ((Number) source).intValue();
        }

        if (source instanceof String) {

            return Integer.parseInt((String) source);
        }

        return null;
    }

    protected String encodeURL(final String source) {

        try {
            return URLEncoder.encode(source, "UTF-8");

        } catch (UnsupportedEncodingException ex) {
        }

        // fallback, unencoded
        return source;
    }

    protected boolean valueEquals(final Object obj1, final Object obj2) {

        if (obj1 instanceof Enum || obj2 instanceof Enum) {

            return obj1.toString().equals(obj2.toString());

        }

        return eq(obj1, obj2);
    }

    protected double getDoubleForComparison(final Object obj) {

        if (obj instanceof Number) {

            return ((Number) obj).doubleValue();

        } else {

            try {
                return Double.valueOf(obj.toString());

            } catch (Throwable t) {

                t.printStackTrace();
            }
        }

        return 0.0;
    }

    protected boolean gt(final Object o1, final Object o2) {

        if (o1 != null && o2 == null) {
            return true;
        }

        if ((o1 == null && o2 != null) || (o1 == null && o2 == null)) {
            return false;
        }

        if (o1 instanceof Number && o2 instanceof Number) {

            return compareNumberNumber(o1, o2) > 0;

        } else if (o1 instanceof String && o2 instanceof String) {

            return compareStringString(o1, o2) > 0;

        } else if (o1 instanceof Date && o2 instanceof Date) {

            return compareDateDate(o1, o2) > 0;

        } else if (o1 instanceof Date && o2 instanceof String) {

            return compareDateString(o1, o2) > 0;

        } else if (o1 instanceof String && o2 instanceof Date) {

            return compareStringDate(o1, o2) > 0;

        } else if (o1 instanceof Boolean && o2 instanceof String) {

            return compareBooleanString((Boolean) o1, (String) o2) > 0;

        } else if (o1 instanceof String && o2 instanceof Boolean) {

            return compareStringBoolean((String) o1, (Boolean) o2) > 0;

        } else if (o1 instanceof Number && o2 instanceof String) {

            return compareNumberString((Number) o1, (String) o2) > 0;

        } else if (o1 instanceof String && o2 instanceof Number) {

            return compareStringNumber((String) o1, (Number) o2) > 0;

        } else {

            return compareStringString(o1.toString(), o2.toString()) > 0;

        }
    }

    protected boolean lt(final Object o1, final Object o2) {

        if (o1 == null && o2 != null) {
            return true;
        }

        if ((o1 != null && o2 == null) || (o1 == null && o2 == null)) {
            return false;
        }

        if (o1 instanceof Number && o2 instanceof Number) {

            return compareNumberNumber(o1, o2) < 0;

        } else if (o1 instanceof String && o2 instanceof String) {

            return compareStringString(o1, o2) < 0;

        } else if (o1 instanceof Date && o2 instanceof Date) {

            return compareDateDate(o1, o2) < 0;

        } else if (o1 instanceof Date && o2 instanceof String) {

            return compareDateString(o1, o2) < 0;

        } else if (o1 instanceof String && o2 instanceof Date) {

            return compareStringDate(o1, o2) < 0;

        } else if (o1 instanceof Boolean && o2 instanceof String) {

            return compareBooleanString((Boolean) o1, (String) o2) < 0;

        } else if (o1 instanceof String && o2 instanceof Boolean) {

            return compareStringBoolean((String) o1, (Boolean) o2) < 0;

        } else if (o1 instanceof Number && o2 instanceof String) {

            return compareNumberString((Number) o1, (String) o2) < 0;

        } else if (o1 instanceof String && o2 instanceof Number) {

            return compareStringNumber((String) o1, (Number) o2) < 0;

        } else {

            return compareStringString(o1.toString(), o2.toString()) < 0;

        }
    }

    protected boolean gte(final Object o1, final Object o2) {
        return eq(o1, o2) || gt(o1, o2);
    }

    protected boolean lte(final Object o1, final Object o2) {
        return eq(o1, o2) || lt(o1, o2);
    }

    protected String getSandboxFileName(final String source) throws IOException {

        final File sandboxFile = new File(source);
        final String fileName = sandboxFile.getName();
        final String basePath = StructrApp.getConfigurationValue(Services.BASE_PATH);

        if (!basePath.isEmpty()) {

            final String defaultExchangePath = basePath.endsWith("/") ? basePath.concat("exchange")
                    : basePath.concat("/exchange");
            String exchangeDir = StructrApp.getConfigurationValue(Services.DATA_EXCHANGE_PATH, defaultExchangePath);

            if (!exchangeDir.endsWith("/")) {
                exchangeDir = exchangeDir.concat("/");
            }

            // create exchange directory
            final File dir = new File(exchangeDir);
            if (!dir.exists()) {

                dir.mkdirs();
            }

            // return sandboxed file name
            return exchangeDir.concat(fileName);

        } else {

            logger.log(Level.WARNING,
                    "Unable to determine base.path from structr.conf, no data input/output possible.");
        }

        return null;
    }

    protected static String serialize(final Gson gson, final Map<String, Object> map) {
        return gson.toJson(map, new TypeToken<Map<String, String>>() {
        }.getType());
    }

    protected static Map<String, Object> deserialize(final Gson gson, final String source) {
        return gson.fromJson(source, new TypeToken<Map<String, Object>>() {
        }.getType());
    }

    protected void recursivelyConvertMapToGraphObjectMap(final GraphObjectMap destination,
            final Map<String, Object> source, final int depth) {

        if (depth > 20) {
            return;
        }

        for (final Map.Entry<String, Object> entry : source.entrySet()) {

            final String key = entry.getKey();
            final Object value = entry.getValue();

            if (value instanceof Map) {

                final Map<String, Object> map = (Map<String, Object>) value;
                final GraphObjectMap obj = new GraphObjectMap();

                destination.put(new StringProperty(key), obj);

                recursivelyConvertMapToGraphObjectMap(obj, map, depth + 1);

            } else if (value instanceof Collection) {

                final List list = new LinkedList();
                final Collection collection = (Collection) value;

                for (final Object obj : collection) {

                    if (obj instanceof Map) {

                        final GraphObjectMap container = new GraphObjectMap();
                        list.add(container);

                        recursivelyConvertMapToGraphObjectMap(container, (Map<String, Object>) obj, depth + 1);

                    } else {

                        list.add(obj);
                    }
                }

                destination.put(new StringProperty(key), list);

            } else {

                destination.put(new StringProperty(key), value);
            }
        }
    }

    public static Object numberOrString(final String value) {

        if (value != null) {

            if ("true".equals(value.toLowerCase())) {
                return true;
            }

            if ("false".equals(value.toLowerCase())) {
                return false;
            }

            if (NumberUtils.isNumber(value)) {
                return NumberUtils.createNumber(value);
            }
        }

        return value;
    }

    // ----- private methods -----
    private boolean eq(final Object o1, final Object o2) {

        if (o1 == null && o2 == null) {
            return true;
        }

        if ((o1 == null && o2 != null) || (o1 != null && o2 == null)) {
            return false;
        }

        try {

            if (o1 instanceof Number && o2 instanceof Number) {

                return compareNumberNumber(o1, o2) == 0;

            } else if (o1 instanceof String && o2 instanceof String) {

                return compareStringString(o1, o2) == 0;

            } else if (o1 instanceof Date && o2 instanceof Date) {

                return compareDateDate(o1, o2) == 0;

            } else if (o1 instanceof Date && o2 instanceof String) {

                return compareDateString(o1, o2) == 0;

            } else if (o1 instanceof String && o2 instanceof Date) {

                return compareStringDate(o1, o2) == 0;

            } else if (o1 instanceof Boolean && o2 instanceof String) {

                return compareBooleanString((Boolean) o1, (String) o2) == 0;

            } else if (o1 instanceof String && o2 instanceof Boolean) {

                return compareStringBoolean((String) o1, (Boolean) o2) == 0;

            } else if (o1 instanceof Number && o2 instanceof String) {

                return compareNumberString((Number) o1, (String) o2) == 0;

            } else if (o1 instanceof String && o2 instanceof Number) {

                return compareStringNumber((String) o1, (Number) o2) == 0;

            } else {

                return compareStringString(o1.toString(), o2.toString()) == 0;

            }

        } catch (NumberFormatException nfe) {

            return false;

        }
    }

    private int compareBooleanBoolean(final Object o1, final Object o2) {

        final Boolean value1 = (Boolean) o1;
        final Boolean value2 = (Boolean) o2;

        return value1.compareTo(value2);
    }

    private int compareNumberNumber(final Object o1, final Object o2) {

        final Double value1 = getDoubleForComparison(o1);
        final Double value2 = getDoubleForComparison(o2);

        return value1.compareTo(value2);
    }

    private int compareStringString(final Object o1, final Object o2) {

        final String value1 = (String) o1;
        final String value2 = (String) o2;

        return value1.compareTo(value2);
    }

    private int compareDateDate(final Object o1, final Object o2) {

        final Date value1 = (Date) o1;
        final Date value2 = (Date) o2;

        return value1.compareTo(value2);
    }

    private int compareDateString(final Object o1, final Object o2) {

        final String value1 = DatePropertyParser.format((Date) o1, DateProperty.DEFAULT_FORMAT);
        final String value2 = (String) o2;

        return value1.compareTo(value2);
    }

    private int compareStringDate(final Object o1, final Object o2) {

        final String value1 = (String) o1;
        final String value2 = DatePropertyParser.format((Date) o2, DateProperty.DEFAULT_FORMAT);

        return value1.compareTo(value2);
    }

    private int compareBooleanString(final Boolean o1, final String o2) {
        return o1.compareTo(Boolean.valueOf(o2));
    }

    private int compareStringBoolean(final String o1, final Boolean o2) {
        return Boolean.valueOf(o1).compareTo(o2);
    }

    private int compareNumberString(final Number o1, final String o2) {

        final Double value1 = getDoubleForComparison(o1);
        Double value2;
        try {
            value2 = Double.parseDouble(o2);

        } catch (NumberFormatException nfe) {
            value2 = Double.NEGATIVE_INFINITY;
        }

        return value1.compareTo(value2);

    }

    private int compareStringNumber(final String o1, final Number o2) {

        Double value1;
        try {
            value1 = Double.parseDouble(o1);
        } catch (NumberFormatException nfe) {
            value1 = Double.NEGATIVE_INFINITY;
        }
        final Double value2 = getDoubleForComparison(o2);

        return value1.compareTo(value2);
    }
}