a0d83fac33d9455cb89f4ee375df8fbd34b1e186
[phpeclipse.git] /
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.corext.template.php;
12
13 import java.io.File;
14 import java.io.FileInputStream;
15 import java.io.FileOutputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19 import java.util.ArrayList;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.MissingResourceException;
23 import java.util.ResourceBundle;
24
25 import javax.xml.parsers.DocumentBuilder;
26 import javax.xml.parsers.DocumentBuilderFactory;
27 import javax.xml.parsers.ParserConfigurationException;
28 import javax.xml.transform.OutputKeys;
29 import javax.xml.transform.Transformer;
30 import javax.xml.transform.TransformerException;
31 import javax.xml.transform.TransformerFactory;
32 import javax.xml.transform.dom.DOMSource;
33 import javax.xml.transform.stream.StreamResult;
34
35 import org.eclipse.core.runtime.CoreException;
36 import org.eclipse.core.runtime.IStatus;
37 import org.eclipse.core.runtime.Status;
38 import org.eclipse.jface.text.templates.ContextTypeRegistry;
39 import org.eclipse.jface.text.templates.Template;
40 import org.eclipse.jface.text.templates.TemplateContextType;
41 import org.eclipse.jface.text.templates.TemplateException;
42 import org.w3c.dom.Attr;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.NamedNodeMap;
45 import org.w3c.dom.Node;
46 import org.w3c.dom.NodeList;
47 import org.w3c.dom.Text;
48 import org.xml.sax.InputSource;
49 import org.xml.sax.SAXException;
50
51 /**
52  * <code>TemplateSet</code> manages a collection of templates and makes them
53  * persistent.
54  * 
55  * @deprecated use TemplateStore instead
56  * @since 3.0
57  */
58 public class TemplateSet {
59
60         private static final String NAME_ATTRIBUTE = "name"; //$NON-NLS-1$
61
62         private static final String DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$
63
64         private static final String CONTEXT_ATTRIBUTE = "context"; //$NON-NLS-1$
65
66         private List fTemplates = new ArrayList();
67
68         private String fTemplateTag;
69
70         private static final int TEMPLATE_PARSE_EXCEPTION = 10002;
71
72         private static final int TEMPLATE_IO_EXCEPTION = 10005;
73
74         private ContextTypeRegistry fRegistry;
75
76         public TemplateSet(String templateTag, ContextTypeRegistry registry) {
77                 fTemplateTag = templateTag;
78                 fRegistry = registry;
79         }
80
81         /**
82          * Convenience method for reading templates from a file.
83          * 
84          * @param file
85          * @param allowDuplicates
86          * @param bundle
87          * @see #addFromStream(InputStream, boolean, boolean, ResourceBundle)
88          * @throws CoreException
89          */
90         public void addFromFile(File file, boolean allowDuplicates,
91                         ResourceBundle bundle) throws CoreException {
92                 InputStream stream = null;
93
94                 try {
95                         stream = new FileInputStream(file);
96                         addFromStream(stream, allowDuplicates, false, bundle);
97
98                 } catch (IOException e) {
99                         throwReadException(e);
100
101                 } finally {
102                         try {
103                                 if (stream != null)
104                                         stream.close();
105                         } catch (IOException e) {
106                         }
107                 }
108         }
109
110         public String getTemplateTag() {
111                 return fTemplateTag;
112         }
113
114         /**
115          * Reads templates from a XML stream and adds them to the templates
116          * 
117          * @param stream
118          * @param allowDuplicates
119          * @param bundle
120          * @param doTranslations
121          * @see #addFromStream(InputStream, boolean, boolean, ResourceBundle)
122          * @throws CoreException
123          */
124         public void addFromStream(InputStream stream, boolean allowDuplicates,
125                         boolean doTranslations, ResourceBundle bundle) throws CoreException {
126                 try {
127                         DocumentBuilderFactory factory = DocumentBuilderFactory
128                                         .newInstance();
129                         DocumentBuilder parser = factory.newDocumentBuilder();
130                         Document document = parser.parse(new InputSource(stream));
131
132                         NodeList elements = document.getElementsByTagName(getTemplateTag());
133
134                         int count = elements.getLength();
135                         for (int i = 0; i != count; i++) {
136                                 Node node = elements.item(i);
137                                 NamedNodeMap attributes = node.getAttributes();
138
139                                 if (attributes == null)
140                                         continue;
141
142                                 String name = getAttributeValue(attributes, NAME_ATTRIBUTE);
143                                 String description = getAttributeValue(attributes,
144                                                 DESCRIPTION_ATTRIBUTE);
145                                 if (name == null || description == null)
146                                         continue;
147
148                                 if (doTranslations) {
149                                         description = translateString(description, bundle);
150                                 }
151                                 String context = getAttributeValue(attributes,
152                                                 CONTEXT_ATTRIBUTE);
153
154                                 if (name == null || description == null || context == null)
155                                         throw new SAXException(JavaTemplateMessages
156                                                         .getString("TemplateSet.error.missing.attribute")); //$NON-NLS-1$
157
158                                 StringBuffer buffer = new StringBuffer();
159                                 NodeList children = node.getChildNodes();
160                                 for (int j = 0; j != children.getLength(); j++) {
161                                         String value = children.item(j).getNodeValue();
162                                         if (value != null)
163                                                 buffer.append(value);
164                                 }
165                                 String pattern = buffer.toString().trim();
166                                 if (doTranslations) {
167                                         pattern = translateString(pattern, bundle);
168                                 }
169
170                                 Template template = new Template(name, description, context,
171                                                 pattern);
172
173                                 String message = validateTemplate(template);
174                                 if (message == null) {
175                                         if (!allowDuplicates) {
176                                                 Template[] templates = getTemplates(name);
177                                                 for (int k = 0; k < templates.length; k++) {
178                                                         remove(templates[k]);
179                                                 }
180                                         }
181                                         add(template);
182                                 } else {
183                                         throwReadException(null);
184                                 }
185                         }
186                 } catch (ParserConfigurationException e) {
187                         throwReadException(e);
188                 } catch (IOException e) {
189                         throwReadException(e);
190                 } catch (SAXException e) {
191                         throwReadException(e);
192                 }
193         }
194
195         private String translateString(String str, ResourceBundle bundle) {
196                 int idx = str.indexOf('%');
197                 if (idx == -1) {
198                         return str;
199                 }
200                 StringBuffer buf = new StringBuffer();
201                 int k = 0;
202                 while (idx != -1) {
203                         buf.append(str.substring(k, idx));
204                         for (k = idx + 1; k < str.length()
205                                         && !Character.isWhitespace(str.charAt(k)); k++) {
206                                 // loop
207                         }
208                         String key = str.substring(idx + 1, k);
209                         buf.append(getBundleString(key, bundle));
210                         idx = str.indexOf('%', k);
211                 }
212                 buf.append(str.substring(k));
213                 return buf.toString();
214         }
215
216         private String getBundleString(String key, ResourceBundle bundle) {
217                 if (bundle != null) {
218                         try {
219                                 return bundle.getString(key);
220                         } catch (MissingResourceException e) {
221                                 return '!' + key + '!';
222                         }
223                 } else
224                         return JavaTemplateMessages.getString(key); // default messages
225         }
226
227         protected String validateTemplate(Template template) {
228                 TemplateContextType type = fRegistry.getContextType(template
229                                 .getContextTypeId());
230                 if (type == null) {
231                         return "Unknown context type: " + template.getContextTypeId(); //$NON-NLS-1$
232                 }
233                 try {
234                         type.validate(template.getPattern());
235                         return null;
236                 } catch (TemplateException e) {
237                         return e.getMessage();
238                 }
239         }
240
241         private String getAttributeValue(NamedNodeMap attributes, String name) {
242                 Node node = attributes.getNamedItem(name);
243
244                 return node == null ? null : node.getNodeValue();
245         }
246
247         /**
248          * Convenience method for saving to a file.
249          * 
250          * @see #saveToStream(OutputStream)
251          */
252         public void saveToFile(File file) throws CoreException {
253                 OutputStream stream = null;
254
255                 try {
256                         stream = new FileOutputStream(file);
257                         saveToStream(stream);
258
259                 } catch (IOException e) {
260                         throwWriteException(e);
261
262                 } finally {
263                         try {
264                                 if (stream != null)
265                                         stream.close();
266                         } catch (IOException e) {
267                         }
268                 }
269         }
270
271         /**
272          * Saves the template set as XML.
273          */
274         public void saveToStream(OutputStream stream) throws CoreException {
275                 try {
276                         DocumentBuilderFactory factory = DocumentBuilderFactory
277                                         .newInstance();
278                         DocumentBuilder builder = factory.newDocumentBuilder();
279                         Document document = builder.newDocument();
280
281                         Node root = document.createElement("templates"); //$NON-NLS-1$
282                         document.appendChild(root);
283
284                         for (int i = 0; i != fTemplates.size(); i++) {
285                                 Template template = (Template) fTemplates.get(i);
286
287                                 Node node = document.createElement(getTemplateTag());
288                                 root.appendChild(node);
289
290                                 NamedNodeMap attributes = node.getAttributes();
291
292                                 Attr name = document.createAttribute(NAME_ATTRIBUTE);
293                                 name.setValue(template.getName());
294                                 attributes.setNamedItem(name);
295
296                                 Attr description = document
297                                                 .createAttribute(DESCRIPTION_ATTRIBUTE);
298                                 description.setValue(template.getDescription());
299                                 attributes.setNamedItem(description);
300
301                                 Attr context = document.createAttribute(CONTEXT_ATTRIBUTE);
302                                 context.setValue(template.getContextTypeId());
303                                 attributes.setNamedItem(context);
304
305                                 Text pattern = document.createTextNode(template.getPattern());
306                                 node.appendChild(pattern);
307                         }
308
309                         Transformer transformer = TransformerFactory.newInstance()
310                                         .newTransformer();
311                         transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
312                         transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
313                         DOMSource source = new DOMSource(document);
314                         StreamResult result = new StreamResult(stream);
315
316                         transformer.transform(source, result);
317
318                 } catch (ParserConfigurationException e) {
319                         throwWriteException(e);
320                 } catch (TransformerException e) {
321                         throwWriteException(e);
322                 }
323         }
324
325         private static void throwReadException(Throwable t) throws CoreException {
326                 int code;
327                 if (t instanceof SAXException)
328                         code = TEMPLATE_PARSE_EXCEPTION;
329                 else
330                         code = TEMPLATE_IO_EXCEPTION;
331                 // IStatus status= JavaUIStatus.createError(code,
332                 // TemplateMessages.getString("TemplateSet.error.read"), t);
333                 // //$NON-NLS-1$
334                 // throw new JavaUIException(status);
335                 throw new CoreException(
336                                 new Status(
337                                                 IStatus.ERROR,
338                                                 "org.eclipse.jface.text", code, JavaTemplateMessages.getString("TemplateSet.error.read"), t)); //$NON-NLS-1$ //$NON-NLS-2$
339         }
340
341         private static void throwWriteException(Throwable t) throws CoreException {
342                 // IStatus status=
343                 // JavaUIStatus.createError(IJavaStatusConstants.TEMPLATE_IO_EXCEPTION,
344                 // TemplateMessages.getString("TemplateSet.error.write"), t);
345                 // //$NON-NLS-1$
346                 // throw new JavaUIException(status);
347                 throw new CoreException(
348                                 new Status(
349                                                 IStatus.ERROR,
350                                                 "org.eclipse.jface.text", TEMPLATE_IO_EXCEPTION, JavaTemplateMessages.getString("TemplateSet.error.write"), t)); //$NON-NLS-1$ //$NON-NLS-2$
351         }
352
353         /**
354          * Adds a template to the set.
355          */
356         public void add(Template template) {
357                 if (exists(template))
358                         return; // ignore duplicate
359
360                 fTemplates.add(template);
361         }
362
363         private boolean exists(Template template) {
364                 for (Iterator iterator = fTemplates.iterator(); iterator.hasNext();) {
365                         Template anotherTemplate = (Template) iterator.next();
366
367                         if (template.equals(anotherTemplate))
368                                 return true;
369                 }
370
371                 return false;
372         }
373
374         /**
375          * Removes a template to the set.
376          */
377         public void remove(Template template) {
378                 fTemplates.remove(template);
379         }
380
381         /**
382          * Empties the set.
383          */
384         public void clear() {
385                 fTemplates.clear();
386         }
387
388         /**
389          * Returns all templates.
390          */
391         public Template[] getTemplates() {
392                 return (Template[]) fTemplates.toArray(new Template[fTemplates.size()]);
393         }
394
395         /**
396          * Returns all templates with a given name.
397          */
398         public Template[] getTemplates(String name) {
399                 ArrayList res = new ArrayList();
400                 for (Iterator iterator = fTemplates.iterator(); iterator.hasNext();) {
401                         Template curr = (Template) iterator.next();
402                         if (curr.getName().equals(name)) {
403                                 res.add(curr);
404                         }
405                 }
406                 return (Template[]) res.toArray(new Template[res.size()]);
407         }
408
409         /**
410          * Returns the first templates with the given name.
411          */
412         public Template getFirstTemplate(String name) {
413                 for (Iterator iterator = fTemplates.iterator(); iterator.hasNext();) {
414                         Template curr = (Template) iterator.next();
415                         if (curr.getName().equals(name)) {
416                                 return curr;
417                         }
418                 }
419                 return null;
420         }
421
422 }