001    /*
002     * This file is part of the Echo Point Project.  This project is a
003     * collection of Components that have extended the Echo Web Application
004     * Framework Version 3.
005     *
006     * Version: MPL 1.1
007     *
008     * The contents of this file are subject to the Mozilla Public License Version
009     * 1.1 (the "License"); you may not use this file except in compliance with
010     * the License. You may obtain a copy of the License at
011     * http://www.mozilla.org/MPL/
012     *
013     * Software distributed under the License is distributed on an "AS IS" basis,
014     * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
015     * for the specific language governing rights and limitations under the
016     * License.
017     */
018    package echopoint;
019    
020    import nextapp.echo.app.PaneContainer;
021    import nextapp.echo.app.Component;
022    
023    import java.util.HashMap;
024    import java.util.Map;
025    
026    import echopoint.template.TemplateDataSource;
027    
028    /**
029     * <code>TemplatePanel</code> is a container that uses a
030     * <code>TemplateLayoutData</code> to render a template of content.
031     * <p>
032     * This layout data can itself contained "named" Components and "named" Text
033     * Substitutions.
034     * <p>
035     * A singleton <code>TemplateDataSource</code> can be used for more than one
036     * <code>TemplatePanel</code> and hence the memory footprint is reduced if
037     * used in this way.
038     * <p>
039     * <h3>Supplied Implementation</h3>
040     * <p>
041     * The supplied template implementation reads XHTML template data from a number
042     * of different sources including Files, Strings, Resources and JSP pages.
043     * <p>
044     * The markup :
045     *
046     * <pre><code>
047     *
048     *
049     *   &lt;component name=&quot;xxx&quot; /&gt;
050     *
051     *
052     * </code></pre>
053     *
054     * is used to indicate where in the template a named component will be placed.
055     * <p>
056     *
057     * In EchopointNG it was possible to set style and css properties. This feature is not implemented yet.
058     *
059     */
060    public class TemplatePanel extends Component implements PaneContainer {
061    
062    
063            public static final String PROPERTY_TEMPLATE_DATA_SOURCE = "templateDataSource";
064        public static final String PROPERTY_COMPONENT_MAPPING = "componentmapping";
065    
066        /**
067         * Constructs a <code>TemplatePanel</code> with no template data as yet.
068         */
069        public TemplatePanel() {
070            super();
071            set(PROPERTY_COMPONENT_MAPPING, new HashMap());
072        }
073    
074        /**
075         * Constructs a <code>TemplatePanel</code> with the specified
076         * TemplateDataSource.
077         *
078         * @param tds -
079         *                 the source for the template data.
080         */
081        public TemplatePanel(TemplateDataSource tds) {
082            super();
083                    setTemplateDataSource(tds);
084            set(PROPERTY_COMPONENT_MAPPING, new HashMap());
085        }
086    
087    
088            /**
089             * Sets the TemplateDataSource to be used
090             *
091             * @param templateDataSource
092             *            the TemplateDataSource to be used
093             */
094            public void setTemplateDataSource(TemplateDataSource templateDataSource) {
095                    set(PROPERTY_TEMPLATE_DATA_SOURCE, templateDataSource);
096            }
097    
098        /**
099             * Returns the TemplateDataSource which contains the template data.
100             *
101             * @return the TemplateDataSource in place
102             */
103        public TemplateDataSource getTemplateDataSource()
104        {
105            return (TemplateDataSource) get(PROPERTY_TEMPLATE_DATA_SOURCE);
106        }
107    
108    
109       /**
110             * Adds a component to the <code>TemplatePanel</code> with the associated
111             * name which can the be references from the template data.
112             *
113             * @param component
114             *            the component to add
115             * @param componentName -
116             *            the name to use when referencing this component in the
117             *            template data.
118             */
119        public void addNamedComponent(Component component, String componentName) {
120            if (component == null)
121                throw new IllegalArgumentException("component must be non null.");
122            if (componentName == null)
123                throw new IllegalArgumentException("componentName must be non null.");
124    
125            ((Map) get(PROPERTY_COMPONENT_MAPPING)).put(componentName, component);
126            add(component);
127        }
128    
129        Map getComponentMapping()
130        {
131            return (Map) get(PROPERTY_COMPONENT_MAPPING); 
132        }
133    
134        /**
135         * Returns the name associated with the component or null if it cant be
136         * found.
137         *
138         * @param component -
139         *                  the component associated with the name
140         * @return a name associated with component
141         */
142        public String getComponentName(Component component) {
143            String componentNames[] = getNamedComponents();
144            for (int i = 0; i < componentNames.length; i++) {
145                Component c = getNamedComponent(componentNames[i]);
146                if (component == c) {
147                    return componentNames[i];
148                }
149            }
150            return null;
151        }
152    
153    
154        /**
155             * Returns a component associated with the name or null if it cant be found.
156             *
157             * @param componentName -
158             *            the name associated with the component
159             * @return a component associated with componentName
160             */
161            public Component getNamedComponent(String componentName) {
162                    return (Component) ((Map) get(PROPERTY_COMPONENT_MAPPING)).get((componentName));
163            }
164    
165            /**
166             * @return an array of all the component names in the
167             *         <code>TemplatePanel</code>.
168             */
169            public String[] getNamedComponents() {
170            Map componentNameMap = ((Map) get(PROPERTY_COMPONENT_MAPPING));
171                    return (String[]) componentNameMap.keySet().toArray(new String[componentNameMap.keySet().size()]);
172            }
173    
174    
175        /**
176             * @see nextapp.echo.app.Component#remove(nextapp.echo.app.Component)
177             */
178            public void remove(Component c) {
179                    String componentName = getComponentName(c);
180                    if (componentName != null) {
181                            ((Map) get(PROPERTY_COMPONENT_MAPPING)).remove(componentName);
182                    }
183                    super.remove(c);
184            }
185    
186            /**
187             * Removes a named component from the <code>TemplatePanel</code> that was
188             * previously added via the <code>addNamedComponent()</code> method.
189             *
190             * @param componentName -
191             *            the name of the component
192             */
193            public void removeNamedComponent(String componentName) {
194                    if (componentName == null)
195                            throw new IllegalArgumentException("componentName must be non null.");
196    
197                    Component child = getNamedComponent(componentName);
198                    ((Map) get(PROPERTY_COMPONENT_MAPPING)).remove(componentName);
199                    if (child != null) {
200                            remove(child);
201                    }
202            }
203    
204    }