1 package de.matthias_burbach.mosaique4eclipse.views;
2
3 import java.io.File;
4 import java.util.HashMap;
5 import java.util.Iterator;
6 import java.util.List;
7 import java.util.Map;
8
9 import org.eclipse.core.resources.IFile;
10 import org.eclipse.core.resources.IFolder;
11 import org.eclipse.core.resources.IWorkspaceRoot;
12 import org.eclipse.core.resources.ResourcesPlugin;
13 import org.eclipse.core.runtime.IAdaptable;
14 import org.eclipse.jface.viewers.ITreeContentProvider;
15 import org.eclipse.jface.viewers.Viewer;
16 import org.eclipse.ui.model.IWorkbenchAdapter;
17
18 import de.matthias_burbach.mosaique.core.model.Context;
19 import de.matthias_burbach.mosaique.core.model.DefinitionResolver;
20 import de.matthias_burbach.mosaique.core.model.JspResolver;
21 import de.matthias_burbach.mosaique.core.model.PathFinder;
22 import de.matthias_burbach.mosaique.core.model.StrutsConfig;
23 import de.matthias_burbach.mosaique.core.model.TilesDefinitions;
24 import de.matthias_burbach.mosaique.core.parser.StrutsConfigParser;
25 import de.matthias_burbach.mosaique.core.parser.TilesDefinitionsParser;
26 import de.matthias_burbach.mosaique.swing.BaseMutableTreeNode;
27 import de.matthias_burbach.mosaique.swing.LogicalPageNode;
28 import de.matthias_burbach.mosaique.swing.StrutsConfigNode;
29 import de.matthias_burbach.mosaique4eclipse.util.Util;
30
31 /***
32 * The content provider class is responsible for providing objects to the
33 * view. It can wrap existing objects in adapters or simply return objects
34 * as-is. These objects may be sensitive to the current input of the view,
35 * or ignore it and always show the same content (like Task List, for
36 * example).
37 */
38 class MosaiqueTreeContentProvider implements ITreeContentProvider {
39 /***
40 * Maps IFile representations of Struts config files to objects of type
41 * {@link StrutsConfigNode}.
42 */
43 private Map strutsConfigNodes = new HashMap();
44
45 /***
46 * Maps IFolder representations of WEB-INF folders
47 * (=parents of IFiles of Struts config files) to objects of type
48 * {@link de.matthias_burbach.mosaique.core.model.Context}.
49 */
50 private Map contexts = new HashMap();
51
52 /***
53 * The parser for Tiles definition files. The instance is stateless and
54 * can be re-used therefore.
55 */
56 private TilesDefinitionsParser tilesDefParser =
57 new TilesDefinitionsParser();
58
59
60
61
62
63
64 /***
65 * {@inheritDoc}
66 */
67 public boolean hasChildren(final Object element) {
68 boolean result = false;
69 Object[] children = getChildren(element);
70 if (children != null && children.length > 0) {
71 result = true;
72 }
73 return result;
74 }
75
76
77
78
79
80
81 /***
82 * {@inheritDoc}
83 */
84 public Object[] getElements(final Object inputElement) {
85 return getChildren(inputElement);
86 }
87
88
89
90
91
92 /***
93 * {@inheritDoc}
94 */
95 public void dispose() {
96
97 }
98
99
100
101
102
103
104
105
106 /***
107 * {@inheritDoc}
108 */
109 public void inputChanged(
110 final Viewer viewer,
111 final Object oldInput,
112 final Object newInput) {
113
114 }
115
116
117
118
119
120
121 /***
122 * {@inheritDoc}
123 */
124 public Object getParent(final Object child) {
125 Object result = null;
126 if (child instanceof LogicalPageNode) {
127 LogicalPageNode node = (LogicalPageNode) child;
128 result = Util.fileToIFile(
129 new File(node.getFileItem().getFilePath()));
130 } else if (child instanceof BaseMutableTreeNode) {
131 result = ((BaseMutableTreeNode) child).getParent();
132 } else {
133 IWorkbenchAdapter adapter = getAdapter(child);
134 if (adapter != null) {
135 result = adapter.getParent(child);
136 }
137 }
138 return result;
139 }
140
141
142
143
144
145
146 /***
147 * {@inheritDoc}
148 */
149 public Object[] getChildren(final Object aParent) {
150 Object[] result = null;
151 Object parent = aParent;
152 if (parent == null) {
153 parent = getRoot();
154 }
155 if (Util.isStrutsConfigFile(parent)) {
156 IFile strutsConfigIFile = (IFile) parent;
157 StrutsConfigNode strutsConfigNode =
158 (StrutsConfigNode) strutsConfigNodes.get(strutsConfigIFile);
159 if (strutsConfigNode == null) {
160 Context context = getContext(strutsConfigIFile);
161 String path = strutsConfigIFile.getLocation().toOSString();
162 StrutsConfigParser parser = new StrutsConfigParser();
163 try {
164 StrutsConfig strutsConfig = parser.parse(path, context);
165 if (!strutsConfig.isErroneous()) {
166 parseTilesDefinitions(
167 strutsConfigIFile,
168 strutsConfig.getDefinitionsConfigValues(),
169 context);
170 }
171 strutsConfigNode = new StrutsConfigNode(
172 strutsConfig, null);
173 strutsConfigNodes.put(strutsConfigIFile, strutsConfigNode);
174 } catch (Exception e) {
175 e.printStackTrace();
176 }
177 }
178 if (strutsConfigNode != null) {
179 result = strutsConfigNode.getChildren();
180 }
181 } else if (parent instanceof BaseMutableTreeNode) {
182 result = ((BaseMutableTreeNode) parent).getChildren();
183 } else {
184 IWorkbenchAdapter adapter = getAdapter(parent);
185 if (adapter != null) {
186 result = adapter.getChildren(parent);
187 }
188 }
189 return result;
190 }
191
192 /***
193 * @return The root object of the tree provided.
194 */
195 IWorkspaceRoot getRoot() {
196 IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
197 return root;
198 }
199
200 /***
201 * Refreshes the provided tree from scratch by discarding all cache
202 * contents. Actual refreshing will take place on next access to the tree
203 * elements.
204 */
205 void refresh() {
206 strutsConfigNodes.clear();
207 contexts.clear();
208 }
209
210 /***
211 * @param strutsConfigIFile The Struts configuration file to derive the
212 * context from.
213 * @return The context of cacheable instances.
214 */
215 private Context getContext(final IFile strutsConfigIFile) {
216 IFolder webInfFolder = (IFolder) strutsConfigIFile.getParent();
217 Context context = (Context) contexts.get(webInfFolder);
218 if (context == null) {
219 context = new Context();
220 DefinitionResolver definitionResolver = new DefinitionResolver();
221 context.setDefinitionResolver(definitionResolver);
222 PathFinder pathFinder = new VrpEclipsePathFinder(strutsConfigIFile);
223 JspResolver jspResolver = new JspResolver(pathFinder, context);
224 context.setJspResolver(jspResolver);
225 contexts.put(webInfFolder, context);
226 }
227 return context;
228 }
229
230 /***
231 * Returns the implementation of IWorkbenchAdapter for the given object.
232 * Returns null if the adapter is not defined or the object is not
233 * adaptable.
234 *
235 * @param element the element to be adapted
236 * @return the corresponding workbench adapter object or <code>null</code>.
237 */
238 private IWorkbenchAdapter getAdapter(final Object element) {
239 IWorkbenchAdapter result = null;
240 if (element instanceof IAdaptable) {
241 result = (IWorkbenchAdapter) ((IAdaptable) element)
242 .getAdapter(IWorkbenchAdapter.class);
243 }
244 return result;
245 }
246
247 /***
248 * @param strutsConfigIFile The Struts configuration that links to the Tiles
249 * to be parsed.
250 * @param definitionsConfigValues The relative paths of the Tiles definition
251 * files to parse.
252 * @param context The context of cacheable instances.
253 * @throws Exception if anything goes wrong.
254 */
255 private void parseTilesDefinitions(
256 final IFile strutsConfigIFile,
257 final List definitionsConfigValues,
258 final Context context) throws Exception {
259 PathFinder pathFinder = new VrpEclipsePathFinder(strutsConfigIFile);
260 DefinitionResolver resolver = context.getDefinitionResolver();
261 Iterator iter = definitionsConfigValues.iterator();
262 while (iter.hasNext()) {
263 String value = (String) iter.next();
264 String path = pathFinder.findAbsolutePath(value);
265 if (path != null) {
266 TilesDefinitions tilesDefinitions =
267 tilesDefParser.parse(path, context);
268 resolver.addTilesDefinitions(tilesDefinitions);
269 }
270 }
271 }
272
273 /***
274 * Checks if the Struts config node corresponding to the Struts file object
275 * has errors.
276 *
277 * @param strutsConfigIFile The Struts config file to be mapped to the
278 * Struts config node to be checked.
279 * @return <code>true</code> if the node exists and is erroneous.
280 */
281 boolean isErroneousStrutsConfig(final IFile strutsConfigIFile) {
282 boolean result = false;
283 StrutsConfigNode strutsConfigNode =
284 (StrutsConfigNode) strutsConfigNodes.get(strutsConfigIFile);
285 if (strutsConfigNode != null && strutsConfigNode.isErroneous()) {
286 result = true;
287 }
288 return result;
289 }
290 }