fiftyfive.wicket.js.JavaScriptDependencySettings.java Source code

Java tutorial

Introduction

Here is the source code for fiftyfive.wicket.js.JavaScriptDependencySettings.java

Source

/**
 * Copyright 2013 55 Minutes (http://www.55minutes.com)
 *
 * Licensed 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 fiftyfive.wicket.js;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import fiftyfive.wicket.js.locator.DefaultJavaScriptDependencyLocator;
import fiftyfive.wicket.js.locator.JavaScriptDependencyLocator;
import fiftyfive.wicket.js.locator.SearchLocation;
import fiftyfive.wicket.js.locator.SprocketsParser;
import fiftyfive.wicket.js.locator.SprocketsParserImplV4;
import org.apache.wicket.Application;
import org.apache.wicket.MetaDataKey;
import org.apache.wicket.request.resource.PackageResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.time.Duration;

/**
 * Settings that affect how JavaScript dependencies are located. To obtain an 
 * instance, use the static {@link #get get()} method.
 * <p>
 * Most applications using out-of-the-box JavaScript widgets will be served
 * well by the default settings. Before changing the settings, review
 * the <a href="package-summary.html#dependency-resolution">dependency
 * resolution guide</a> to get a complete understanding of how
 * fiftyfive-wicket-js loads JavaScript files and determines their
 * dependencies.
 * <p>
 * Then consider these scenarios:
 * <ol>
 * <li><b>If you want to disable dependency resolution entirely,
 *     call {@link #setSprocketsParser setSprocketsParser(null)}.</b></li>
 * <li><b>If your application already has a mechanism for including jQuery
 *     and/or jQuery UI in the &lt;head&gt;</b> (e.g. via your base page),
 *     then you should take care that fiftyfive-wicket-js is not including its
 *     own copies of these libraries. In this scenario, call
 *     {@link #setJQueryResource setJQueryResource()} and
 *     {@link #setJQueryUIResource setJQueryUIResource()} with references to
 *     the files that your application is already using (or {@code null},
 *     if you don't want fiftyfive-wicket-js to manage these resources at all).
 *     </li>
 * <li><b>If you have your own library of custom JavaScript files</b>,
 *     consider placing those files inside your classpath, and then use
 *     {@link #addLibraryPath addLibraryPath()} to make fiftyfive-wicket-js
 *     aware of them. Then you can use the {@code //=require} dependency syntax
 *     or the single argument constructor for
 *     {@link JavaScriptDependency JavaScriptDependency}, and those files will
 *     be found automatically.</li>
 * <li><b>If you'd like to change the jQuery UI CSS theme</b>, call
 *     {@link #setJQueryUICSSResource setJQueryUICSSResource()} with a
 *     reference to the desired CSS file, or {@code null} if you don't want
 *     fiftyfive-wicket-js to manage this for you.</li>
 * </ol>
 * 
 * @since 2.0
 */
public class JavaScriptDependencySettings {
    private static final MetaDataKey<JavaScriptDependencySettings> SETTINGS_KEY = new MetaDataKey<JavaScriptDependencySettings>() {
    };

    private Application app;
    private List<SearchLocation> locations;
    private ResourceReference jQueryResource;
    private ResourceReference jQueryUIResource;
    private ResourceReference jQueryUICSSResource;
    private Duration traversalCacheDuration;
    private String encoding;
    private JavaScriptDependencyLocator locator;
    private SprocketsParser sprocketsParser;

    /**
     * Returns the JavaScriptDependencySettings associated with the current
     * Wicket Application, creating a new default settings object if one does
     * not yet exist. This method can only be called within a Wicket thread.
     */
    public static JavaScriptDependencySettings get() {
        Application app = Application.get();
        if (null == app) {
            throw new IllegalStateException("No thread-local Wicket Application object was found. "
                    + "JavaScriptDependencySettings.get() can only be called " + "within a Wicket request.");
        }
        JavaScriptDependencySettings settings = app.getMetaData(SETTINGS_KEY);
        if (null == settings) {
            settings = new JavaScriptDependencySettings(app);
            app.setMetaData(SETTINGS_KEY, settings);
        }
        return settings;
    }

    /**
     * Constructs a settings object for the given application with a reasonable
     * set of defaults.
     */
    protected JavaScriptDependencySettings(Application app) {
        super();
        this.app = app;
        this.locator = new DefaultJavaScriptDependencyLocator();
        this.sprocketsParser = new SprocketsParserImplV4();

        this.locations = new ArrayList<SearchLocation>();

        Class<?> c = JavaScriptDependencySettings.class;
        addLibraryPath(c, "");
        addLibraryPath(c, "lib");
        addLibraryPath(c, "lib/fiftyfive-utils");

        this.jQueryResource = new PackageResourceReference(JavaScriptDependencySettings.class, "lib/jquery.js");
        this.jQueryUIResource = new PackageResourceReference(JavaScriptDependencySettings.class,
                "lib/jquery-ui.js");
        this.jQueryUICSSResource = new PackageResourceReference(JavaScriptDependencySettings.class,
                "lib/jquery-ui/themes/redmond/jquery-ui.redmond.css");
    }

    /**
     * Returns the JavaScriptDependencyLocator for this application.
     */
    public JavaScriptDependencyLocator getLocator() {
        return this.locator;
    }

    /**
     * Sets the JavaScriptDependencyLocator that should be used for this
     * application. By default this is
     * {@link DefaultJavaScriptDependencyLocator}.
     * 
     * @return {@code this} to allow chaining
     */
    public JavaScriptDependencySettings setLocator(JavaScriptDependencyLocator loc) {
        Args.notNull(loc, "loc");
        this.locator = loc;
        return this;
    }

    /**
     * Returns the list of classpath locations that will be used to find
     * JavaScript libraries.
     */
    public List<SearchLocation> getLibraryPaths() {
        return Collections.unmodifiableList(this.locations);
    }

    /**
     * Adds a classpath location to be used for locating JavaScript libraries.
     * A default list of locations from the fiftyfive-wicket-js JAR contains
     * jQuery, jQuery UI, cookies, fiftyfive-utils, jquery-scrollto and
     * strftime.
     * Call this method if you wish to add more libraries to this list, or if
     * you want your versions of the previously mentioned libraries to take
     * precedence. The paths that you add will be consulted before the
     * defaults.
     * <p>
     * Library paths are searched whenever you use the {@code //= require} syntax
     * for JavaScript dependencies, like this:
     * <pre class="example">
     * //= require libraryname</pre>
     * <p>
     * Or when you use
     * {@link JavaScriptDependency#JavaScriptDependency(String)} or
     * {@link MergedJavaScriptBuilder#addLibrary(String)}.
     * 
     * @return {@code this} to allow chaining
     */
    public JavaScriptDependencySettings addLibraryPath(Class<?> cls, String path) {
        this.locations.add(0, new SearchLocation(cls, path));
        return this;
    }

    /**
     * Returns the ResourceReference for the jQuery JavaScript file.
     */
    public ResourceReference getJQueryResource() {
        return this.jQueryResource;
    }

    /**
     * Sets the ResourceReference of the jQuery JavaScript file that should
     * be used whenever the dependency locator determines that jQuery is
     * needed. Pass {@code null} if you do not want the framework to include
     * jQuery automatically.
     * By default this refers to a copy of jQuery bundled in the
     * fiftyfive-wicket-js JAR.
     * 
     * @return {@code this} to allow chaining
     */
    public JavaScriptDependencySettings setJQueryResource(ResourceReference r) {
        this.jQueryResource = r;
        return this;
    }

    /**
     * Returns the ResourceReference for the jQuery UI JavaScript file.
     */
    public ResourceReference getJQueryUIResource() {
        return this.jQueryUIResource;
    }

    /**
     * Sets the ResourceReference of the jQuery UI JavaScript file that should
     * be used whenever the dependency locator determines that jQuery UI is
     * needed. Pass {@code null} if you do not want the framework to include
     * jQuery UI automatically.
     * By default this refers to a copy of jQuery UI bundled in the
     * fiftyfive-wicket-js JAR.
     * 
     * @return {@code this} to allow chaining
     */
    public JavaScriptDependencySettings setJQueryUIResource(ResourceReference r) {
        this.jQueryUIResource = r;
        return this;
    }

    /**
     * Returns the ResourceReference for the jQuery UI CSS theme file.
     */
    public ResourceReference getJQueryUICSSResource() {
        return this.jQueryUICSSResource;
    }

    /**
     * Sets the ResourceReference of the jQuery UI CSS theme file that should
     * be used whenever the dependency locator determines that jQuery UI is
     * needed. Pass {@code null} if you do not want the framework to include
     * jQuery UI CSS automatically.
     * By default this refers to a copy of jQuery UI "redmond" theme bundled
     * in the fiftyfive-wicket-js JAR.
     * 
     * @return {@code this} to allow chaining
     */
    public JavaScriptDependencySettings setJQueryUICSSResource(ResourceReference r) {
        this.jQueryUICSSResource = r;
        return this;
    }

    /**
     * Returns the strategy that will be used to parse Sprockets {@code //= require}
     * directives. The default is {@link SprocketsParserImplV4}.
     * @since 4.0
     */
    public SprocketsParser getSprocketsParser() {
        return this.sprocketsParser;
    }

    /**
     * Sets the strategy that will be used to parse Sprockets {@code //= require}
     * directives. The default strategy changed in fiftyfive-wicket-js 4.0. Starting
     * with 4.0 the default is {@link SprocketsParserImplV4}. If you would like to
     * restore the Sprockets behavior of earlier versions, pass an instance of
     * {@link fiftyfive.wicket.js.locator.SprocketsParserImplV3 SprocketsParserImplV3}.
     * <p>
     * The two versions differ in how they resolve paths specified in the
     * {@code //= require} directive. Refer to the documentation for each implementation
     * for further details.
     * <p>
     * Pass {@code null} to disable Sprockets parsing altogether.
     * 
     * @return {@code this} to allow chaining
     * @since 4.0
     */
    public JavaScriptDependencySettings setSprocketsParser(SprocketsParser p) {
        this.sprocketsParser = p;
        return this;
    }

    /**
     * Returns the duration that JavaScript dependency traversal results
     * (i.e. the tree of dependencies as determined by parsing sprockets
     * directives) are allowed to be stored in cache.
     */
    public Duration getTraversalCacheDuration() {
        // Interpret null based on application mode
        if (null == this.traversalCacheDuration) {
            if (this.app.usesDeploymentConfig()) {
                // Cache indefinitely
                return Duration.MAXIMUM;
            }
            // Disable cache
            return Duration.NONE;
        }
        return this.traversalCacheDuration;
    }

    /**
     * Sets the duration that JavaScript dependency traversal results
     * (i.e. the tree of dependencies as determined by parsing sprockets
     * directives) are allowed to be stored in cache.
     * <p>
     * If this is set to {@code null} (the default), at runtime this will be
     * interpreted as a value of zero (cache disabled) if the application is
     * in development mode, and will be interpreted as the maximum duration
     * (effectively indefinite) if the application is in deployment mode.
     * 
     * @return {@code this} to allow chaining
     */
    public JavaScriptDependencySettings setTraversalCacheDuration(Duration d) {
        this.traversalCacheDuration = d;
        return this;
    }

    /**
     * Returns the character encoding that will be used when parsing
     * JavaScript files.
     */
    public String getEncoding() {
        if (null == this.encoding) {
            String enc = this.app.getMarkupSettings().getDefaultMarkupEncoding();
            if (null == enc) {
                enc = Charset.defaultCharset().name();
            }
            return enc;
        }
        return this.encoding;
    }

    /**
     * Sets the character encoding that will be used when parsing
     * JavaScript files. If this is set to {@code null} (the default), then
     * Wicket's markup encoding setting will be used.
     * 
     * @return {@code this} to allow chaining
     * @see org.apache.wicket.settings.IMarkupSettings#getDefaultMarkupEncoding()
     */
    public JavaScriptDependencySettings setEncoding(String encoding) {
        this.encoding = encoding;
        return this;
    }
}