    001// Copyright 2008, 2009, 2010, 2011 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007// http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.services.javascript;
    016
    017import org.apache.tapestry5.Asset;
    018import org.apache.tapestry5.dom.Document;
    019import org.apache.tapestry5.dom.Element;
    020import org.apache.tapestry5.internal.TapestryInternalUtils;
    021import org.apache.tapestry5.internal.services.DocumentLinker;
    022import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    023
    024/**
    025 * Captures the information needed to create a stylesheet link in the final {@link Document}, or
    026 * as part of a JSON partial page render response.
    027 *
    028 * @see DocumentLinker
    029 * @see JavaScriptStack
    030 * @since 5.2.0
    031 */
    032public final class StylesheetLink
    033{
    034    private final Asset asset;
    035
    036    private final String url;
    037
    038    private final StylesheetOptions options;
    039
    040    private static final StylesheetOptions BLANK_OPTIONS = new StylesheetOptions(null);
    041
    042    public StylesheetLink(Asset asset)
    043    {
    044        this(asset, null, null);
    045    }
    046
    047    public StylesheetLink(Asset asset, StylesheetOptions options)
    048    {
    049        this(asset, null, options);
    050    }
    051
    052    public StylesheetLink(String url)
    053    {
    054        this(null, url, null);
    055    }
    056
    057    public StylesheetLink(String url, StylesheetOptions options)
    058    {
    059        this(null, url, options);
    060    }
    061
    062    private StylesheetLink(Asset asset, String url, StylesheetOptions options)
    063    {
    064        assert asset != null || InternalUtils.isNonBlank(url);
    065
    066        this.asset = asset;
    067        this.url = url;
    068        this.options = options != null ? options : BLANK_OPTIONS;
    069    }
    070
    071    public String getURL()
    072    {
    073        // Only one of asset or url will be non-null.
    074        // Starting in 5.4, we keep the asset around and ask it for its clientURL; this is because
    075        // clientURLs can change if the content of the underlying Resource changes.
    076        return asset != null ? asset.toClientURL() : url;
    077    }
    078
    079    /**
    080     * Returns an instance of {@link StylesheetOptions}. Never returns null (a blank options
    081     * object is returned if null is passed to the constructor).
    082     */
    083    public StylesheetOptions getOptions()
    084    {
    085        return options;
    086    }
    087
    088    /**
    089     * Invoked to add the stylesheet link to a container element.
    090     *
    091     * @param container
    092     *         to add the new element to
    093     */
    094    public void add(Element container)
    095    {
    096        boolean hasCondition = InternalUtils.isNonBlank(options.condition);
    097
    098        if (hasCondition)
    099        {
    100            container.raw(String.format("\n<!--[if %s]>\n", options.condition));
    101        }
    102
    103        String rel = options.ajaxInsertionPoint ? "stylesheet ajax-insertion-point" : "stylesheet";
    104
    105        container.element("link",
    106                "href", getURL(),
    107                "rel", rel,
    108                "type", "text/css",
    109                "media", options.media);
    110
    111        if (hasCondition)
    112        {
    113            container.raw("\n<![endif]-->\n");
    114        }
    115    }
    116
    117    @Override
    118    public String toString()
    119    {
    120        return String.format("StylesheetLink[%s %s]", url, options);
    121    }
    122
    123    @Override
    124    public boolean equals(Object obj)
    125    {
    126        if (obj == this)
    127            return true;
    128
    129        if (obj == null || !(obj instanceof StylesheetLink))
    130            return false;
    131
    132        StylesheetLink ssl = (StylesheetLink) obj;
    133
    134        return TapestryInternalUtils.isEqual(getURL(), ssl.getURL()) && TapestryInternalUtils.isEqual(options, ssl.options);
    135    }
    136
    137}