2 * (c) Copyright IBM Corp. 2000, 2001.
5 package net.sourceforge.phpdt.internal.corext.template;
8 import java.io.StringReader;
9 import java.util.HashMap;
10 import java.util.Iterator;
13 import java.util.Vector;
15 import org.eclipse.core.runtime.CoreException;
18 * The template translator translates a string into a template buffer.
19 * The EBNF grammer of a valid string is as follows:
22 * template := (text | escape)*.<br />
23 * text := character - dollar.<br />
24 * escape := dollar ('{' identifier '}' | dollar).<br />
25 * dollar := '$'.<br />
28 public class TemplateTranslator {
31 private static final int TEXT= 0;
32 private static final int ESCAPE= 1;
33 private static final int IDENTIFIER= 2;
36 private static final char ESCAPE_CHARACTER= '$';
37 private static final char IDENTIFIER_BEGIN= '{';
38 private static final char IDENTIFIER_END= '}';
40 /** a buffer for the translation result string */
41 private final StringBuffer fBuffer= new StringBuffer();
42 /** position offsets of variables */
43 private final Vector fOffsets= new Vector();
44 /** position lengths of variables */
45 private final Vector fLengths= new Vector();
47 /** the current parsing state */
49 /** the last translation error */
50 private String fErrorMessage;
53 * Returns an error message if an error occured for the last translation, <code>null</code>
56 public String getErrorMessage() {
61 * Translates a template string to <code>TemplateBuffer</code>. <code>null</code>
62 * is returned if there was an error. <code>getErrorMessage()</code> retrieves the
63 * associated error message.
65 * @param string the string to translate.
66 * @return returns the template buffer corresponding to the string, <code>null</code>
67 * if there was an error.
68 * @see #getErrorMessage()
70 public TemplateBuffer translate(String string) throws CoreException {
85 // illegal, but be tolerant
87 fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.incomplete.variable"); //$NON-NLS-1$
88 fBuffer.append(ESCAPE_CHARACTER);
91 // illegal, but be tolerant
93 fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.incomplete.variable"); //$NON-NLS-1$
94 fBuffer.append(ESCAPE_CHARACTER);
98 int[] offsets= new int[fOffsets.size()];
99 int[] lengths= new int[fLengths.size()];
101 for (int i= 0; i < fOffsets.size(); i++) {
102 offsets[i]= ((Integer) fOffsets.get(i)).intValue();
103 lengths[i]= ((Integer) fLengths.get(i)).intValue();
106 String translatedString= fBuffer.toString();
107 TemplatePosition[] variables= findVariables(translatedString, offsets, lengths);
109 return new TemplateBuffer(translatedString, variables);
112 private static TemplatePosition[] findVariables(String string, int[] offsets, int[] lengths) {
114 Map map= new HashMap();
116 for (int i= 0; i != offsets.length; i++) {
117 int offset= offsets[i];
118 int length= lengths[i];
120 String content= string.substring(offset, offset + length);
121 Vector vector= (Vector) map.get(content);
122 if (vector == null) {
123 vector= new Vector();
124 map.put(content, vector);
126 vector.add(new Integer(offset));
129 TemplatePosition[] variables= new TemplatePosition[map.size()];
132 Set keys= map.keySet();
133 for (Iterator i= keys.iterator(); i.hasNext(); ) {
134 String name= (String) i.next();
135 Vector vector= (Vector) map.get(name);
137 int[] offsets_= new int[vector.size()];
138 for (int j= 0; j != offsets_.length; j++)
139 offsets_[j]= ((Integer) vector.get(j)).intValue();
141 variables[k]= new TemplatePosition(name, name, offsets_, name.length());
148 /** internal parser */
149 private boolean parse(String string) {
151 for (int i= 0; i != string.length(); i++) {
152 char ch= string.charAt(i);
157 case ESCAPE_CHARACTER:
169 case ESCAPE_CHARACTER:
174 case IDENTIFIER_BEGIN:
175 fOffsets.add(new Integer(fBuffer.length()));
180 // illegal single escape character, but be tolerant
181 fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.incomplete.variable"); //$NON-NLS-1$
182 fBuffer.append(ESCAPE_CHARACTER);
192 int offset = ((Integer) fOffsets.get(fOffsets.size() - 1)).intValue();
193 fLengths.add(new Integer(fBuffer.length() - offset));
198 if (!Character.isUnicodeIdentifierStart((char) ch) &&
199 !Character.isUnicodeIdentifierPart((char) ch))
201 // illegal identifier character
202 fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.invalid.identifier"); //$NON-NLS-1$