001// Copyright 2008-2014 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.internal.structure;
016
017import org.apache.tapestry5.ComponentResources;
018import org.apache.tapestry5.Link;
019import org.apache.tapestry5.internal.InternalConstants;
020import org.apache.tapestry5.internal.services.ComponentClassCache;
021import org.apache.tapestry5.internal.services.LinkSource;
022import org.apache.tapestry5.internal.services.RequestPageCache;
023import org.apache.tapestry5.ioc.*;
024import org.apache.tapestry5.ioc.services.PerThreadValue;
025import org.apache.tapestry5.ioc.services.PerthreadManager;
026import org.apache.tapestry5.ioc.services.TypeCoercer;
027import org.apache.tapestry5.model.ComponentModel;
028import org.apache.tapestry5.services.ComponentClassResolver;
029import org.apache.tapestry5.services.ContextValueEncoder;
030import org.apache.tapestry5.services.Request;
031import org.apache.tapestry5.services.RequestGlobals;
032import org.apache.tapestry5.services.messages.ComponentMessagesSource;
033import org.apache.tapestry5.services.pageload.ComponentResourceSelector;
034import org.slf4j.Logger;
035
036import java.io.IOException;
037
038public class ComponentPageElementResourcesImpl implements ComponentPageElementResources
039{
040    private final ComponentResourceSelector selector;
041
042    private final ComponentMessagesSource componentMessagesSource;
043
044    private final TypeCoercer typeCoercer;
045
046    private final ComponentClassCache componentClassCache;
047
048    private final ContextValueEncoder contextValueEncoder;
049
050    private final LinkSource linkSource;
051
052    private final RequestPageCache requestPageCache;
053
054    private final ComponentClassResolver componentClassResolver;
055
056    private final LoggerSource loggerSource;
057
058    private final OperationTracker tracker;
059
060    private final PerthreadManager perThreadManager;
061
062    private final boolean productionMode, componentTracingEnabled;
063
064    private final RequestGlobals requestGlobals;
065
066    public ComponentPageElementResourcesImpl(ComponentResourceSelector selector,
067                                             ComponentMessagesSource componentMessagesSource, TypeCoercer typeCoercer,
068                                             ComponentClassCache componentClassCache, ContextValueEncoder contextValueEncoder, LinkSource linkSource,
069                                             RequestPageCache requestPageCache, ComponentClassResolver componentClassResolver,
070                                             LoggerSource loggerSource, OperationTracker tracker, PerthreadManager perThreadManager, boolean productionMode, boolean componentTracingEnabled, RequestGlobals requestGlobals)
071    {
072        this.selector = selector;
073        this.componentMessagesSource = componentMessagesSource;
074        this.typeCoercer = typeCoercer;
075        this.componentClassCache = componentClassCache;
076        this.contextValueEncoder = contextValueEncoder;
077        this.linkSource = linkSource;
078        this.requestPageCache = requestPageCache;
079        this.componentClassResolver = componentClassResolver;
080        this.loggerSource = loggerSource;
081        this.tracker = tracker;
082        this.perThreadManager = perThreadManager;
083        this.productionMode = productionMode;
084        this.componentTracingEnabled = componentTracingEnabled;
085        this.requestGlobals = requestGlobals;
086    }
087
088    public ComponentResourceSelector getSelector()
089    {
090        return selector;
091    }
092
093    public Messages getMessages(ComponentModel componentModel)
094    {
095        return componentMessagesSource.getMessages(componentModel, selector);
096    }
097
098    public <S, T> T coerce(S input, Class<T> targetType)
099    {
100        return typeCoercer.coerce(input, targetType);
101    }
102
103    public Class toClass(String className)
104    {
105        return componentClassCache.forName(className);
106    }
107
108    public Link createComponentEventLink(ComponentResources resources, String eventType, boolean forForm,
109                                         Object... context)
110    {
111        Page page = requestPageCache.get(resources.getPageName());
112
113        return linkSource.createComponentEventLink(page, resources.getNestedId(), eventType, forForm,
114                defaulted(context));
115    }
116
117    public Link createPageRenderLink(String pageName, boolean override, Object... context)
118    {
119        return linkSource.createPageRenderLink(pageName, override, defaulted(context));
120    }
121
122    public Link createPageRenderLink(Class pageClass, boolean override, Object... context)
123    {
124        assert pageClass != null;
125        String pageName = componentClassResolver.resolvePageClassNameToPageName(pageClass.getName());
126
127        return linkSource.createPageRenderLink(pageName, override, defaulted(context));
128    }
129
130    public Logger getEventLogger(Logger componentLogger)
131    {
132        String name = "tapestry.events." + componentLogger.getName();
133
134        return loggerSource.getLogger(name);
135    }
136
137    public String toClient(Object value)
138    {
139        return contextValueEncoder.toClient(value);
140    }
141
142    public <T> T toValue(Class<T> requiredType, String clientValue)
143    {
144        return contextValueEncoder.toValue(requiredType, clientValue);
145    }
146
147    private Object[] defaulted(Object[] context)
148    {
149        return context == null ? InternalConstants.EMPTY_STRING_ARRAY : context;
150    }
151
152    public <T> T invoke(String description, Invokable<T> operation)
153    {
154        return tracker.invoke(description, operation);
155    }
156
157    public <T> T perform(String description, IOOperation<T> operation) throws IOException
158    {
159        return tracker.perform(description, operation);
160    }
161
162    public void run(String description, Runnable operation)
163    {
164        tracker.run(description, operation);
165    }
166
167    public <T> PerThreadValue<T> createPerThreadValue()
168    {
169        return perThreadManager.createValue();
170    }
171
172    public boolean isRenderTracingEnabled()
173    {
174        if (productionMode)
175        {
176            return false;
177        }
178
179        if (componentTracingEnabled)
180        {
181            return true;
182        }
183
184        Request request = requestGlobals.getRequest();
185
186        if (request == null)
187        {
188            return false;
189        }
190
191        return "true".equals(request.getParameter("t:component-trace"));
192    }
193
194}