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