org.wicketstuff.dojo11.AbstractDefaultDojoBehavior.java Source code

Java tutorial

Introduction

Here is the source code for org.wicketstuff.dojo11.AbstractDefaultDojoBehavior.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.wicketstuff.dojo11;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.wicket.Application;
import org.apache.wicket.Component;
import org.apache.wicket.RuntimeConfigurationType;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.request.resource.CompressedResourceReference;
import org.apache.wicket.request.resource.PackageResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.util.collections.MiniMap;
import org.wicketstuff.dojo11.application.DojoSettings;
import org.wicketstuff.dojo11.application.IDojoApplication;
import org.wicketstuff.dojo11.application.IDojoSettings;
import org.wicketstuff.dojo11.templates.DojoPackagedTextTemplate;

/**
 * Handles event requests using Dojo.
 * <p>
 * This class is mainly here to automatically add the javascript files you need.
 * As header contributions are done once per class, you can have multiple
 * instances/ subclasses without having duplicate header contributions.
 * </p>
 * <p> this class use {@link AjaxRequestTarget} to respond to XMLHttpRequest </p>
 * 
 * <p>
 * By default this behavior will use the package dojo distributiuon included in this jar. If you want to use an other 
 * Dojo Distribution (A custom one to fit to your need), You should write the following code in your {@link Application} to
 * use a custom {@link CompressedResourceReference}
 * <pre>
 *  CompressedResourceReference myCustomDojo = new CompressedResourceReference([...]);
 *    setMetaData(AbstractDefaultDojoBehavior.USE_CUSTOM_DOJO_DIST, myCustomDojo);
 * </pre>
 * <b>WARNING</b> : the package dojo distribution contains some patches on dojo. If you use your own
 * distribution it can break some component behaviors.
 * </p>
 * 
 * @see <a href="http://dojotoolkit.org/">Dojo</a>
 * @author Eelco Hillenius
 */
public abstract class AbstractDefaultDojoBehavior
        extends AbstractDefaultAjaxBehavior /*implements IAjaxIndicatorAware*/
{
    private static final long serialVersionUID = 1L;

    /** A unique ID for a piece of JavaScript that registers the wicketstuff dojo namespace */
    private static final String DOJO_MODULES_ID = AbstractDefaultDojoBehavior.class.getName() + "::modules::";

    /** The wicketstuff dojo module */
    //   private static final DojoModule WICKETSTUFF_MODULE = new DojoModuleImpl("wicketstuff", AbstractDefaultDojoBehavior.class);

    /**
     * @see org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#renderHead(org.apache.wicket.markup.html.IHeaderResponse)
     */
    public void renderHead(Component c, IHeaderResponse response) {
        super.renderHead(c, response);

        IDojoSettings dojoSettings = ((IDojoApplication) Application.get()).getDojoSettings();
        List<ResourceReference> dojoResourceReferences = dojoSettings.getDojoResourceReferences();

        renderConfig(response);

        for (ResourceReference r : dojoResourceReferences) {
            response.renderJavaScriptReference(r);
        }

        registerDojoModulePathes(response, getDojoModules());
    }

    protected void renderConfig(IHeaderResponse response) {
        DojoPackagedTextTemplate template = new DojoPackagedTextTemplate(AbstractDefaultDojoBehavior.class,
                AbstractDefaultDojoBehavior.class.getSimpleName() + ".js");
        MiniMap map = new MiniMap(3);
        map.put("debug", RuntimeConfigurationType.DEVELOPMENT.equals(Application.get().getConfigurationType()));
        map.put("baseUrl", DojoSettings.get().getDojoBaseUrl());
        map.put("locale", ((IDojoApplication) Application.get()).getDojoSettings().getDefaultLocale().toString()
                .replace('_', '-'));
        response.renderJavaScript(template.asString(map), template.getStaticKey());
    }

    /**
     * Register a specific dojo module.
     * @param response
     * @param modules
     */
    protected void registerDojoModulePathes(IHeaderResponse response, Collection<DojoModule> modules) {
        if (modules != null && modules.size() > 0) {
            StringBuilder buf = new StringBuilder();
            for (DojoModule module : modules) {
                registerDojoModulePath(buf, module);
            }
            response.renderJavaScript(buf.toString(), DOJO_MODULES_ID + "module");
        }
    }

    private void registerDojoModulePath(StringBuilder javascript, DojoModule module) {
        ResourceReference dojoReference = getDojoResourceReference();
        String dojoUrl = RequestCycle.get().urlFor(dojoReference, new PageParameters()).toString();

        //FIXME : investigate on url resolving : http://81.17.46.170:8090/jira/browse/DOJO-67

        // count the depth to determine the relative path
        String url = "";

        int slash = 0; // count /
        int last = 0;
        while (last > -1) {
            last = dojoUrl.indexOf("/", last + 1);
            if (last > -1) {
                slash++;
            }
        }

        //count ../
        //each "../" should remove 2 "/" :
        //     - One because it is contained in "../"
        //     - An other because of the meaning of "../"
        last = 0;
        while (last > -1) {
            last = dojoUrl.indexOf("../", last);
            if (last > -1) {
                dojoUrl = dojoUrl.substring(last + "../".length());
                slash = slash - 2;
            }
        }

        for (int i = 0; i < slash; i++) {
            url += "../";
        }

        ResourceReference moduleReference = new PackageResourceReference(module.getScope(), module.getPath());
        String moduleUrl = RequestCycle.get().urlFor(moduleReference, new PageParameters()).toString();
        url = url + moduleUrl;
        //remove / at the end if exists
        if (url.charAt(url.length() - 1) == '/') {
            url = url.substring(0, url.length() - 1);
        }

        javascript.append("dojo.registerModulePath(\"" + module.getNamespace() + "\", \"" + url + "\");\n");
    }

    /**
     * XXX untested, using first ref might not work as expected
     * @return reference to the Dojo scripts.
     */
    public ResourceReference getDojoResourceReference() {
        return ((IDojoApplication) Application.get()).getDojoSettings().getDojoResourceReferences().get(0);
    }

    //   /**
    //    * return the indicator Id to show it if it is in the page
    //    * @return the indicator Id to show it if it is in the page
    //    */
    //   public String getAjaxIndicatorMarkupId()
    //   {
    //      return new WicketAjaxIndicatorAppender().getMarkupId();
    //   }
    //
    //   /**
    //    * return the ajax call decorator to do more than hide or show an image
    //    * @return the ajax call decorator to do more than hide or show an image
    //    */
    //   protected IAjaxCallDecorator getAjaxCallDecorator()
    //   {
    //      return new DojoIndicatorHandlerHelper(getComponent()).getAjaxCallDecorator();
    //   }

    /**
     * @return collection of modules that should be registered.
     */
    protected final Collection<DojoModule> getDojoModules() {
        Collection<DojoModule> modules = new ArrayList<DojoModule>();
        modules.addAll(DojoSettings.get().getDojoModules());
        setDojoModules(modules);
        return modules;
    }

    /**
     * Allow classes to override this and add their own modules.
     * @param modules
     */
    protected void setDojoModules(Collection<DojoModule> modules) {
        //      modules.add(DOJO_MODULE);
        //      modules.add(DIJIT_MODULE);
        //      modules.add(DOJOX_MODULE);
        //modules.add(WICKETSTUFF_MODULE);
    }

    /**
     * Provides information about a dojo module.
     * 
     * @author B. Molenkamp
     */
    public static interface DojoModule {

        /**
         * Returns the scope. This scope will be used to calculate the relative
         * path to this module.
         * 
         * @return the scope
         */
        public Class<?> getScope();

        /**
         * Returns the namespace of this module.
         * 
         * @return the module's namespace
         */
        public String getNamespace();

        /**
         * Returns the path of this module starting from scope or null.
         * 
         * @return the module's path starting from scope
         */
        public String getPath();

    }

    /**
     * Abstract implementation of a dojo module. If the scope is not passed to
     * the constructor, or if it's null, it will use it's own class as a scope.
     * 
     * @author B. Molenkamp
     */
    public static class DojoModuleImpl implements DojoModule {

        private String moduleNamespace;
        private Class<?> scope;

        /**
         * Creates a module with the scope of the implementing class.
         * @param namespace
         */
        public DojoModuleImpl(String namespace) {
            this(namespace, null);
        }

        /**
         * Creates a module with the given namespace at the given scope. It will
         * use the scope to resolve anything from the namespace.
         * 
         * @param namespace
         * @param scope
         */
        public DojoModuleImpl(String namespace, Class<?> scope) {
            this.moduleNamespace = namespace;
            this.scope = scope == null ? AbstractDefaultDojoBehavior.class : scope;
        }

        /**
         * @see org.wicketstuff.dojo11.AbstractDefaultDojoBehavior.DojoModule#getNamespace()
         */
        public String getNamespace() {
            return this.moduleNamespace;
        }

        /**
         * @see org.wicketstuff.dojo11.AbstractDefaultDojoBehavior.DojoModule#getScope()
         */
        public Class<?> getScope() {
            return this.scope;
        }

        /**
         * @see org.wicketstuff.dojo11.AbstractDefaultDojoBehavior.DojoModule#getPath()
         */
        public String getPath() {
            return "";
        }

    }
}