2 * (c) Copyright IBM Corp. 2000, 2001.
5 package net.sourceforge.phpdt.internal.corext.template;
7 import java.util.HashMap;
8 import java.util.Iterator;
11 import java.util.Vector;
13 import org.eclipse.core.runtime.CoreException;
16 * The template translator translates a string into a template buffer.
17 * The EBNF grammer of a valid string is as follows:
20 * template := (text | escape)*.<br />
21 * text := character - dollar.<br />
22 * escape := dollar ('{' identifier '}' | dollar).<br />
23 * dollar := '$'.<br />
26 public class TemplateTranslator {
29 private static final int TEXT= 0;
30 private static final int ESCAPE= 1;
31 private static final int IDENTIFIER= 2;
34 private static final char ESCAPE_CHARACTER= '$';
35 private static final char IDENTIFIER_BEGIN= '{';
36 private static final char IDENTIFIER_END= '}';
38 /** a buffer for the translation result string */
39 private final StringBuffer fBuffer= new StringBuffer();
40 /** position offsets of variables */
41 private final Vector fOffsets= new Vector();
42 /** position lengths of variables */
43 private final Vector fLengths= new Vector();
45 /** the current parsing state */
47 /** the last translation error */
48 private String fErrorMessage;
51 * Returns an error message if an error occured for the last translation, <code>null</code>
54 public String getErrorMessage() {
59 * Translates a template string to <code>TemplateBuffer</code>. <code>null</code>
60 * is returned if there was an error. <code>getErrorMessage()</code> retrieves the
61 * associated error message.
63 * @param string the string to translate.
64 * @return returns the template buffer corresponding to the string, <code>null</code>
65 * if there was an error.
66 * @see #getErrorMessage()
68 public TemplateBuffer translate(String string) throws CoreException {
83 // illegal, but be tolerant
85 fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.incomplete.variable"); //$NON-NLS-1$
86 fBuffer.append(ESCAPE_CHARACTER);
89 // illegal, but be tolerant
91 fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.incomplete.variable"); //$NON-NLS-1$
92 fBuffer.append(ESCAPE_CHARACTER);
96 int[] offsets= new int[fOffsets.size()];
97 int[] lengths= new int[fLengths.size()];
99 for (int i= 0; i < fOffsets.size(); i++) {
100 offsets[i]= ((Integer) fOffsets.get(i)).intValue();
101 lengths[i]= ((Integer) fLengths.get(i)).intValue();
104 String translatedString= fBuffer.toString();
105 TemplatePosition[] variables= findVariables(translatedString, offsets, lengths);
107 return new TemplateBuffer(translatedString, variables);
110 private static TemplatePosition[] findVariables(String string, int[] offsets, int[] lengths) {
112 Map map= new HashMap();
114 for (int i= 0; i != offsets.length; i++) {
115 int offset= offsets[i];
116 int length= lengths[i];
118 String content= string.substring(offset, offset + length);
119 Vector vector= (Vector) map.get(content);
120 if (vector == null) {
121 vector= new Vector();
122 map.put(content, vector);
124 vector.add(new Integer(offset));
127 TemplatePosition[] variables= new TemplatePosition[map.size()];
130 Set keys= map.keySet();
131 for (Iterator i= keys.iterator(); i.hasNext(); ) {
132 String name= (String) i.next();
133 Vector vector= (Vector) map.get(name);
135 int[] offsets_= new int[vector.size()];
136 for (int j= 0; j != offsets_.length; j++)
137 offsets_[j]= ((Integer) vector.get(j)).intValue();
139 variables[k]= new TemplatePosition(name, name, offsets_, name.length());
146 /** internal parser */
147 private boolean parse(String string) {
149 for (int i= 0; i != string.length(); i++) {
150 char ch= string.charAt(i);
155 case ESCAPE_CHARACTER:
167 case ESCAPE_CHARACTER:
172 case IDENTIFIER_BEGIN:
173 fOffsets.add(new Integer(fBuffer.length()));
178 // illegal single escape character, but be tolerant
179 fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.incomplete.variable"); //$NON-NLS-1$
180 fBuffer.append(ESCAPE_CHARACTER);
190 int offset = ((Integer) fOffsets.get(fOffsets.size() - 1)).intValue();
191 fLengths.add(new Integer(fBuffer.length() - offset));
196 if (!Character.isUnicodeIdentifierStart((char) ch) &&
197 !Character.isUnicodeIdentifierPart((char) ch))
199 // illegal identifier character
200 fErrorMessage= TemplateMessages.getString("TemplateTranslator.error.invalid.identifier"); //$NON-NLS-1$