001 // Copyright Jul 9, 2006 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 package org.apache.tapestry.link;
015
016 import java.util.HashMap;
017 import java.util.Map;
018
019 import org.apache.hivemind.ClassResolver;
020 import org.apache.hivemind.util.ClasspathResource;
021 import org.apache.hivemind.util.Defense;
022 import org.apache.tapestry.IComponent;
023 import org.apache.tapestry.IDirect;
024 import org.apache.tapestry.IRequestCycle;
025 import org.apache.tapestry.PageRenderSupport;
026 import org.apache.tapestry.TapestryUtils;
027 import org.apache.tapestry.components.ILinkComponent;
028 import org.apache.tapestry.engine.IScriptSource;
029 import org.apache.tapestry.html.Body;
030 import org.apache.tapestry.services.ComponentRenderWorker;
031 import org.apache.tapestry.util.ScriptUtils;
032
033
034 /**
035 * Manages connecting {@link IDirect} components that also implement
036 * the {@link ILinkComponent} interface to JavaScript asynchronous IO operations
037 * when any of the shared parameters of {@link IDirect} are specified that relate
038 * to asynchronous operations.
039 *
040 * @author jkuhnert
041 */
042 public class DirectLinkWorker implements ComponentRenderWorker
043 {
044 // Parses/manages script template
045 private IScriptSource _scriptSource;
046
047 // Used to resolve classpath relative resources
048 private ClasspathResource _script;
049
050 // Class resolver
051 private ClassResolver _resolver;
052
053 // The path to the javascript template we will use to connect links to IO operations
054 private String _scriptPath;
055
056 /**
057 * Default constructor, does nothing.
058 */
059 public DirectLinkWorker()
060 {
061 }
062
063 /**
064 * {@inheritDoc}
065 */
066 public void renderComponent(IRequestCycle cycle, IComponent component)
067 {
068 if (cycle.isRewinding())
069 return;
070
071 // must implement both interfaces
072 if (!ILinkComponent.class.isInstance(component)
073 || !IDirect.class.isInstance(component))
074 return;
075
076 IDirect direct = (IDirect)component;
077
078 // check for dynamic parameters
079 if (!direct.isAsync() && !direct.isJson())
080 return;
081
082 PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, component);
083
084 if (prs == null)
085 return;
086
087 Map parms = new HashMap();
088
089 parms.put("component", component);
090 parms.put("json", Boolean.valueOf(direct.isJson()));
091 parms.put("key", ScriptUtils.functionHash("onclick" + component.hashCode()));
092
093 // execute script template
094
095 _scriptSource.getScript(_script).execute(component, cycle, prs, parms);
096 }
097
098 /**
099 * {@inheritDoc}
100 */
101 public void renderBody(IRequestCycle cycle, Body component)
102 {
103 }
104
105 /**
106 * Needs to be invoked to initialize resources used.
107 */
108 public void initialize()
109 {
110 Defense.notNull(_resolver, "Classpath Resolver");
111 Defense.notNull(_scriptPath, "Script path");
112
113 _script = new ClasspathResource(_resolver, _scriptPath);
114 }
115
116 public void setScriptSource(IScriptSource source)
117 {
118 _scriptSource = source;
119 }
120
121 public void setScript(String path)
122 {
123 _scriptPath = path;
124 }
125
126 /**
127 * Auto-Wire injected.
128 * @param resolver
129 */
130 public void setClassResolver(ClassResolver resolver)
131 {
132 _resolver = resolver;
133 }
134 }