001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.resource.bundles;
018
019import java.util.Arrays;
020import java.util.LinkedHashSet;
021import java.util.List;
022import java.util.Locale;
023import java.util.Set;
024
025import org.apache.wicket.Application;
026import org.apache.wicket.ResourceBundles;
027import org.apache.wicket.markup.head.HeaderItem;
028import org.apache.wicket.markup.head.IReferenceHeaderItem;
029import org.apache.wicket.request.resource.CssResourceReference;
030import org.apache.wicket.request.resource.IResource;
031import org.apache.wicket.request.resource.JavaScriptResourceReference;
032import org.apache.wicket.request.resource.ResourceReference;
033import org.apache.wicket.request.resource.caching.IStaticCacheableResource;
034import org.apache.wicket.resource.ITextResourceCompressor;
035import org.apache.wicket.util.lang.Args;
036
037/**
038 * A resource bundle that automatically concatenates the given resources. These resources should all
039 * be of the same type (javascript or css) and all have {@link IStaticCacheableResource} (or
040 * subclasses). After creating the bundle, you normally have to register it in the
041 * {@link ResourceBundles} under {@link Application#getResourceBundles()}. {@link ResourceBundles}
042 * has two utility methods to create instances of this class:
043 * {@link ResourceBundles#addJavaScriptBundle(Class, String, JavaScriptResourceReference...)
044 * addJavaScriptBundle} and
045 * {@link ResourceBundles#addCssBundle(Class, String, CssResourceReference...) addCssBundle}.
046 * Dependencies are inherited from the provided resources, if the bundle does not provide all
047 * dependencies itself.
048 * 
049 * @author papegaaij
050 * @param <T>
051 *            The type of the header items to bundle
052 */
053public class ConcatResourceBundleReference<T extends HeaderItem & IReferenceHeaderItem> extends
054        ResourceReference implements IResourceBundle
055{
056        private static final long serialVersionUID = 1L;
057
058        private final List<T> providedResources;
059
060        /**
061         * An optional compressor that will be used to compress the bundle resources
062         */
063        private ITextResourceCompressor compressor;
064
065        /**
066         * Creates a new {@link ConcatResourceBundleReference} for the given resources.
067         * 
068         * @param scope
069         * @param name
070         * @param resources
071         */
072        public ConcatResourceBundleReference(Class<?> scope, String name, List<T> resources)
073        {
074                this(scope, name, null, null, null, resources);
075        }
076
077        /**
078         * Creates a new {@link ConcatResourceBundleReference} for the given resources.
079         * 
080         * @param scope
081         * @param name
082         * @param resources
083         */
084        public ConcatResourceBundleReference(Class<?> scope, String name, T... resources)
085        {
086                this(scope, name, null, null, null, Arrays.asList(resources));
087        }
088
089        /**
090         * Creates a new {@link ConcatResourceBundleReference} for the given resources.
091         * 
092         * @param name
093         * @param resources
094         */
095        public ConcatResourceBundleReference(String name, T... resources)
096        {
097                this(Application.class, name, null, null, null, Arrays.asList(resources));
098        }
099
100        /**
101         * Creates a new {@link ConcatResourceBundleReference} for the given resources.
102         * 
103         * @param scope
104         *            mandatory parameter
105         * @param name
106         *            mandatory parameter
107         * @param locale
108         *            resource locale
109         * @param style
110         *            resource style
111         * @param variation
112         *            resource variation
113         * @param resources
114         *            the resources that are concatenated
115         */
116        public ConcatResourceBundleReference(Class<?> scope, String name, Locale locale, String style,
117                String variation, List<T> resources)
118        {
119                super(scope, name, locale, style, variation);
120                providedResources = Args.notNull(resources, "resources");
121        }
122
123        @Override
124        public IResource getResource()
125        {
126                ConcatBundleResource bundleResource = new ConcatBundleResource(providedResources);
127                ITextResourceCompressor compressor = getCompressor();
128                if (compressor != null)
129                {
130                        bundleResource.setCompressor(compressor);
131                }
132                return bundleResource;
133        }
134
135        @Override
136        public List<T> getProvidedResources()
137        {
138                return providedResources;
139        }
140
141        @Override
142        public List<HeaderItem> getDependencies()
143        {
144                Set<HeaderItem> ret = new LinkedHashSet<>();
145                for (HeaderItem curProvided : providedResources)
146                {
147                        for (HeaderItem curDependency : curProvided.getDependencies())
148                                ret.add(curDependency);
149                }
150                for (HeaderItem curProvided : providedResources)
151                {
152                        ret.remove(curProvided);
153                }
154                List<HeaderItem> dependencies = super.getDependencies();
155                dependencies.addAll(ret);
156                return dependencies;
157        }
158
159        public void setCompressor(ITextResourceCompressor compressor)
160        {
161                this.compressor = compressor;
162        }
163
164        public ITextResourceCompressor getCompressor()
165        {
166                return compressor;
167        }
168}