org.ofbiz.angularjs.event.AngularJsEvents.java Source code

Java tutorial

Introduction

Here is the source code for org.ofbiz.angularjs.event.AngularJsEvents.java

Source

/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  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.
 *******************************************************************************/
package org.ofbiz.angularjs.event;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringEscapeUtils;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.ofbiz.angularjs.application.ModelNgApplication;
import org.ofbiz.angularjs.application.ModelNgController;
import org.ofbiz.angularjs.application.ModelNgState;
import org.ofbiz.angularjs.application.ModelNgView;
import org.ofbiz.angularjs.component.NgComponentConfig;
import org.ofbiz.angularjs.component.NgComponentConfig.ClasspathInfo;
import org.ofbiz.angularjs.directive.ModelNgDirective;
import org.ofbiz.angularjs.factory.ModelNgFactory;
import org.ofbiz.angularjs.filter.ModelNgFilter;
import org.ofbiz.angularjs.javascript.JavaScriptClass;
import org.ofbiz.angularjs.javascript.JavaScriptFactory;
import org.ofbiz.angularjs.javascript.JavaScriptRenderer;
import org.ofbiz.angularjs.model.NgModelDispatcherContext;
import org.ofbiz.angularjs.module.ModelNgModule;
import org.ofbiz.angularjs.module.ModelNgModule.ModelJavaScript;
import org.ofbiz.angularjs.provider.ModelNgProvider;
import org.ofbiz.angularjs.service.ModelNgService;
import org.ofbiz.base.lang.JSON;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.FileUtil;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.webapp.control.LoginWorker;

public class AngularJsEvents {

    public final static String module = AngularJsEvents.class.getName();
    public final static String NG_APPS_INIT_PATH = "/WEB-INF/ng-apps.xml";

    private static String checkPath(String path, boolean fullPath, HttpServletRequest request) {
        String checkedPath = null;
        if (fullPath) {
            String protocol = "http";
            if (request.isSecure()) {
                protocol = "https";
            }
            checkedPath = protocol + "://" + path;
        } else {
            checkedPath = path;
        }
        return checkedPath;
    }

    private static void buildJsClasses(List<File> files, StringBuilder builder) throws IOException {
        JavaScriptFactory.clear();

        Context context = Context.enter();
        for (File file : files) {
            String packageName = null;
            String className = null;
            try {
                if (file.getAbsolutePath().endsWith(".js")) {
                    Scriptable scope = context.initStandardObjects();
                    BufferedReader reader = new BufferedReader(new FileReader(file));
                    String packageLine = reader.readLine();

                    // find package name
                    Pattern packagePattern = Pattern.compile(".*?package.*?(.*?);");
                    Matcher packageMatcher = packagePattern.matcher(packageLine);
                    while (packageMatcher.find()) {
                        packageName = packageMatcher.group(1).trim();
                    }

                    context.evaluateReader(scope, reader, null, 2, null);
                    className = file.getName().replace(".js", "").trim();
                    Function classFunction = (Function) scope.get(className, scope);
                    JavaScriptFactory.addJavaScriptClass(packageName, className, classFunction, context);
                }
            } catch (Exception e) {
                Debug.logError(e, "Could not compile " + packageName + "." + className + " class", module);
            }
        }
        Context.exit();

        JavaScriptRenderer renderer = new JavaScriptRenderer(builder);
        renderer.render(JavaScriptFactory.getRootJavaScriptPackages());
    }

    private static void buildCombindAllModule(StringBuilder builder) {
        builder.append("\nangular.module('combine.all', [");

        // modules
        List<String> moduleNames = new LinkedList<String>();
        for (ModelNgModule modelModule : NgModelDispatcherContext.getAllModelNgModules()) {
            moduleNames.add("'" + modelModule.name + "'");
        }

        if (UtilValidate.isNotEmpty(moduleNames)) {
            builder.append(StringUtil.join(moduleNames, ","));
        }
        builder.append("])\n");

        // directives
        String emptyJsFunction = "function() {}";
        for (ModelNgDirective modelNgDirective : NgModelDispatcherContext.getAllModelNgDirectives()) {
            String directiveJsFunction = createDirectiveJsFunction(modelNgDirective);
            if (UtilValidate.isEmpty(directiveJsFunction)) {
                directiveJsFunction = emptyJsFunction;
            }
            builder.append(".directive('" + modelNgDirective.name + "', " + directiveJsFunction + ")\n");
        }

        // filters
        for (ModelNgFilter modelNgFilter : NgModelDispatcherContext.getAllModelNgFilters()) {
            builder.append(".filter('" + modelNgFilter.name + "', " + modelNgFilter.location + ")\n");
        }

        // services
        for (ModelNgService modelNgService : NgModelDispatcherContext.getAllModelNgServices()) {
            builder.append(".service('" + modelNgService.name + "', " + modelNgService.location + ")\n");
        }

        // providers
        for (ModelNgProvider modelNgProvider : NgModelDispatcherContext.getAllModelNgProviders()) {
            builder.append(".provider('" + modelNgProvider.name + "', " + modelNgProvider.location + "."
                    + modelNgProvider.invoke + ")\n");
        }

        // factories
        for (ModelNgFactory modelNgFactory : NgModelDispatcherContext.getAllModelNgFactories()) {
            builder.append(".factory('" + modelNgFactory.name + "', " + modelNgFactory.location + ")\n");
        }

        builder.append(";");
    }

    private static void buildAppJsFunction(String name, String defaultState, boolean disableAutoScrolling,
            List<? extends ModelNgController> modelNgControllers, List<? extends ModelNgState> modelNgStates,
            StringBuilder builder) {
        builder.append("\nangular.module('" + name + "', ['combine.all'])");

        // controllers
        StringBuilder controllersBuilder = new StringBuilder();
        if (UtilValidate.isNotEmpty(modelNgControllers)) {
            for (ModelNgController modelNgController : modelNgControllers) {
                String controllerName = modelNgController.name;
                if (UtilValidate.isEmpty(controllerName)) {
                    controllerName = modelNgController.path;
                }

                if (UtilValidate.isNotEmpty(controllerName)) {
                    controllersBuilder
                            .append("\n.controller(\"" + controllerName + "\", " + modelNgController.path + ")");
                }
            }
        }
        builder.append(controllersBuilder);

        builder.append("\n.config(function($stateProvider, $urlRouterProvider, $anchorScrollProvider) {\n");

        String defaultUrl = "";
        List<String> defaultStateTokens = StringUtil.split(defaultState, ".");

        // states
        StringBuilder statesBuilder = new StringBuilder();
        if (UtilValidate.isNotEmpty(modelNgStates)) {
            statesBuilder.append("\n$stateProvider");
            for (ModelNgState modelNgState : modelNgStates) {

                // append default URL
                String defaultStateTokenTail = "";
                for (String defaultStateToken : defaultStateTokens) {
                    defaultStateTokenTail += defaultStateToken;

                    if (UtilValidate.isNotEmpty(defaultStateTokenTail)
                            && defaultStateTokenTail.equals(modelNgState.name)) {
                        defaultUrl += modelNgState.url;
                        break;
                    }

                    defaultStateTokenTail += ".";
                }

                statesBuilder.append("\n//- State[" + modelNgState.name + "] is abstract[" + modelNgState.isAbstract
                        + "] with URL[" + modelNgState.url + "]\n");
                statesBuilder.append(".state(\"" + modelNgState.name + "\", {");
                statesBuilder.append("abstract: " + modelNgState.isAbstract + ",");
                statesBuilder.append("url: \"" + modelNgState.url + "\",");
                statesBuilder.append("views: {");

                List<String> viewDefs = new LinkedList<String>();
                for (ModelNgView modelNgView : modelNgState.getModelNgViews()) {
                    statesBuilder.append("\n//-- View[" + modelNgView.name + "] with template URL["
                            + modelNgView.target + "] and controller[" + modelNgView.controller + "]\n");
                    viewDefs.add("\"" + modelNgView.name + "\": { templateUrl: \"" + modelNgView.target
                            + "\", controller: " + modelNgView.controller + ", controllerClassName: \""
                            + modelNgView.controller + "\"}");
                }
                statesBuilder.append(StringUtil.join(viewDefs, ","));

                statesBuilder.append("}})");
            }
        }

        // default path (One page can have only one default path)
        if (UtilValidate.isNotEmpty(defaultUrl)) {
            builder.append("//- Default URL[" + defaultUrl + "] of state[" + defaultState + "]\n\n");
            builder.append("\n$urlRouterProvider.otherwise(\"" + defaultUrl + "\");");
        }

        builder.append(statesBuilder);
        builder.append(";");

        builder.append("})\n");

        // disable auto scrolling
        if (disableAutoScrolling) {
            builder.append(".value('$anchorScroll', angular.noop)");
        }

        // run
        builder.append(
                "\n.run(function($rootScope, $state, $stateParams, $templateFactory, $templateCache, $http) {");
        builder.append("\n$rootScope.$state = $state;");
        builder.append("\n$rootScope.$stateParams = $stateParams;");

        // override $templateFactory.fromUrl() function and add X-Requested-With header
        builder.append("\n$templateFactory.fromUrl = function (url, params) {");
        builder.append("\n    if (angular.isFunction(url)) url = url(params);");
        builder.append("\n    if (url == null) return null;");
        builder.append("\n    else{");
        builder.append("\n        return $http");
        builder.append(
                "\n            .get(url, { cache: $templateCache, headers: { Accept: 'text/html', 'X-Requested-With': 'XMLHttpRequest' }})");
        builder.append("\n            .then(function(response) {");
        builder.append("\n                return response.data;");
        builder.append("\n            });");
        builder.append("\n   }");
        builder.append("\n};");

        builder.append("})");

        builder.append(";");
    }

    private static String createDirectiveJsFunction(ModelNgDirective modelNgDirective) {
        JavaScriptClass javaScriptClass = JavaScriptFactory.getJavaScriptClass(modelNgDirective.location);
        if (UtilValidate.isNotEmpty(javaScriptClass)) {
            // object builder
            StringBuilder objectBuilder = new StringBuilder();
            objectBuilder.append("var " + modelNgDirective.name + " = new " + modelNgDirective.location + "("
                    + javaScriptClass.getConstructorArgument() + ");");
            if (UtilValidate.isNotEmpty(modelNgDirective.replace)) {
                objectBuilder.append(modelNgDirective.name + ".replace = " + modelNgDirective.replace + ";");
            }
            if (UtilValidate.isNotEmpty(modelNgDirective.transclude)) {
                objectBuilder.append(modelNgDirective.name + ".transclude = " + modelNgDirective.transclude + ";");
            }
            if (UtilValidate.isNotEmpty(modelNgDirective.scope)) {
                objectBuilder.append(modelNgDirective.name + ".scope = " + modelNgDirective.scope + ";");
            }
            if (UtilValidate.isNotEmpty(modelNgDirective.priority)) {
                objectBuilder.append(modelNgDirective.name + ".priority = " + modelNgDirective.priority + ";");
            }
            if (UtilValidate.isNotEmpty(modelNgDirective.require)) {
                objectBuilder.append(modelNgDirective.name + ".require = \"" + modelNgDirective.require + "\";");
            }
            if (UtilValidate.isNotEmpty(modelNgDirective.restrict)) {
                objectBuilder.append(modelNgDirective.name + ".restrict = \"" + modelNgDirective.restrict + "\";");
            }

            StringBuilder builder = new StringBuilder();
            builder.append("function(" + javaScriptClass.getConstructorArgument() + ") {");
            builder.append(objectBuilder.toString());
            builder.append(" return " + modelNgDirective.name + ";");
            builder.append("}");
            return builder.toString();
        } else {
            return "";
        }
    }

    public static String buildMainJs(HttpServletRequest request, HttpServletResponse response) {

        StringBuilder builder = new StringBuilder();

        try {
            synchronized (AngularJsEvents.class) {
                // classes
                List<File> classFiles = new LinkedList<File>();
                List<ClasspathInfo> classpathResoruceInfos = NgComponentConfig.getAllClasspathResourceInfos();
                for (ClasspathInfo classpathResourceInfo : classpathResoruceInfos) {
                    try {
                        List<File> jsFiles = FileUtil.findFiles("js",
                                classpathResourceInfo.createResourceHandler().getFullLocation(), null, null);
                        classFiles.addAll(jsFiles);
                    } catch (Exception e) {
                        Debug.logWarning(e, module);
                    }
                }
                buildJsClasses(classFiles, builder);
            }

            // require
            builder.append("require.config({");
            builder.append("\nbaseUrl: \"/angularjs/control\",");
            builder.append("\nwaitSeconds: 15,");
            builder.append("\n});");
            builder.append("\nrequire([\n");

            // modules
            List<ModelNgModule> ngModules = NgModelDispatcherContext.getAllModelNgModules();
            List<String> moduleJsPaths = new LinkedList<String>();
            List<String> javaScriptPaths = new LinkedList<String>();

            for (ModelNgModule ngModule : ngModules) {
                String modulePath = checkPath(ngModule.location, false, request);
                for (ModelJavaScript modelJavaScript : ngModule.modelJavaScripts) {
                    String javaScriptPath = checkPath(modelJavaScript.path, modelJavaScript.fullPath, request);
                    javaScriptPaths.add("\n'" + javaScriptPath + "'");
                }
                moduleJsPaths.add("\n'" + modulePath + "'");
            }

            String moduleJsList = StringUtil.join(moduleJsPaths, ",");
            String javaScriptJsList = StringUtil.join(javaScriptPaths, ",");

            builder.append(moduleJsList);
            builder.append("], function() {");

            builder.append("\nrequire([\n");
            builder.append(javaScriptJsList);
            builder.append("\n], function() {");

            buildCombindAllModule(builder);

            builder.append("/*\n");
            builder.append("*\n");
            builder.append("* ============== Applications =================");
            builder.append("*\n");
            builder.append("*/\n");

            // apps
            for (ModelNgApplication modelNgApplication : NgModelDispatcherContext.getAllModelNgApplications()) {
                builder.append("\n// Application [" + modelNgApplication.name + "] with default state["
                        + modelNgApplication.defaultState + "] and disable auto scrolling["
                        + modelNgApplication.disableAutoScrolling + "]\n");
                buildAppJsFunction(modelNgApplication.name, modelNgApplication.defaultState,
                        modelNgApplication.disableAutoScrolling, modelNgApplication.getModelNgControllers(),
                        modelNgApplication.getModelNgStates(), builder);
            }

            // bootstrap
            for (ModelNgApplication modelNgApplication : NgModelDispatcherContext.getAllModelNgApplications()) {
                String elementName = "appElement_" + modelNgApplication.name;
                String elementId = modelNgApplication.name + "-app";
                builder.append("\nvar " + elementName + " = $('#" + elementId + "');");
                builder.append("\nif(" + elementName + ".length > 0) {");
                builder.append("\nangular.bootstrap(" + elementName + ", ['" + modelNgApplication.name + "']);");
                builder.append("\n}");
            }

            builder.append("\n});");

            builder.append("\n});");

            // return the JavaScript String
            String javaScriptString = builder.toString();
            response.setContentType("application/x-javascript; charset=UTF-8");

            response.setContentLength(javaScriptString.getBytes("UTF8").length);

            Writer out;
            try {
                out = response.getWriter();
                out.write(javaScriptString);
                out.flush();
            } catch (IOException e) {
                Debug.logError(e, module);
            }
        } catch (UnsupportedEncodingException e) {
            Debug.logError(e, "Problems with JavaScript encoding.", module);
        } catch (IOException e) {
            Debug.logError(e, "Problems with IO.", module);
        }

        return "success";
    }

    public static String error(HttpServletRequest request, HttpServletResponse response) {
        List<String> responseMessageList = new LinkedList<String>();
        String errorMessage = UtilGenerics.cast(request.getAttribute("_ERROR_MESSAGE_"));
        List<String> errorMessageList = UtilGenerics.cast(request.getAttribute("_ERROR_MESSAGE_LIST_"));
        if (UtilValidate.isNotEmpty(errorMessage)) {
            responseMessageList.add(StringEscapeUtils.unescapeHtml(errorMessage));
        }
        if (UtilValidate.isNotEmpty(errorMessageList)) {
            responseMessageList.addAll(errorMessageList);
        }

        Map<String, Object> results = new HashMap<String, Object>();
        results.put("_ERROR_MESSAGE_LIST_", responseMessageList);

        // set the X-JSON content type
        response.setContentType("application/x-json");
        try {
            JSON json = JSON.from(results);
            String jsonStr = json.toString();
            // jsonStr.length is not reliable for unicode characters
            response.setContentLength(jsonStr.getBytes("UTF8").length);

            // return the JSON String
            Writer out;
            out = response.getWriter();
            out.write(jsonStr);
            out.flush();
        } catch (UnsupportedEncodingException e) {
            Debug.logError("Problems with Json encoding: " + e, module);
        } catch (IOException e) {
            Debug.logError(e, module);
        }

        return "success";
    }

    public static String ajaxCheckLogin(HttpServletRequest request, HttpServletResponse response) {
        //TODO show AJAX login popup
        String result = LoginWorker.checkLogin(request, response);
        if ("error".equals(result)) {
            request.setAttribute("MESSAGE", "Please Login");
        } else {
            request.setAttribute("SUCCESS", "Please Login");
        }
        return "success";
    }
}