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.markup.html; 018 019import java.util.List; 020import java.util.concurrent.CopyOnWriteArrayList; 021 022import org.apache.wicket.markup.head.IHeaderResponse; 023import org.apache.wicket.markup.head.ResourceAggregator; 024import org.apache.wicket.util.lang.Args; 025 026/** 027 * A collection of {@link IHeaderResponseDecorator}s. The decorators will be nested oldest on the 028 * inside, newest on the outside. By default {@link ResourceAggregator} is already registered. 029 * 030 * @author Emond Papegaaij 031 */ 032public class HeaderResponseDecoratorCollection implements IHeaderResponseDecorator 033{ 034 private final List<IHeaderResponseDecorator> decorators = new CopyOnWriteArrayList<>(); 035 036 private IHeaderResponseDecorator resourceAggregation = ResourceAggregator::new; 037 038 public HeaderResponseDecoratorCollection() 039 { 040 decorators.add(resourceAggregation); 041 } 042 043 /** 044 * Adds a new {@link IHeaderResponseDecorator} that will decorates prior to all already 045 * registered decorators. That means, the first to be added will be wrapped by a 046 * {@link ResourceAggregator} like this: {@code new ResourceAggregator(first)}. The second will 047 * be wrapped by the first and the aggregator: {@code new ResourceAggregator(first(second))}. 048 * 049 * @param decorator 050 * The decorator to add, cannot be null. 051 * @return {@code this} for chaining. 052 */ 053 public HeaderResponseDecoratorCollection add(IHeaderResponseDecorator decorator) 054 { 055 Args.notNull(decorator, "decorator"); 056 decorators.add(0, decorator); 057 return this; 058 } 059 060 /** 061 * Adds a new {@link IHeaderResponseDecorator} that decorates immediately prior to resource 062 * aggregation. 063 * 064 * @param decorator 065 * The decorator to add, cannot be null. 066 * @return {@code this} for chaining. 067 * 068 * @see ResourceAggregator 069 */ 070 public HeaderResponseDecoratorCollection addPreResourceAggregationDecorator( 071 IHeaderResponseDecorator decorator) 072 { 073 Args.notNull(decorator, "decorator"); 074 075 for (int i = 0; i < decorators.size(); i++) 076 { 077 if (decorators.get(i) == resourceAggregation) 078 { 079 decorators.add(i, decorator); 080 return this; 081 } 082 } 083 084 throw new IllegalStateException("no resource aggregation"); 085 } 086 087 /** 088 * Adds a new {@link IHeaderResponseDecorator} that decorates after all already registered 089 * decorators. 090 * 091 * @param decorator 092 * The decorator to add, cannot be null. 093 * @return {@code this} for chaining. 094 */ 095 public HeaderResponseDecoratorCollection addPostProcessingDecorator( 096 IHeaderResponseDecorator decorator) 097 { 098 Args.notNull(decorator, "decorator"); 099 decorators.add(decorator); 100 return this; 101 } 102 103 /** 104 * Replaces all registered {@link IHeaderResponseDecorator}s with the given decorator. This also 105 * removes the {@link ResourceAggregator}, which is required to render resource dependencies. 106 * 107 * @param decorator 108 * The decorator to add, cannot be null. 109 * @return {@code this} for chaining. 110 */ 111 public HeaderResponseDecoratorCollection replaceAll(IHeaderResponseDecorator decorator) 112 { 113 Args.notNull(decorator, "decorator"); 114 decorators.clear(); 115 resourceAggregation = null; 116 decorators.add(decorator); 117 return this; 118 } 119 120 @Override 121 public IHeaderResponse decorate(IHeaderResponse response) 122 { 123 IHeaderResponse ret = response; 124 for (IHeaderResponseDecorator curDecorator : decorators) 125 { 126 ret = curDecorator.decorate(ret); 127 } 128 return ret; 129 } 130}