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