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    }