001: package org.drools.eclipse.editors.completion;
002:
003: import java.io.BufferedReader;
004: import java.io.IOException;
005: import java.io.StringReader;
006: import java.util.regex.Pattern;
007:
008: import org.eclipse.jdt.core.Signature;
009:
010: public class CompletionUtil {
011:
012: protected static final Pattern INCOMPLETED_MVEL_EXPRESSION = Pattern
013: .compile("[\\.\\(\\{\\[]\\Z", Pattern.DOTALL);
014:
015: protected static final Pattern COMPLETED_MVEL_EXPRESSION = Pattern
016: .compile("]\\)\\}\\]\\Z", Pattern.DOTALL);
017:
018: private CompletionUtil() {
019: }
020:
021: /**
022: * Looks behind, gets stuff after the white space. Basically ripping out the
023: * last word.
024: */
025: public static String stripLastWord(String prefix) {
026: if ("".equals(prefix)) {
027: return prefix;
028: }
029: if (prefix.charAt(prefix.length() - 1) == ' ') {
030: return "";
031: } else {
032: char[] c = prefix.toCharArray();
033: int start = 0;
034: for (int i = c.length - 1; i >= 0; i--) {
035: if (Character.isWhitespace(c[i]) || c[i] == '('
036: || c[i] == ':' || c[i] == ';' || c[i] == '='
037: || c[i] == '<' || c[i] == '>' || c[i] == '.'
038: || c[i] == '{' || c[i] == '}') {
039: start = i + 1;
040: break;
041: }
042: }
043: prefix = prefix.substring(start, prefix.length());
044: return prefix;
045: }
046: }
047:
048: public static String stripWhiteSpace(String prefix) {
049: if ("".equals(prefix)) {
050: return prefix;
051: }
052: if (prefix.charAt(prefix.length() - 1) == ' ') {
053: return "";
054: } else {
055: char[] c = prefix.toCharArray();
056: int start = 0;
057: for (int i = c.length - 1; i >= 0; i--) {
058: if (Character.isWhitespace(c[i])) {
059: start = i + 1;
060: break;
061: }
062: }
063: prefix = prefix.substring(start, prefix.length());
064: return prefix;
065: }
066: }
067:
068: /**
069: * Attempt to enhance a consequence backtext such that it should compile in MVEL
070: * @param backText
071: * @return a substring of the back text, that should be compilable without
072: * syntax errors by the mvel compiler TODO: add tests and more use
073: * cases
074: */
075: public static String getCompilableText(String backText) {
076: if (backText.trim().endsWith(";")) {
077: // RHS expression should compile if it ends with ;. but to hget the last object, we do no want it
078: return backText.substring(0, backText.length() - 1);
079: } else if (backText.endsWith(".")) {
080: // RHS expression should compile if it ends with ;
081: return backText.substring(0, backText.length() - 1);
082: } else if (CompletionUtil.COMPLETED_MVEL_EXPRESSION.matcher(
083: backText).matches()) {
084: // RHS expression should compile if closed. just need to close the
085: // statement
086: return backText + ";";
087: } else if (INCOMPLETED_MVEL_EXPRESSION.matcher(backText)
088: .matches()) {
089: // remove the last char and close the statement
090: return backText.substring(0, backText.length() - 1);
091: } else {
092: return backText;
093: }
094: }
095:
096: /*
097: * propertyname extraction and bean convention methods names checks
098: */
099:
100: public static boolean isGetter(String methodName, int argCount,
101: String returnedType) {
102: return isAccessor(methodName, argCount, 0, "get", returnedType,
103: Signature.SIG_VOID, false);
104: }
105:
106: public static boolean isSetter(String methodName, int argCount,
107: String returnedType) {
108: return isAccessor(methodName, argCount, 1, "set", returnedType,
109: Signature.SIG_VOID, true);
110: }
111:
112: public static boolean isIsGetter(String methodName, int argCount,
113: String returnedType) {
114: return isAccessor(methodName, argCount, 0, "is", returnedType,
115: Signature.SIG_BOOLEAN, true);
116: }
117:
118: /**
119: * Given a data depicting a method (name, # or params/args, returned type key), tries to return a bean property name derived from that method.
120: * If a bean property name is not found, the initial method name is returned
121: * @param methodName
122: * @param parameterCount
123: * @param returnType
124: * @return a bean property name
125: */
126: public static String getPropertyName(String methodName,
127: int parameterCount, String returnType) {
128: if (methodName == null) {
129: return null;
130: }
131: String simpleName = methodName.replaceAll("\\(\\)", "");
132: int prefixLength = 0;
133: if (isIsGetter(simpleName, parameterCount, returnType)) {
134:
135: prefixLength = 2;
136:
137: } else if (isGetter(simpleName, parameterCount, returnType) //
138: || isSetter(simpleName, parameterCount, returnType)) {
139:
140: prefixLength = 3;
141: } else {
142: return methodName;
143: }
144:
145: char firstChar = Character.toLowerCase(simpleName
146: .charAt(prefixLength));
147: String propertyName = firstChar
148: + simpleName.substring(prefixLength + 1);
149: return propertyName;
150: }
151:
152: public static String getPropertyName(String methodName,
153: char[] signature) {
154: if (signature == null || methodName == null) {
155: return methodName;
156: }
157:
158: int parameterCount = Signature.getParameterCount(signature);
159: String returnType = new String(Signature
160: .getReturnType(signature));
161:
162: return getPropertyName(methodName, parameterCount, returnType);
163: }
164:
165: /**
166: * Determine if the given method is a bean accessor (ie getter/setter)
167: * @param methodName
168: * @param actualParameterCount
169: * @param requiredParameterCount
170: * @param prefix
171: * @param returnType
172: * @param requiredReturnType
173: * @param includeType
174: * @return true if the method is a bean accessor, false otherwise
175: */
176: private static boolean isAccessor(String methodName,
177: int actualParameterCount, int requiredParameterCount,
178: String prefix, String returnType,
179: String requiredReturnType, boolean includeType) {
180:
181: //must be longer than the accessor prefix
182: if (methodName.length() < prefix.length() + 1) {
183: return false;
184: }
185:
186: //start with get, set or is
187: if (!methodName.startsWith(prefix)) {
188: return false;
189: }
190:
191: if (actualParameterCount != requiredParameterCount) {
192: return false;
193: }
194:
195: //if we check for the returned type, verify that the returned type is of the cirrect type signature
196: if (includeType) {
197: if (!requiredReturnType.equals(returnType)) {
198: return false;
199: }
200: } else {
201: if (requiredReturnType.equals(returnType)) {
202: return false;
203: }
204: }
205: return true;
206: }
207:
208: public static boolean isStartOfNewStatement(String text,
209: String prefix) {
210: String javaTextWithoutPrefix = text.substring(0, text.length()
211: - prefix.length());
212:
213: if ("".equals(javaTextWithoutPrefix.trim())
214: || DefaultCompletionProcessor.START_OF_NEW_JAVA_STATEMENT
215: .matcher(javaTextWithoutPrefix).matches()) {
216: return true;
217: }
218: return false;
219: }
220:
221: public static String getLastLine(String text) {
222: final BufferedReader reader = new BufferedReader(
223: new StringReader(text));
224: String line = null;
225: String lastLine = null;
226: try {
227: while ((line = reader.readLine()) != null) {
228: if (line.trim().length() > 0) {
229: lastLine = line;
230: }
231: }
232: } catch (final IOException e) {
233: // should never happen, it's just reading over a string.
234: }
235: return lastLine;
236: }
237: }
|