de.innovationgate.wgpublisher.webtml.utils.ItemExpression.java Source code

Java tutorial

Introduction

Here is the source code for de.innovationgate.wgpublisher.webtml.utils.ItemExpression.java

Source

/*******************************************************************************
 * Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
 * 
 * This file is part of the OpenWGA server platform.
 * 
 * OpenWGA 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.
 * 
 * In addition, a special exception is granted by the copyright holders
 * of OpenWGA called "OpenWGA plugin exception". You should have received
 * a copy of this exception along with OpenWGA in file COPYING.
 * If not, see <http://www.openwga.com/gpl-plugin-exception>.
 * 
 * OpenWGA 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 OpenWGA in file COPYING.
 * If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

package de.innovationgate.wgpublisher.webtml.utils;

import java.io.IOException;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringEscapeUtils;

import de.innovationgate.utils.NullPlaceHolder;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGDocument;
import de.innovationgate.webgate.api.WGException;
import de.innovationgate.wga.server.api.WGA;
import de.innovationgate.wga.server.api.WebTMLFunctionArgumentSubstitutor;
import de.innovationgate.wgpublisher.WGACore;
import de.innovationgate.wgpublisher.expressions.ExpressionEngineFactory;
import de.innovationgate.wgpublisher.so.ManagedObject;
import de.innovationgate.wgpublisher.so.ScopeObjectRegistry.ScopeObject;
import de.innovationgate.wgpublisher.webtml.portlet.TMLPortlet;
import de.innovationgate.wgpublisher.webtml.utils.TMLContext.ListVarContainer;

public class ItemExpression {

    private static final Pattern PATTERN_STRING_LITERAL = Pattern.compile("^'(.*)'$");

    private static final Pattern PATTERN_NUMBER_LITERAL = Pattern.compile("^(-??[0-9]+.??[0-9]*)$");

    private static final DecimalFormat DECIMALFORMAT_NUMBER_LITERAL = new DecimalFormat("0.#",
            DecimalFormatSymbols.getInstance(Locale.ENGLISH));

    private String _fullItemName;
    private String _itemName;
    private String _itemCall = null;
    private boolean _enhancedExpressions;
    private TMLContext _context;
    private List<Runnable> _afterRetrieval = new ArrayList<Runnable>();

    public ItemExpression(TMLContext context, String itemName) {
        _context = context;
        _fullItemName = itemName;
        _itemName = itemName;
        _enhancedExpressions = context.isEnhancedItemExpressions();

        if (_enhancedExpressions && _fullItemName != null) {
            int dotPos = _fullItemName.indexOf(".");
            if (dotPos != -1) {
                _itemName = _fullItemName.substring(0, dotPos);
                _itemCall = _fullItemName.substring(dotPos + 1);
            }
        }

    }

    public Object retrieve(Map<String, Object> params, List<Object> unnamedParams, Map<String, Object> objects)
            throws WGException {

        Object itemValue = retrieveItemValue();

        if (_itemCall != null && itemValue != null) {
            itemValue = performItemCall(itemValue, params, unnamedParams, objects);
        }

        for (Runnable cleanup : _afterRetrieval) {
            cleanup.run();
        }

        return itemValue;

    }

    private Object performItemCall(Object object, Map<String, Object> params, List<Object> unnamedParams,
            Map<String, Object> systemInjections) throws WGException {

        WGA wga = WGA.get(_context);
        Map<String, Object> allNamedParams = new HashMap<String, Object>();
        if (systemInjections != null) {
            for (Map.Entry<String, Object> entry : systemInjections.entrySet()) {
                allNamedParams.put("$" + entry.getKey(), entry.getValue());
            }
        }
        if (params != null) {
            allNamedParams.putAll(params);
        }

        Object value = wga.tmlscript().callMethod(object, _itemCall, allNamedParams, unnamedParams);

        if (value instanceof List<?>) {
            @SuppressWarnings("unchecked")
            List<Object> valueList = (List<Object>) value;
            value = new ListVarContainer(valueList);
        }

        return value;

    }

    private Object retrieveItemValue() throws WGException {

        if (_itemName == null) {
            return null;
        }

        if (_enhancedExpressions) {

            // String Literal (Match against full itemname bc. the decimal point, if present, has been misinterpreted as call chain. Also clear call information on match) 
            Matcher stringLiteralMatcher = PATTERN_STRING_LITERAL.matcher(_fullItemName);
            if (stringLiteralMatcher.matches()) {
                try {
                    String stringContent = stringLiteralMatcher.group(1);
                    StringWriter out = new StringWriter();
                    StringEscapeUtils.unescapeJavaScript(out, stringContent);
                    _itemCall = null;
                    return out.toString();
                } catch (IOException e) {
                    _context.addwarning(
                            "Exception interpreting string literal in item expression: " + _fullItemName, true);

                }
            }

            // Number literal (Match against full itemname bc. the decimal point, if present, has been misinterpreted as call chain. Also clear call information on match)
            Matcher numberLiteralMatcher = PATTERN_NUMBER_LITERAL.matcher(_fullItemName);
            if (numberLiteralMatcher.matches()) {
                try {
                    String numberContent = numberLiteralMatcher.group(1);
                    _itemCall = null;
                    return DECIMALFORMAT_NUMBER_LITERAL.parse(numberContent);
                } catch (ParseException e) {
                    _context.addwarning("Parse error interpreting number literal in item expression: "
                            + _fullItemName + ": " + e.getMessage(), true);
                }
            }

            // Boolean literal
            if (Boolean.TRUE.toString().equals(_itemName)) {
                return true;
            }
            if (Boolean.FALSE.toString().equals(_itemName)) {
                return false;
            }

            // Null literal
            if ("null".equals(_itemName)) {
                return null;
            }

            // Undefined literal
            if ("undefined".equals(_itemName)) {
                return ExpressionEngineFactory.getTMLScriptEngine().getUndefined();
            }

            if (_itemName.startsWith("$")) {

                // Controllers
                if (_itemName.equals("$pc")) {
                    Object pc = retrievePortletController();
                    if (pc != null) {
                        return pc;
                    }
                }

                if (_itemName.equals("$mc")) {
                    Object mc = retrieveModuleController();
                    if (mc != null) {
                        return mc;
                    }
                }

                // WebTML substitution variables
                Object substitutedValue = new WebTMLFunctionArgumentSubstitutor(WGA.get(_context))
                        .getArgumentValue(_itemName);
                if (substitutedValue != null) {
                    if (substitutedValue instanceof List<?>) {
                        @SuppressWarnings("unchecked")
                        List<Object> substitutedValueList = (List<Object>) substitutedValue;
                        substitutedValue = new ListVarContainer(substitutedValueList);
                    }
                    return substitutedValue;
                }
            }

        }

        // WebTML variables
        Object value = _context.retrieveVar(_itemName);
        if (!(value instanceof NullPlaceHolder)) {
            return value;
        }

        // Mapped item values
        Object result = _context.getMappedItemValue(_itemName.toLowerCase());
        if (result != null) {
            return result;
        }

        // Content items
        WGDocument doc = _context.getdocument();
        if (doc.hasItem(_itemName)) {
            return doc.getItemValue(_itemName);
        }

        // Symbolizes that no value could be found
        return new NullPlaceHolder();

    }

    private Object retrieveModuleController() throws WGException {
        final ManagedObject controller = _context.fetchModuleController();
        if (controller != null) {
            controller.beforeUsage();
            _afterRetrieval.add(new Runnable() {
                @Override
                public void run() {
                    try {
                        controller.afterUsage();
                    } catch (WGException e) {
                        _context.getlog().error("Exception in module controller cleanup", e);
                    }
                }

            });
            return controller.getObject();
        } else {
            return null;
        }
    }

    private Object retrievePortletController() throws WGException {
        WGA wga = WGA.get(_context);
        final TMLPortlet portlet = _context.getportlet();
        if (portlet == null) {
            return null;
        }

        final ScopeObject controller = portlet.getState().fetchController(wga);
        if (controller == null) {
            return null;
        }

        controller.beforeUsage();
        _afterRetrieval.add(new Runnable() {
            @Override
            public void run() {

                try {
                    controller.afterUsage();
                } catch (WGException e) {
                    _context.getlog().error("Exception cleaning up from portlet controller", e);
                }
            }

        });

        return controller.getObject();
    }

}