Author: akazakov
Date: 2007-07-20 14:43:09 -0400 (Fri, 20 Jul 2007)
New Revision: 2574
Added:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELCompletionEngine.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamExpressionResolver.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidationHelper.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidator.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidationHelper.java
Removed:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidationHelper.java
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELCompletionEngine.java
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamExpressionResolver.java
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/META-INF/MANIFEST.MF
trunk/seam/plugins/org.jboss.tools.seam.core/plugin.xml
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidator.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidationContext.java
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidator.java
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalComputer.java
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalProcessor.java
Log:
http://jira.jboss.com/jira/browse/EXIN-327 EL Validation in XML
Modified: trunk/seam/plugins/org.jboss.tools.seam.core/META-INF/MANIFEST.MF
===================================================================
--- trunk/seam/plugins/org.jboss.tools.seam.core/META-INF/MANIFEST.MF 2007-07-20 17:46:54
UTC (rev 2573)
+++ trunk/seam/plugins/org.jboss.tools.seam.core/META-INF/MANIFEST.MF 2007-07-20 18:43:09
UTC (rev 2574)
@@ -23,7 +23,8 @@
org.eclipse.wst.validation,
org.eclipse.jst.j2ee.web,
org.eclipse.jst.j2ee,
- org.eclipse.jst.ws
+ org.eclipse.jst.ws,
+ org.eclipse.jface.text
Provide-Package: org.jboss.tools.seam.core,
org.jboss.tools.seam.internal.core,
org.jboss.tools.seam.internal.core.scanner,
@@ -32,6 +33,8 @@
Export-Package: org.jboss.tools.seam.core,
org.jboss.tools.seam.core.event,
org.jboss.tools.seam.internal.core,
+ org.jboss.tools.seam.internal.core.el,
+ org.jboss.tools.seam.internal.core.preferences,
org.jboss.tools.seam.internal.core.project.facet,
org.jboss.tools.seam.internal.core.scanner,
org.jboss.tools.seam.internal.core.scanner.java,
Modified: trunk/seam/plugins/org.jboss.tools.seam.core/plugin.xml
===================================================================
--- trunk/seam/plugins/org.jboss.tools.seam.core/plugin.xml 2007-07-20 17:46:54 UTC (rev
2573)
+++ trunk/seam/plugins/org.jboss.tools.seam.core/plugin.xml 2007-07-20 18:43:09 UTC (rev
2574)
@@ -141,10 +141,10 @@
objectClass="org.eclipse.core.resources.IFile"
nameFilter="*.xml"/>
<markerId
- markerIdValue="seamProblem">
+ markerIdValue="seamCoreProblem">
</markerId>
<helper
- class="org.jboss.tools.seam.internal.core.validation.SeamCoreValidationHelper">
+ class="org.jboss.tools.seam.internal.core.validation.SeamValidationHelper">
</helper>
<run
class="org.jboss.tools.seam.internal.core.validation.SeamCoreValidator"
@@ -153,15 +153,75 @@
/>
</validator>
</extension>
+ <extension
+ point="org.eclipse.wst.validation.validator"
+ id="SeamELValidator"
+ name="Seam EL Validator">
+ <validator>
+ <projectNature id="org.jboss.tools.seam.core.seamnature" />
+ <filter
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.java"/>
+ <filter
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.xml"/>
+ <filter
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.xhtml"/>
+ <filter
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.jsp">
+ </filter>
+ <filter
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.jspf">
+ </filter>
+ <filter
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.jsf">
+ </filter>
+ <filter
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.jsv">
+ </filter>
+ <filter
+ objectClass="org.eclipse.core.resources.IFile"
+ nameFilter="*.jtpl">
+ </filter>
+ <contentTypeBinding
contentTypeId="org.eclipse.jst.jsp.core.jspsource"/>
+ <contentTypeBinding
contentTypeId="org.eclipse.jst.jsp.core.jspfragmentsource"/>
+ <contentTypeBinding
contentTypeId="org.eclipse.jst.jsp.core.tagsource"/>
+ <markerId
+ markerIdValue="seamELProblem">
+ </markerId>
+ <helper
+ class="org.jboss.tools.seam.internal.core.validation.SeamELValidationHelper">
+ </helper>
+ <run
+
class="org.jboss.tools.seam.internal.core.validation.SeamELValidator"
+ incremental="true"
+ fullBuild="true"
+ />
+ </validator>
+ </extension>
<extension
- id="seamProblem"
- name="Seam Problem"
+ id="seamCoreProblem"
+ name="Seam Core Problem"
point="org.eclipse.core.resources.markers">
<super type="org.eclipse.wst.validation.problemmarker"/>
<persistent
value="true">
</persistent>
</extension>
+ <extension
+ id="seamELProblem"
+ name="Seam EL Problem"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.wst.validation.problemmarker"/>
+ <persistent
+ value="true">
+ </persistent>
+ </extension>
</plugin>
\ No newline at end of file
Copied:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELCompletionEngine.java
(from rev 2536,
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELCompletionEngine.java)
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELCompletionEngine.java
(rev 0)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamELCompletionEngine.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -0,0 +1,830 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Distributed under license by Red Hat, Inc. All rights reserved.
+ * This program is made available under the terms of the
+ * Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at
http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributor:
+ * Red Hat, Inc. - initial API and implementation
+ ******************************************************************************/
+package org.jboss.tools.seam.internal.core.el;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.rules.IToken;
+import org.jboss.tools.common.model.util.EclipseJavaUtil;
+import org.jboss.tools.seam.core.ISeamComponent;
+import org.jboss.tools.seam.core.ISeamContextVariable;
+import org.jboss.tools.seam.core.ISeamProject;
+import org.jboss.tools.seam.core.ScopeType;
+import org.jboss.tools.seam.core.SeamCorePlugin;
+
+/**
+ * Utility class used to find Seam Project content assist proposals
+ *
+ * @author Jeremy
+ */
+public final class SeamELCompletionEngine {
+
+ /**
+ * Constructs SeamELCompletionEngine object
+ */
+ public SeamELCompletionEngine() {
+
+ }
+
+ /**
+ * Create the array of suggestions.
+ *
+ * @param project Seam project
+ * @param file File
+ * @param document
+ * @param prefix the prefix to search for
+ * @param position Offset of the prefix
+ * @return the list of all possible suggestions
+ * @throws BadLocationException if accessing the current document fails
+ */
+ public List<String> getCompletions(ISeamProject project, IFile file, IDocument
document, CharSequence prefix,
+ int position) throws BadLocationException, StringIndexOutOfBoundsException {
+ String documentContent = null;
+ if(document!=null) {
+ documentContent = document.get();
+ }
+ return getCompletions(project, file, documentContent, prefix, position, false);
+ }
+
+ /**
+ * Create the array of suggestions.
+ * @param project Seam project
+ * @param file File
+ * @param document
+ * @param prefix the prefix to search for
+ * @param position Offset of the prefix
+ * @return the list of all possible suggestions
+ * @param returnCompletedVariablesOnly - if 'true' then returns only variables
that equals prefix. It's useful for validation.
+ * for example:
+ * we have 'variableName.variableProperty',
'variableName.variableProperty1', 'variableName.variableProperty2'
+ * prefix is 'variableName.variableProperty'
+ * Result is {'variableProperty'}
+ * if 'false' then returns ends of variables that starts with prefix. It's
useful for CA.
+ * for example:
+ * we have 'variableName.variableProperty',
'variableName.variableProperty1', 'variableName.variableProperty2'
+ * prefix is 'variableName.variableProperty'
+ * Result is {'1','2'}
+ */
+ public List<String> getCompletions(ISeamProject project, IFile file, String
documentContent, CharSequence prefix,
+ int position, boolean returnEqualedVariablesOnly) throws BadLocationException,
StringIndexOutOfBoundsException {
+
+ List<String> res= new ArrayList<String>();
+ SeamELTokenizer tokenizer = new SeamELTokenizer(documentContent, position +
prefix.length());
+ List<ELToken> tokens = tokenizer.getTokens();
+
+ List<ELToken> resolvedExpressionPart = new ArrayList<ELToken>();
+ List<ISeamContextVariable> resolvedVariables = new
ArrayList<ISeamContextVariable>();
+ ScopeType scope = getScope(project, file);
+ List<List<ELToken>> variations = getPossibleVarsFromPrefix(tokens);
+
+ if (variations.isEmpty()) {
+ resolvedVariables = resolveVariables(project, scope, tokens, tokens);
+ } else {
+ for (List<ELToken> variation : variations) {
+ List<ISeamContextVariable>resolvedVars = new
ArrayList<ISeamContextVariable>();
+ resolvedVars = resolveVariables(project, scope, variation, tokens);
+ if (resolvedVars != null && !resolvedVars.isEmpty()) {
+ resolvedVariables = resolvedVars;
+ resolvedExpressionPart = variation;
+ break;
+ }
+ }
+ }
+
+ // Here we have a list of vars for some part of expression
+ // OK. we'll proceed with members of these vars
+ if (areEqualExpressions(resolvedExpressionPart, tokens)) {
+ // First segment is the last one
+ for (ISeamContextVariable var : resolvedVariables) {
+ res.add(var.getName().substring(prefix.toString().length()));
+ }
+ return res;
+ }
+
+ // First segment is found - proceed with next tokens
+ int startTokenIndex = (resolvedExpressionPart == null ? 0 :
resolvedExpressionPart.size());
+ Set<IMember> members = new HashSet<IMember>();
+ for (ISeamContextVariable var : resolvedVariables) {
+ IMember member = SeamExpressionResolver.getMemberByVariable(var);
+ if (member != null && !members.contains(member))
+ members.add(member);
+ }
+ for (int i = startTokenIndex;
+ tokens != null && i < tokens.size() &&
+ members != null && members.size() > 0;
+ i++) {
+ ELToken token = tokens.get(i);
+
+ if (i < tokens.size() - 1) { // inside expression
+ if (token.getType() == ELToken.EL_SEPARATOR_TOKEN)
+ // proceed with next token
+ continue;
+
+ if (token.getType() == ELToken.EL_NAME_TOKEN) {
+ // Find properties for the token
+ String name = token.getText();
+ Set<IMember> newMembers = new HashSet<IMember>();
+ for (IMember mbr : members) {
+ try {
+ IType type = (mbr instanceof IType ? (IType)mbr :
EclipseJavaUtil.findType(mbr.getJavaProject(),
EclipseJavaUtil.getMemberTypeAsString(mbr)));
+ Set<IMember> properties = SeamExpressionResolver.getProperties(type);
+ for (IMember property : properties) {
+ StringBuffer propertyName = new StringBuffer(property.getElementName());
+ if (property instanceof IMethod) { // Setter or getter
+ propertyName.delete(0, 3);
+ propertyName.setCharAt(0, Character.toLowerCase(propertyName.charAt(0)));
+ }
+ if (name.equals(propertyName.toString())) {
+ newMembers.add(property);
+ }
+ }
+ } catch (JavaModelException ex) {
+ SeamCorePlugin.getPluginLog().logError(ex);
+ }
+ }
+ members = newMembers;
+ }
+ if (token.getType() == ELToken.EL_METHOD_TOKEN) {
+ // Find methods for the token
+ String name = token.getText();
+ if (name.indexOf('(') != -1) {
+ name = name.substring(0, name.indexOf('('));
+ }
+ Set<IMember> newMembers = new HashSet<IMember>();
+ for (IMember mbr : members) {
+ try {
+ IType type = (mbr instanceof IType ? (IType)mbr :
EclipseJavaUtil.findType(mbr.getJavaProject(),
EclipseJavaUtil.getMemberTypeAsString(mbr)));
+ Set<IMember> methods = SeamExpressionResolver.getMethods(type);
+ for (IMember method : methods) {
+ if (name.equals(method.getElementName())) {
+ newMembers.add(method);
+ }
+ }
+ } catch (JavaModelException ex) {
+ SeamCorePlugin.getPluginLog().logError(ex);
+ }
+ }
+ members = newMembers;
+ }
+ } else { // Last segment
+ Set<String> proposals = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+ if (token.getType() == ELToken.EL_SEPARATOR_TOKEN) {
+ // return all the methods + properties
+ for (IMember mbr : members) {
+ try {
+ IType type = (mbr instanceof IType ? (IType)mbr :
EclipseJavaUtil.findType(mbr.getJavaProject(),
EclipseJavaUtil.getMemberTypeAsString(mbr)));
+ proposals.addAll(SeamExpressionResolver.getMethodPresentations(type));
+ proposals.addAll(SeamExpressionResolver.getPropertyPresentations(type));
+ } catch (JavaModelException ex) {
+ SeamCorePlugin.getPluginLog().logError(ex);
+ }
+ }
+ } else if (token.getType() == ELToken.EL_NAME_TOKEN ||
+ token.getType() == ELToken.EL_METHOD_TOKEN) {
+ // return filtered methods + properties
+ Set<String> proposalsToFilter = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+ for (IMember mbr : members) {
+ try {
+ IType type = null;
+ if(mbr instanceof IType) {
+ type = (IType)mbr;
+ } else {
+ type = EclipseJavaUtil.findType(mbr.getJavaProject(),
EclipseJavaUtil.getMemberTypeAsString(mbr));
+ }
+ proposalsToFilter.addAll(SeamExpressionResolver.getMethodPresentations(type));
+ proposalsToFilter.addAll(SeamExpressionResolver.getPropertyPresentations(type));
+ } catch (JavaModelException ex) {
+ SeamCorePlugin.getPluginLog().logError(ex);
+ }
+ }
+ for (String proposal : proposalsToFilter) {
+ // We do expect nothing but name for method tokens (No round brackets)
+ String filter = token.getText();
+ if(returnEqualedVariablesOnly) {
+ // This is used for validation.
+ if (proposal.equals(filter)) {
+ proposals.add(proposal);
+ }
+ } else {
+ // This is used for CA.
+ if (proposal.startsWith(filter)) {
+ proposals.add(proposal.substring(filter.length()));
+ }
+ }
+ }
+ }
+ res.addAll(proposals);
+ }
+ }
+
+ return res;
+ }
+
+ private String computeVariableName(List<ELToken> tokens){
+ if (tokens == null)
+ tokens = new ArrayList<ELToken>();
+ StringBuffer sb = new StringBuffer();
+ for (ELToken token : tokens) {
+ if (token.getType() == ELToken.EL_NAME_TOKEN ||
+ token.getType() == ELToken.EL_METHOD_TOKEN ||
+ token.getType() == ELToken.EL_SEPARATOR_TOKEN) {
+ sb.append(token.getText());
+ }
+ }
+ return sb.toString();
+ }
+
+ /*
+ * Compares to tokenized expressions.
+ *
+ * @param first
+ * @param second
+ * @return boolean true if two expressions are equal
+ */
+ private boolean areEqualExpressions(List<ELToken>first, List<ELToken>second)
{
+ if (first == null || second == null)
+ return (first == second);
+
+ if (first.size() != second.size())
+ return false;
+
+ for (int i = 0; i < first.size(); i++) {
+ if (!first.get(i).equals(second.get(i)))
+ return false;
+ }
+ return true;
+ }
+
+ /* Returns scope for the resource
+ *
+ * @param project
+ * @param resource
+ * @return
+ */
+ private ScopeType getScope(ISeamProject project, IResource resource) {
+ if (project == null || resource == null)
+ return null;
+
+ Set<ISeamComponent> components =
project.getComponentsByPath(resource.getFullPath());
+
+ if (components.size() > 1) // Don't use scope in case of more than one
component
+ return null;
+ for (ISeamComponent component : components) {
+ return component.getScope();
+ }
+ return null;
+ }
+
+ /*
+ * Tries to resolve variables by part of expression
+ *
+ * @param project
+ * @param scope
+ * @param part
+ * @param tokens
+ * @return
+ */
+ private List<ISeamContextVariable> resolveVariables(ISeamProject project,
ScopeType scope, List<ELToken>part, List<ELToken> tokens) {
+ List<ISeamContextVariable>resolvedVars = new
ArrayList<ISeamContextVariable>();
+ String varName = computeVariableName(part);
+ if (varName != null) {
+ resolvedVars = SeamExpressionResolver.resolveVariables(project, scope, varName);
+ }
+ if (resolvedVars != null && resolvedVars.size() > 0) {
+ List<ISeamContextVariable> newResolvedVars = new
ArrayList<ISeamContextVariable>();
+ for (ISeamContextVariable var : resolvedVars) {
+ if(!areEqualExpressions(part, tokens)) {
+ // Do filter by equals (name)
+ // In case of the last pass - do not filter by startsWith(name) instead of equals
+ if (varName.equals(var.getName())) {
+ newResolvedVars.add(var);
+ }
+ } else {
+ newResolvedVars.add(var);
+ }
+ }
+ return newResolvedVars;
+ }
+ return new ArrayList<ISeamContextVariable>();
+ }
+
+ /*
+ * Creates and returns list of possible variable name combinations from expression
starting from the longest name
+ *
+ *
+ * @param prefix
+ * @return
+ */
+ private List<List<ELToken>>
getPossibleVarsFromPrefix(List<ELToken>prefix) {
+ ArrayList<List<ELToken>> result = new
ArrayList<List<ELToken>>();
+ for (int i = 0; prefix != null && i < prefix.size(); i++) {
+ ELToken lastToken = prefix.get(i);
+ if (lastToken.getType() != ELToken.EL_SEPARATOR_TOKEN) {
+ ArrayList<ELToken> prefixPart = new ArrayList<ELToken>();
+ for (int j = 0; j <= i; j++) {
+ prefixPart.add(prefix.get(j));
+ }
+ result.add(0, prefixPart);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Removes duplicates of completion strings
+ *
+ * @param suggestions a list of suggestions ({@link String}).
+ * @return a list of unique completion suggestions.
+ */
+ public List<String> makeUnique(List<String> suggestions) {
+ HashSet<String> present = new HashSet<String>();
+ ArrayList<String> unique= new ArrayList<String>();
+
+ if (suggestions == null)
+ return unique;
+
+ for (String item : suggestions) {
+ if (!present.contains(item)) {
+ present.add(item);
+ unique.add(item);
+ }
+ }
+
+ present.clear();
+ return unique;
+ }
+
+ /**
+ * EL string parser.
+ * Creates list of tokens for the name, method and separator parts
+ *
+ * @author Jeremy
+ */
+ public static class SeamELTokenizer {
+ static final int STATE_INITIAL = 0;
+ static final int STATE_VAR = 1;
+ static final int STATE_METHOD = 2;
+ static final int STATE_SEPARATOR = 3;
+
+// IDocument fDocument;
+ String documentContent;
+ List<ELToken> fTokens;
+ int index;
+
+ /**
+ * Constructs SeamELTokenizer object
+ *
+ * @param document
+ * @param offset
+ */
+ public SeamELTokenizer(IDocument document, int offset) {
+ if(document!=null) {
+ this.documentContent = document.get();
+ }
+ index = (documentContent == null || documentContent.length() < offset? -1 :
offset);
+ fTokens = new ArrayList<ELToken>();
+ parseBackward();
+ }
+
+ /**
+ * Constructs SeamELTokenizer object
+ *
+ * @param document
+ * @param offset
+ */
+ public SeamELTokenizer(String documentContent, int offset) {
+ this.documentContent = documentContent;
+ index = (documentContent == null || documentContent.length() < offset? -1 :
offset);
+ fTokens = new ArrayList<ELToken>();
+ parseBackward();
+ }
+
+ /**
+ * Returns list of tokens for the expression parsed
+ *
+ * @return
+ */
+ public List<ELToken> getTokens() {
+ return fTokens;
+ }
+
+ /*
+ * Performs backward parsing of document text for expression
+ */
+ private void parseBackward() {
+ ELToken token;
+ fState = STATE_INITIAL;
+ while ((token = getNextToken()) != ELToken.EOF) {
+
+ if (token.type == ELToken.EL_NAME_TOKEN ||
+ token.type == ELToken.EL_METHOD_TOKEN ||
+ token.type == ELToken.EL_SEPARATOR_TOKEN) {
+
+ fTokens.add(0, token);
+ }
+ }
+ }
+
+ int fState;
+ int fEndOfToken;
+
+ /*
+ * Calculates and returns next token for expression
+ *
+ * @return
+ */
+ private ELToken getNextToken() {
+ switch (fState) {
+ case STATE_INITIAL: // Just started
+ {
+ int ch = readCharBackward();
+ if (ch == -1) {
+ return ELToken.EOF;
+ }
+ if (Character.isJavaIdentifierPart((char)ch)) {
+ releaseChar();
+ return readVarToken();
+ }
+ if (ch == '.') {
+ releaseChar();
+ return readSeparatorToken();
+ }
+ if (ch == ')') {
+ releaseChar();
+ return readMethodToken();
+ }
+ return ELToken.EOF;
+ }
+ case STATE_VAR: // Variable name is read - expecting a separator
+ {
+ int ch = readCharBackward();
+ if (ch == -1) {
+ return ELToken.EOF;
+ }
+ if (ch == '.') {
+ releaseChar();
+ return readSeparatorToken();
+ }
+ return ELToken.EOF;
+ }
+ case STATE_METHOD: // Method name and parameters are read - expecting a separator
+ {
+ int ch = readCharBackward();
+ if (ch == -1) {
+ return ELToken.EOF;
+ }
+ if (ch == '.') {
+ releaseChar();
+ return readSeparatorToken();
+ }
+ return ELToken.EOF;
+ }
+ case STATE_SEPARATOR: // Separator is read - expecting a var or method
+ {
+ int ch = readCharBackward();
+ if (ch == -1) {
+ return ELToken.EOF;
+ }
+ if (Character.isJavaIdentifierPart((char)ch)) {
+ releaseChar();
+ return readVarToken();
+ }
+ if (ch == ')') {
+ releaseChar();
+ return readMethodToken();
+ }
+ return ELToken.EOF;
+ }
+ }
+ return ELToken.EOF;
+ }
+
+ /* Reads and returns the method token from the expression
+ *
+ * @return
+ */
+ ELToken readMethodToken() {
+ fState = STATE_METHOD;
+ int endOfToken = index;
+
+ // read the method parameters
+ if (!skipMethodParameters())
+ return ELToken.EOF;
+
+ // skip spaces between the method's name and it's parameters
+ if (!skipSpaceChars())
+ return ELToken.EOF;
+ // read the method name
+ if (!skipMethodName())
+ return ELToken.EOF;
+
+ return (endOfToken - index > 0 ? new ELToken(index, endOfToken - index,
getCharSequence(index, endOfToken - index), ELToken.EL_METHOD_TOKEN) : ELToken.EOF);
+ }
+
+ /*
+ * Returns the CharSequence object
+ *
+ * @param start
+ * @param length
+ * @return
+ */
+ private CharSequence getCharSequence(int start, int length) {
+ String text = "";
+ try {
+ text.substring(start, length);
+ } catch (StringIndexOutOfBoundsException e) {
+ text = ""; // For sure
+ }
+ return text.subSequence(0, text.length());
+ }
+
+
+ /*
+ * Skips the space characters in the document
+ */
+ boolean skipSpaceChars() {
+ int ch;
+ while ((ch = readCharBackward()) != -1) {
+ if (!Character.isSpaceChar(ch)) {
+ releaseChar();
+ break;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * Skips the method name characters in the document
+ *
+ * @return boolean true if at least 1 character had been read
+ */
+ boolean skipMethodName() {
+ int endOfToken = index;
+ int ch;
+ while((ch = readCharBackward()) != -1) {
+ if (!Character.isJavaIdentifierPart(ch)) {
+ releaseChar();
+ return (endOfToken - index > 0);
+ }
+ }
+ return false;
+ }
+
+ /*
+ * Skips the method parameters characters in the document
+ *
+ * @return boolean true if complete parameters set had been read
+ */
+ boolean skipMethodParameters() {
+ int ch = readCharBackward();
+ if (ch != ')')
+ return false;
+ int pCount = 1;
+ while (pCount > 0) {
+ ch = readCharBackward();
+ if (ch == -1)
+ return false;
+
+ if (ch == '"' || ch == '\'') {
+ skipQuotedChars((char)ch);
+ continue;
+ }
+ if (ch == ')') {
+ pCount++;
+ continue;
+ }
+ if (ch == '(') {
+ pCount--;
+ continue;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * Skips the quoted characters
+ *
+ */
+ void skipQuotedChars(char pair) {
+ int ch = readCharBackward();
+
+ while (ch != -1) {
+ if (ch == pair) {
+ ch = readCharBackward();
+ if (ch == '\\') {
+ int backSlashCount = 0;
+ while (ch == '\\') {
+ backSlashCount++;
+ ch = readCharBackward();
+ }
+ releaseChar(); // Return the last non-slash char to the buffer
+ if ((backSlashCount/2)*2 == backSlashCount) {
+ return;
+ }
+ }
+ }
+ ch = readCharBackward();
+ }
+ }
+
+ /* Reads and returns the separator token from the expression
+ *
+ * @return
+ */
+ ELToken readSeparatorToken() {
+ fState = STATE_SEPARATOR;
+ int ch = readCharBackward();
+
+ return (ch == '.' ? new ELToken(index, 1, getCharSequence(index, 1),
ELToken.EL_SEPARATOR_TOKEN) :
+ ELToken.EOF);
+ }
+
+ /* Reads and returns the variable token from the expression
+ *
+ * @return
+ */
+ ELToken readVarToken() {
+ fState = STATE_VAR;
+ int endOfToken = index;
+ int ch;
+ while((ch = readCharBackward()) != -1) {
+ if (!Character.isJavaIdentifierPart(ch)) {
+ releaseChar();
+ return (endOfToken - index > 0 ? new ELToken(index, endOfToken - index,
getCharSequence(index, endOfToken - index), ELToken.EL_NAME_TOKEN) : ELToken.EOF);
+ }
+ }
+ releaseChar();
+ return (endOfToken - index > 0 ? new ELToken(index, endOfToken - index,
getCharSequence(index, endOfToken - index), ELToken.EL_NAME_TOKEN) : ELToken.EOF);
+ }
+
+ /* Reads the next character in the document
+ *
+ * @return
+ */
+ int readCharBackward() {
+ if (--index < 0 ||
+ documentContent == null ||
+ documentContent.length() <= index)
+ return -1;
+
+ try {
+ return documentContent.charAt(index);
+ } catch (StringIndexOutOfBoundsException e) {
+ return -1;
+ }
+ }
+
+ /*
+ * returns the character to the document
+ */
+ void releaseChar() {
+ if (index < documentContent.length())
+ index++;
+ }
+ }
+
+ /**
+ * Calculates the EX expression operand string
+ *
+ * @param viewer
+ * @param offset
+ * @return
+ * @throws BadLocationException
+ */
+ public static String getPrefix(ITextViewer viewer, int offset) throws
StringIndexOutOfBoundsException {
+ IDocument doc= viewer.getDocument();
+ if (doc == null || offset > doc.getLength())
+ return null;
+ return getPrefix(doc.get(), offset);
+ }
+
+ /**
+ * Calculates the EX expression operand string
+ *
+ * @param viewer
+ * @param offset
+ * @return
+ * @throws BadLocationException
+ */
+ public static String getPrefix(String documentContent, int offset) throws
StringIndexOutOfBoundsException {
+ if (documentContent == null || offset > documentContent.length())
+ return null;
+
+ SeamELTokenizer tokenizer = new SeamELTokenizer(documentContent, offset);
+ List<ELToken> tokens = tokenizer.getTokens();
+
+ if (tokens == null || tokens.size() == 0)
+ return null;
+
+ return documentContent.substring(tokens.get(0).start, offset - tokens.get(0).start);
+ }
+}
+
+/**
+ * Token for the EX expression
+ *
+ * @author Jeremy
+ */
+class ELToken implements IToken {
+ static final ELToken EOF = new ELToken(-1, -1, null, -1);
+ static final int EL_NAME_TOKEN = 1;
+ static final int EL_METHOD_TOKEN = 2;
+ static final int EL_SEPARATOR_TOKEN = 3;
+
+ int start;
+ int length;
+ CharSequence chars;
+ int type;
+
+ /**
+ * Constructs the ELToken object
+ *
+ * @param start
+ * @param length
+ * @param chars
+ * @param type
+ */
+ public ELToken(int start, int length, CharSequence chars, int type) {
+ this.start = start;
+ this.length = length;
+ this.chars = chars;
+ this.type = type;
+ }
+
+ /**
+ * Returns string representation for the token
+ */
+ public String toString() {
+ return "ELToken(" + start + ", " + length + ", " + type +
") [" + (chars == null ? "<Empty>" : chars.toString()) +
"]";
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IToken#getData()
+ */
+ public Object getData() {
+ return (chars == null ? null : chars.subSequence(start, start+length).toString());
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IToken#isEOF()
+ */
+ public boolean isEOF() {
+ return (start == -1 && length == -1 && chars == null);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IToken#isOther()
+ */
+ public boolean isOther() {
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IToken#isUndefined()
+ */
+ public boolean isUndefined() {
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.rules.IToken#isWhitespace()
+ */
+ public boolean isWhitespace() {
+ return false;
+ }
+
+ /*
+ * Returns the token type
+ */
+ public int getType(){
+ return type;
+ }
+
+ /*
+ * Returns the token text
+ */
+ public String getText() {
+ return chars.toString();
+ }
+}
\ No newline at end of file
Copied:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamExpressionResolver.java
(from rev 2501,
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamExpressionResolver.java)
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamExpressionResolver.java
(rev 0)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/el/SeamExpressionResolver.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Distributed under license by Red Hat, Inc. All rights reserved.
+ * This program is made available under the terms of the
+ * Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at
http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributor:
+ * Red Hat, Inc. - initial API and implementation
+ ******************************************************************************/
+
+package org.jboss.tools.seam.internal.core.el;
+
+import java.lang.reflect.Modifier;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.jboss.tools.seam.core.IBijectedAttribute;
+import org.jboss.tools.seam.core.ISeamComponent;
+import org.jboss.tools.seam.core.ISeamContextVariable;
+import org.jboss.tools.seam.core.ISeamElement;
+import org.jboss.tools.seam.core.ISeamJavaComponentDeclaration;
+import org.jboss.tools.seam.core.ISeamJavaSourceReference;
+import org.jboss.tools.seam.core.ISeamProject;
+import org.jboss.tools.seam.core.ISeamXmlFactory;
+import org.jboss.tools.seam.core.ScopeType;
+
+/**
+ * Utility class used to resolve Seam project variables and to get the methods/properties
and their presentation strings from type
+ *
+ * @author Jeremy
+ */
+public class SeamExpressionResolver {
+
+ /**
+ * Returns Seam project variables which names start from specified value
+ *
+ * @param project
+ * @param scope
+ * @param name
+ * @return
+ */
+ public static List<ISeamContextVariable> resolveVariables(ISeamProject project,
ScopeType scope, String name) {
+ if (project == null || name == null) return null;
+ return (scope == null ? internalResolveVariables(project, name) :
+ internalResolveVariablesByScope(project, scope, name));
+ }
+
+ /**
+ * Returns Seam project variables which names start from specified value
+ * No scope used
+ *
+ * @param project
+ * @param name
+ * @return
+ */
+ private static List<ISeamContextVariable> internalResolveVariables(ISeamProject
project, String name) {
+ List<ISeamContextVariable> resolvedVariables = new
ArrayList<ISeamContextVariable>();
+ Set<ISeamContextVariable> variables = project.getVariables();
+ for (ISeamContextVariable variable : variables) {
+ if (variable.getName().startsWith(name)) {
+ resolvedVariables.add(variable);
+ }
+ }
+ return resolvedVariables;
+ }
+
+ /**
+ * Returns Seam project variables which names start from specified value
+ * Search is performed using scope
+ *
+ * @param project
+ * @param scope
+ * @param name
+ * @return
+ */
+ private static List<ISeamContextVariable>
internalResolveVariablesByScope(ISeamProject project, ScopeType scope, String name) {
+ List<ISeamContextVariable> resolvedVariables = new
ArrayList<ISeamContextVariable>();
+ Set<ISeamContextVariable> variables = project.getVariablesByScope(scope);
+ for (ISeamContextVariable variable : variables) {
+ if (variable.getName().startsWith(name)) {
+ resolvedVariables.add(variable);
+ }
+ }
+ return resolvedVariables;
+ }
+
+ /**
+ * Returns the IMember for the variable specified
+ *
+ * @param variable
+ * @return
+ */
+ public static IMember getMemberByVariable(ISeamContextVariable variable) {
+ IMember member = null;
+ if (variable instanceof ISeamComponent) {
+ ISeamComponent component = (ISeamComponent)variable;
+ ISeamJavaComponentDeclaration decl = component.getJavaDeclaration();
+ if (decl != null) {
+ member = decl.getSourceMember();
+ }
+ }
+ if (member == null && variable instanceof IBijectedAttribute) {
+ member = ((ISeamJavaSourceReference)variable).getSourceMember();
+ }
+ if (member == null && variable instanceof ISeamJavaSourceReference) {
+ member = ((ISeamJavaSourceReference)variable).getSourceMember();
+ }
+ if (member == null && variable instanceof ISeamXmlFactory) {
+ ISeamXmlFactory factory = (ISeamXmlFactory)variable;
+ String value = factory.getValue();
+ if (value != null && value.length() > 0) {
+ if (value.startsWith("#{") || value.startsWith("${"))
+ value = value.substring(2);
+ if (value.endsWith("}"))
+ value = value.substring(0, value.length() - 1);
+ }
+ if (value != null && value.length() > 0) {
+ // TODO: Need to make sure that it's correct way to get the project and
+ // the scope from the factory
+ ISeamProject project = ((ISeamElement)factory).getSeamProject();
+// ISeamProject project = getSeamProject(factory.getResource());
+ if (project != null) {
+ List<ISeamContextVariable> resolvedValues = resolveVariables(project,
factory.getScope(), value);
+ for (ISeamContextVariable var : resolvedValues) {
+ if (var.getName().equals(value)) {
+ member = getMemberByVariable(var);
+ break;
+ }
+ }
+ }
+ }
+ }
+ return member;
+ }
+
+ /**
+ * Returns the methods for the type specified
+ *
+ * @param type
+ * @return
+ */
+ public static Set<IMember> getMethods(IType type) {
+ Set<IMember> methods = new HashSet<IMember>();
+ if (type != null) {
+ try {
+ IMethod[] mthds = type.getMethods();
+ for (int i = 0; mthds != null && i < mthds.length; i++) {
+ IMethod m = mthds[i];
+ if (Modifier.isPublic(m.getFlags()) &&
+ (!m.getElementName().startsWith("get") &&
!m.getElementName().startsWith("set")) ||
+ "get".equals(m.getElementName()) ||
"set".equals(m.getElementName())) {
+ methods.add(m);
+ }
+ }
+ } catch (JavaModelException e) {
+ }
+ }
+ return methods;
+ }
+
+ /**
+ * Returns the method presentation strings for the type specified
+ *
+ * @param type
+ * @return
+ */
+ public static Set<String> getMethodPresentations(IType type) {
+ Set<String> methods = new HashSet<String>();
+ if (type != null) {
+ try {
+ IMethod[] mthds = type.getMethods();
+ for (int i = 0; mthds != null && i < mthds.length; i++) {
+ IMethod m = mthds[i];
+ if (Modifier.isPublic(m.getFlags()) &&
+ (!m.getElementName().startsWith("get") &&
!m.getElementName().startsWith("set")) ||
+ "get".equals(m.getElementName()) ||
"set".equals(m.getElementName())) {
+
+ StringBuffer name = new StringBuffer(m.getElementName());
+
+ name.append('(');
+ String[] mParams = null;
+ mParams = m.getParameterNames();
+ for (int j = 0; mParams != null && j < mParams.length; j++) {
+ if (j > 0) name.append(", ");
+ name.append(mParams[j]);
+ }
+ name.append(')');
+
+ methods.add(name.toString());
+ }
+ }
+ } catch (JavaModelException e) {
+ }
+ }
+ return methods;
+ }
+
+ /**
+ * Returns the properties for the type specified
+ *
+ * @param type
+ * @return
+ */
+ public static Set<IMember> getProperties(IType type) {
+ Set<IMember> properties = new HashSet<IMember>();
+ if (type != null) {
+ try {
+ IMethod[] props = type.getMethods();
+ for (int i = 0; props != null && i < props.length; i++) {
+ IMethod m = props[i];
+ if (Modifier.isPublic(m.getFlags()) &&
+ (m.getElementName().startsWith("get") &&
!"get".equals(m.getElementName())) ||
+ (m.getElementName().startsWith("set") &&
!"set".equals(m.getElementName()))) {
+ properties.add(m);
+ }
+ }
+ } catch (JavaModelException e) {
+ }
+
+ try {
+ IField[] fields = type.getFields();
+ for (int i = 0; fields != null && i < fields.length; i++) {
+ IField f = fields[i];
+ if (Modifier.isPublic(f.getFlags())) {
+ properties.add(f);
+ }
+ }
+ } catch (JavaModelException e) {
+ }
+ }
+ return properties;
+ }
+
+ /**
+ * Returns the property presentation strings for the type specified
+ *
+ * @param type
+ * @return
+ */
+ public static Set<String> getPropertyPresentations(IType type) {
+ Set<String> properties = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+ if (type != null) {
+ try {
+ IMethod[] props = type.getMethods();
+ for (int i = 0; props != null && i < props.length; i++) {
+ IMethod m = props[i];
+ if (Modifier.isPublic(m.getFlags()) &&
+ (m.getElementName().startsWith("get") &&
!"get".equals(m.getElementName())) ||
+ (m.getElementName().startsWith("set") &&
!"set".equals(m.getElementName()))) {
+
+ StringBuffer name = new StringBuffer(m.getElementName());
+ name.delete(0, 3);
+ name.setCharAt(0, Character.toLowerCase(name.charAt(0)));
+
+ properties.add(name.toString());
+ }
+ }
+ } catch (JavaModelException e) {
+ }
+
+ try {
+ IField[] fields = type.getFields();
+ for (int i = 0; fields != null && i < fields.length; i++) {
+ IField f = fields[i];
+ if (Modifier.isPublic(f.getFlags())) {
+ properties.add(f.getElementName());
+ }
+ }
+ } catch (JavaModelException e) {
+ }
+ }
+ return properties;
+ }
+}
Deleted:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidationHelper.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidationHelper.java 2007-07-20
17:46:54 UTC (rev 2573)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidationHelper.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -1,262 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
- * Distributed under license by Red Hat, Inc. All rights reserved.
- * This program is made available under the terms of the
- * Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at
http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Exadel, Inc. and Red Hat, Inc. - initial API and implementation
- ******************************************************************************/
-package org.jboss.tools.seam.internal.core.validation;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.wst.validation.internal.operations.WorkbenchContext;
-import org.jboss.tools.common.model.util.EclipseResourceUtil;
-import org.jboss.tools.seam.core.ISeamComponent;
-import org.jboss.tools.seam.core.ISeamElement;
-import org.jboss.tools.seam.core.ISeamProject;
-import org.jboss.tools.seam.core.ISeamTextSourceReference;
-import org.jboss.tools.seam.core.SeamCorePlugin;
-import org.jboss.tools.seam.internal.core.AbstractContextVariable;
-import org.jboss.tools.seam.internal.core.SeamComponentDeclaration;
-import org.jboss.tools.seam.internal.core.SeamProject;
-
-public class SeamCoreValidationHelper extends WorkbenchContext {
-
- private SeamValidationContext validationContext;
-
- /**
- * @return Seam project
- */
- public ISeamProject getSeamProject() {
- ISeamProject project = null;
- try {
- project = SeamCorePlugin.getSeamProject(getProject(), true);
- } catch (Exception e) {
- SeamCorePlugin.getDefault().logError("Can't get Seam Project", e);
- }
- return project;
- }
-
- /**
- * @param element
- * @return Resource of seam model element
- */
- public IResource getComponentResourceWithName(ISeamElement element) {
- if(element instanceof ISeamComponent) {
- Set declarations = ((ISeamComponent)element).getAllDeclarations();
- for (Object o : declarations) {
- SeamComponentDeclaration d = (SeamComponentDeclaration)o;
- if(d.getLocationFor(SeamComponentDeclaration.PATH_OF_NAME)!=null) {
- return d.getResource();
- }
- }
- }
- return element.getResource();
- }
-
- /**
- * @param seam model element
- * @return location of name attribute
- */
- public ISeamTextSourceReference getLocationOfName(ISeamElement element) {
- return getLocationOfAttribute(element, SeamComponentDeclaration.PATH_OF_NAME);
- }
-
- /**
- * @param seam model element
- * @return location of attribute
- */
- public ISeamTextSourceReference getLocationOfAttribute(ISeamElement element, String
attributeName) {
- ISeamTextSourceReference location = null;
- if(element instanceof AbstractContextVariable) {
- location = ((AbstractContextVariable)element).getLocationFor(attributeName);
- } else if(element instanceof ISeamComponent) {
- Set declarations = ((ISeamComponent)element).getAllDeclarations();
- for (Object d : declarations) {
- location = ((SeamComponentDeclaration)d).getLocationFor(attributeName);
- if(location!=null) {
- break;
- }
- }
- } else if(element instanceof SeamComponentDeclaration) {
- location = ((SeamComponentDeclaration)element).getLocationFor(attributeName);
- }
- if(location==null && element instanceof ISeamTextSourceReference) {
- location = (ISeamTextSourceReference)element;
- }
- return location;
- }
-
- /**
- * @param resource
- * @return true if resource is Jar file
- */
- public boolean isJar(IResource resource) {
- String ext = resource.getFileExtension();
- return ext!=null && ext.equalsIgnoreCase("jar");
- }
-
- /**
- * @param element
- * @return true if seam element packed in Jar file
- */
- public boolean isJar(ISeamElement element) {
- return isJar(element.getResource());
- }
-
- /**
- * @param componentXmlFile
- * @return IType of component for <ComponentName>.component.xml
- */
- public IType getClassTypeForComponentXml(IFile componentXmlFile) {
- String className = getClassNameForComponentXml(componentXmlFile);
- if(className==null) {
- return null;
- }
- return findType(className);
- }
-
- /**
- * @param type name
- * @return IType
- */
- public IType findType(String fullyQualifiedName) {
- IProject p = getProject().getProject();
- try {
- IJavaProject jp = EclipseResourceUtil.getJavaProject(p);
- return jp.findType(fullyQualifiedName);
- } catch (JavaModelException e) {
- SeamCorePlugin.getDefault().logError(e);
- return null;
- }
- }
-
- /**
- * @param componentXmlFile
- * @return name of component class for <ComponentName>.component.xml
- */
- public String getClassNameForComponentXml(IFile componentXmlFile) {
- String fileName = componentXmlFile.getName();
- int firstDot = fileName.indexOf('.');
- if(firstDot==-1) {
- return null;
- }
- String className = fileName.substring(0, firstDot);
- IProject p = getProject().getProject();
- try {
- IJavaProject jp = EclipseResourceUtil.getJavaProject(p);
- IPackageFragment packageFragment =
jp.findPackageFragment(componentXmlFile.getFullPath().removeLastSegments(1));
- if(packageFragment==null) {
- return null;
- }
- return packageFragment.getElementName() + "." + className;
- } catch (JavaModelException e) {
- SeamCorePlugin.getDefault().logError(e);
- return null;
- }
- }
-
- /**
- * Find setter for property
- * @param type
- * @param propertyName
- * @return
- */
- public IMethod findSetter(IType type, String propertyName) {
- if(propertyName == null || propertyName.length()==0) {
- return null;
- }
- String firstLetter = propertyName.substring(0, 1).toUpperCase();
- String nameWithoutFirstLetter = propertyName.substring(1);
- String setterName = "set" + firstLetter + nameWithoutFirstLetter;
- try {
- return findSetterInHierarchy(type, setterName);
- } catch (JavaModelException e) {
- SeamCorePlugin.getDefault().logError(e);
- }
- return null;
- }
-
- private IMethod findSetterInHierarchy(IType type, String setterName) throws
JavaModelException {
- IMethod[] methods = type.getMethods();
- for (int i = 0; i < methods.length; i++) {
- if(methods[i].getElementName().equals(setterName) &&
methods[i].getParameterNames().length==1) {
- return methods[i];
- }
- }
- String superclassName = type.getSuperclassName();
- if(superclassName!=null) {
- String[][] packages = type.resolveType(superclassName);
- if(packages!=null) {
- for (int i = 0; i < packages.length; i++) {
- String packageName = packages[i][0];
- if(packageName!=null && packageName.length()>0) {
- packageName = packageName + ".";
- } else {
- packageName = "";
- }
- String qName = packageName + packages[i][1];
- IType superclass = type.getJavaProject().findType(qName);
- if(superclass!=null) {
- IMethod method = findSetterInHierarchy(superclass, setterName);
- if(method!=null) {
- return method;
- }
- }
- }
- }
- }
- return null;
- }
-
- /*
- * (non-Javadoc)
- * @see
org.eclipse.wst.validation.internal.operations.WorkbenchContext#registerResource(org.eclipse.core.resources.IResource)
- */
- @Override
- public void registerResource(IResource resource) {
- if(resource instanceof IFile) {
- IFile file = (IFile)resource;
- if(!file.exists()) {
- getValidationContext().addRemovedFile(file);
- }
- }
- }
-
- /**
- * @return Set of changed resources
- */
- public Set<IFile> getChangedFiles() {
- Set<IFile> result = new HashSet<IFile>();
- String[] uris = getURIs();
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- for (int i = 0; i < uris.length; i++) {
- IFile currentFile = root.getFile(new Path(uris[i]));
- result.add(currentFile);
- }
- result.addAll(getValidationContext().getRemovedFiles());
- return result;
- }
-
- public SeamValidationContext getValidationContext() {
- if(validationContext==null) {
- validationContext = ((SeamProject)getSeamProject()).getValidationContext();
- }
- return validationContext;
- }
-}
\ No newline at end of file
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidator.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidator.java 2007-07-20
17:46:54 UTC (rev 2573)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidator.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -23,14 +23,12 @@
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
-import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.seam.core.BijectedAttributeType;
import org.jboss.tools.seam.core.IBijectedAttribute;
@@ -61,91 +59,84 @@
*/
public class SeamCoreValidator extends SeamValidator {
- private static final String MARKED_SEAM_RESOURCE_MESSAGE_GROUP =
"markedSeamResource";
+ private static final String MARKED_SEAM_RESOURCE_MESSAGE_GROUP =
"markedSeamCoreResource";
- private SeamValidationContext validationContext;
-
- public ISchedulingRule getSchedulingRule(IValidationContext helper) {
- return null;
- }
-
- public IStatus validateInJob(IValidationContext helper, IReporter reporter) throws
ValidationException {
- super.validateInJob(helper, reporter);
- validationContext = ((SeamProject)project).getValidationContext();
- Set<IFile> changedFiles = coreHelper.getChangedFiles();
- validationContext.getRemovedFiles().clear();
- if(changedFiles.size()>0) {
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- Set<ISeamComponent> checkedComponents = new HashSet<ISeamComponent>();
- Set<String> markedDuplicateFactoryNames = new HashSet<String>();
- // Collect all resources which we must validate.
- Set<IPath> resources = new HashSet<IPath>(); // Resources which we have to
validate.
- Set<IPath> newResources = new HashSet<IPath>(); // New (unlinked)
resources file
- for(IFile currentFile : changedFiles) {
- if(reporter.isCancelled()) {
- break;
- }
- if (currentFile != null) {
- // Get all variable names that were linked with this resource.
- Set<String> oldVariablesNamesOfChangedFile =
validationContext.getVariableNamesByResource(currentFile.getFullPath());
- if(oldVariablesNamesOfChangedFile!=null) {
- // Check if variable name was changed in source file
- Set<String> newVariableNamesOfChangedFile =
getVariablesNameByResource(currentFile.getFullPath());
- for (String newVariableName : newVariableNamesOfChangedFile) {
- if(!oldVariablesNamesOfChangedFile.contains(newVariableName)) {
- // Name was changed.
- // Collect resources with new component name.
- Set<IPath> linkedResources =
validationContext.getResourcesByVariableName(newVariableName);
- if(linkedResources!=null) {
- resources.addAll(linkedResources);
- }
- }
- }
- resources.add(currentFile.getFullPath());
-
- // Collect all linked resources with old variable names.
- for (String name : oldVariablesNamesOfChangedFile) {
- Set<IPath> linkedResources =
validationContext.getResourcesByVariableName(name);
+ /* (non-Javadoc)
+ * @see
org.jboss.tools.seam.internal.core.validation.SeamValidator#validate(java.util.Set)
+ */
+ @Override
+ public IStatus validate(Set<IFile> changedFiles) throws ValidationException {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ Set<ISeamComponent> checkedComponents = new HashSet<ISeamComponent>();
+ Set<String> markedDuplicateFactoryNames = new HashSet<String>();
+ // Collect all resources which we must validate.
+ Set<IPath> resources = new HashSet<IPath>(); // Resources which we have to
validate.
+ Set<IPath> newResources = new HashSet<IPath>(); // New (unlinked) resources
file
+ for(IFile currentFile : changedFiles) {
+ if(reporter.isCancelled()) {
+ break;
+ }
+ if (currentFile != null) {
+ // Get all variable names that were linked with this resource.
+ Set<String> oldVariablesNamesOfChangedFile =
validationContext.getVariableNamesByResource(currentFile.getFullPath());
+ if(oldVariablesNamesOfChangedFile!=null) {
+ // Check if variable name was changed in source file
+ Set<String> newVariableNamesOfChangedFile =
getVariablesNameByResource(currentFile.getFullPath());
+ for (String newVariableName : newVariableNamesOfChangedFile) {
+ if(!oldVariablesNamesOfChangedFile.contains(newVariableName)) {
+ // Name was changed.
+ // Collect resources with new component name.
+ Set<IPath> linkedResources =
validationContext.getResourcesByVariableName(newVariableName);
if(linkedResources!=null) {
resources.addAll(linkedResources);
}
}
- } else {
- // Validate new (unlinked) source file.
- resources.add(currentFile.getFullPath());
}
- newResources.add(currentFile.getFullPath());
+ resources.add(currentFile.getFullPath());
+
+ // Collect all linked resources with old variable names.
+ for (String name : oldVariablesNamesOfChangedFile) {
+ Set<IPath> linkedResources =
validationContext.getResourcesByVariableName(name);
+ if(linkedResources!=null) {
+ resources.addAll(linkedResources);
+ }
+ }
+ } else {
+ // Validate new (unlinked) source file.
+ resources.add(currentFile.getFullPath());
}
+ newResources.add(currentFile.getFullPath());
}
- // Validate all collected linked resources.
- // Remove all links between collected resources and variables names because they will
be linked again during validation.
- validationContext.removeLinkedResources(resources);
- for (IPath linkedResource : resources) {
- // Remove markers from collected source file
- IFile sourceFile = root.getFile(linkedResource);
- reporter.removeMessageSubset(this, sourceFile, MARKED_SEAM_RESOURCE_MESSAGE_GROUP);
- validateComponent(linkedResource, checkedComponents);
- validateFactory(linkedResource, markedDuplicateFactoryNames);
- // TODO
- }
+ }
+ // Validate all collected linked resources.
+ // Remove all links between collected resources and variables names because they will
be linked again during validation.
+ validationContext.removeLinkedResources(resources);
+ for (IPath linkedResource : resources) {
+ // Remove markers from collected source file
+ IFile sourceFile = root.getFile(linkedResource);
+ reporter.removeMessageSubset(this, sourceFile, MARKED_SEAM_RESOURCE_MESSAGE_GROUP);
+ validateComponent(linkedResource, checkedComponents);
+ validateFactory(linkedResource, markedDuplicateFactoryNames);
+ }
- // Validate all unnamed resources.
- Set<IPath> unnamedResources = validationContext.getUnnamedResources();
- newResources.addAll(unnamedResources);
- for (IPath path : newResources) {
- Set<SeamJavaComponentDeclaration> declarations =
((SeamProject)project).findJavaDeclarations(path);
- for (SeamJavaComponentDeclaration d : declarations) {
- validateMethodsOfUnknownComponent(d);
- }
+ // Validate all unnamed resources.
+ Set<IPath> unnamedResources = validationContext.getUnnamedResources();
+ newResources.addAll(unnamedResources);
+ for (IPath path : newResources) {
+ Set<SeamJavaComponentDeclaration> declarations =
((SeamProject)project).findJavaDeclarations(path);
+ for (SeamJavaComponentDeclaration d : declarations) {
+ validateMethodsOfUnknownComponent(d);
}
- } else {
- return validateAll();
}
return OK_STATUS;
}
- private IStatus validateAll() {
+ /* (non-Javadoc)
+ * @see org.jboss.tools.seam.internal.core.validation.SeamValidator#validateAll()
+ */
+ @Override
+ public IStatus validateAll() throws ValidationException {
reporter.removeAllMessages(this);
validationContext.clear();
Set<ISeamComponent> components = project.getComponents();
@@ -164,7 +155,6 @@
validateMethodsOfUnknownComponent(d);
}
- // TODO
return OK_STATUS;
}
@@ -508,7 +498,7 @@
private void validateInAndOut(ISeamJavaComponentDeclaration declaration,
IBijectedAttribute bijection) {
String name = bijection.getName();
- if(name==null || name.startsWith("#{")) {
+ if(name==null || name.startsWith("#{") || name.startsWith("${")) {
return;
}
// save link between java source and variable name
Added:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidationHelper.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidationHelper.java
(rev 0)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidationHelper.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -0,0 +1,19 @@
+ /*******************************************************************************
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Distributed under license by Red Hat, Inc. All rights reserved.
+ * This program is made available under the terms of the
+ * Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at
http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ ******************************************************************************/
+package org.jboss.tools.seam.internal.core.validation;
+
+/**
+ * Helper for EL Seam valodator
+ * @author Alexey Kazakov
+ */
+public class SeamELValidationHelper extends SeamValidationHelper {
+
+}
\ No newline at end of file
Added:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidator.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidator.java
(rev 0)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamELValidator.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -0,0 +1,189 @@
+ /*******************************************************************************
+ * Copyright (c) 2007 Red Hat, Inc.
+ * Distributed under license by Red Hat, Inc. All rights reserved.
+ * This program is made available under the terms of the
+ * Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at
http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ ******************************************************************************/
+package org.jboss.tools.seam.internal.core.validation;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.wst.validation.internal.core.ValidationException;
+import org.jboss.tools.common.util.FileUtil;
+import org.jboss.tools.seam.core.SeamCorePlugin;
+import org.jboss.tools.seam.internal.core.el.SeamELCompletionEngine;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * EL Validator
+ * @author Alexey Kazakov
+ */
+public class SeamELValidator extends SeamValidator {
+
+ private SeamELCompletionEngine fEngine= new SeamELCompletionEngine();
+
+ /* (non-Javadoc)
+ * @see
org.jboss.tools.seam.internal.core.validation.SeamValidator#validate(java.util.Set)
+ */
+ @Override
+ public IStatus validate(Set<IFile> changedFiles) throws ValidationException {
+ // TODO
+ validateAll();
+ return OK_STATUS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.jboss.tools.seam.internal.core.validation.SeamValidator#validateAll()
+ */
+ @Override
+ public IStatus validateAll() throws ValidationException {
+ // TODO
+ /*
+ Set<IFile> files = validationContext.getRegisteredFiles();
+ for (IFile file : files) {
+ validateFile(file);
+ }
+ */
+
+ return OK_STATUS;
+ }
+
+ private void validateFile(IFile file) {
+ String ext = file.getFileExtension();
+ String content = null;
+ try {
+ content = FileUtil.readStream(file.getContents());
+ } catch (CoreException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ return;
+ }
+ if(ext.equalsIgnoreCase("xml")) {
+ validateXml(file, content);
+ } else if(ext.equalsIgnoreCase("java")) {
+ validateJava(file);
+ } else {
+ validateText(file);
+ }
+ }
+
+ private void validateXml(IFile file, String content) {
+ Document document = new Document(content);
+ SeamSaxHandler handler = new SeamSaxHandler(file, document);
+ try {
+ SAXParserFactory.newInstance().newSAXParser().parse(file.getContents(), handler);
+ } catch (SAXException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ return;
+ } catch (IOException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ return;
+ } catch (ParserConfigurationException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ return;
+ } catch (CoreException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ }
+
+ return;
+ }
+
+ private void validateJava(IFile file) {
+
+ }
+
+ private void validateText(IFile file) {
+
+ }
+
+ /**
+ * @param offset - offset of string in file
+ * @param length - length of string in file
+ */
+ private void validateString(IFile file, String string, int offset, int length) {
+ if((string.startsWith("#{") || string.startsWith("${")) &&
!validateEl(file, string)) {
+ // Mark
+ System.out.println("Error: " + string);
+ }
+ }
+
+ private boolean validateEl(IFile file, String el) {
+ try {
+ String exp = el;
+ int offset = exp.length()-1;
+ String prefix= SeamELCompletionEngine.getPrefix(el, offset);
+ prefix = (prefix == null ? "" : prefix);
+
+ // TODO ?
+ List<String> suggestions = fEngine.getCompletions(project, file, el, prefix,
offset - prefix.length(), true);
+
+ if (suggestions != null && suggestions.size() > 0) {
+ return true;
+ }
+ } catch (BadLocationException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ } catch (StringIndexOutOfBoundsException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ }
+ return false;
+ }
+
+ public class SeamSaxHandler extends DefaultHandler {
+
+ private IFile source;
+ private Locator locator;
+ private Document document;
+
+ public SeamSaxHandler(IFile source, Document document) {
+ super();
+ this.source = source;
+ this.document = document;
+ }
+
+ private int[] getAttributeRange(int attributeIndex, String attributeValue) {
+ try {
+ int lineOffset = document.getLineOffset(locator.getLineNumber());
+ String line = document.get(lineOffset, locator.getColumnNumber()-1);
+ } catch (BadLocationException e) {
+ throw new RuntimeException(e);
+ }
+ int[] result = new int[2];
+ return result;
+ }
+
+ @Override
+ public void setDocumentLocator(Locator locator) {
+ this.locator = locator;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String name, Attributes
attributes) throws SAXException {
+ for(int i=0; i<attributes.getLength(); i++) {
+ String value = attributes.getValue(i);
+ SeamELValidator.this.validateString(source, value, 0, 0);
+ }
+ }
+
+ @Override
+ public void characters (char[] ch, int start, int length) throws SAXException {
+ String value = new String(ch, start, length).trim();
+ SeamELValidator.this.validateString(source, value, start, length);
+ }
+ }
+}
\ No newline at end of file
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidationContext.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidationContext.java 2007-07-20
17:46:54 UTC (rev 2573)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidationContext.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -32,7 +32,9 @@
private Map<String, Set<IPath>> resourcesByVariableName = new
HashMap<String, Set<IPath>>();
private Map<IPath, Set<String>> variableNamesByResource = new
HashMap<IPath, Set<String>>();
private Set<IPath> unnamedResources = new HashSet<IPath>();
+
private Set<IFile> removedFiles = new HashSet<IFile>();
+ private Set<IFile> registeredResources = new HashSet<IFile>();
/**
* Save link between resource and variable name.
@@ -137,6 +139,7 @@
variableNamesByResource.clear();
unnamedResources.clear();
removedFiles.clear();
+ registeredResources.clear();
}
public void store(Element root) {
@@ -192,4 +195,12 @@
public void addRemovedFile(IFile file) {
removedFiles.add(file);
}
+
+ public Set<IFile> getRegisteredFiles() {
+ return registeredResources;
+ }
+
+ public void registerFile(IFile file) {
+ registeredResources.add(file);
+ }
}
\ No newline at end of file
Copied:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidationHelper.java
(from rev 2529,
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamCoreValidationHelper.java)
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidationHelper.java
(rev 0)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidationHelper.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -0,0 +1,268 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
+ * Distributed under license by Red Hat, Inc. All rights reserved.
+ * This program is made available under the terms of the
+ * Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at
http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Exadel, Inc. and Red Hat, Inc. - initial API and implementation
+ ******************************************************************************/
+package org.jboss.tools.seam.internal.core.validation;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.wst.validation.internal.operations.WorkbenchContext;
+import org.jboss.tools.common.model.util.EclipseResourceUtil;
+import org.jboss.tools.seam.core.ISeamComponent;
+import org.jboss.tools.seam.core.ISeamElement;
+import org.jboss.tools.seam.core.ISeamProject;
+import org.jboss.tools.seam.core.ISeamTextSourceReference;
+import org.jboss.tools.seam.core.SeamCorePlugin;
+import org.jboss.tools.seam.internal.core.AbstractContextVariable;
+import org.jboss.tools.seam.internal.core.SeamComponentDeclaration;
+import org.jboss.tools.seam.internal.core.SeamProject;
+
+/**
+ * Base Helper for Seam Validators.
+ * @author Alexey Kazakov
+ */
+public class SeamValidationHelper extends WorkbenchContext {
+
+ protected SeamValidationContext validationContext;
+
+ /**
+ * @return Seam project
+ */
+ public ISeamProject getSeamProject() {
+ ISeamProject project = null;
+ try {
+ project = SeamCorePlugin.getSeamProject(getProject(), true);
+ } catch (Exception e) {
+ SeamCorePlugin.getDefault().logError("Can't get Seam Project", e);
+ }
+ return project;
+ }
+
+ /**
+ * @param element
+ * @return Resource of seam model element
+ */
+ public IResource getComponentResourceWithName(ISeamElement element) {
+ if(element instanceof ISeamComponent) {
+ Set declarations = ((ISeamComponent)element).getAllDeclarations();
+ for (Object o : declarations) {
+ SeamComponentDeclaration d = (SeamComponentDeclaration)o;
+ if(d.getLocationFor(SeamComponentDeclaration.PATH_OF_NAME)!=null) {
+ return d.getResource();
+ }
+ }
+ }
+ return element.getResource();
+ }
+
+ /**
+ * @param seam model element
+ * @return location of name attribute
+ */
+ public ISeamTextSourceReference getLocationOfName(ISeamElement element) {
+ return getLocationOfAttribute(element, SeamComponentDeclaration.PATH_OF_NAME);
+ }
+
+ /**
+ * @param seam model element
+ * @return location of attribute
+ */
+ public ISeamTextSourceReference getLocationOfAttribute(ISeamElement element, String
attributeName) {
+ ISeamTextSourceReference location = null;
+ if(element instanceof AbstractContextVariable) {
+ location = ((AbstractContextVariable)element).getLocationFor(attributeName);
+ } else if(element instanceof ISeamComponent) {
+ Set declarations = ((ISeamComponent)element).getAllDeclarations();
+ for (Object d : declarations) {
+ location = ((SeamComponentDeclaration)d).getLocationFor(attributeName);
+ if(location!=null) {
+ break;
+ }
+ }
+ } else if(element instanceof SeamComponentDeclaration) {
+ location = ((SeamComponentDeclaration)element).getLocationFor(attributeName);
+ }
+ if(location==null && element instanceof ISeamTextSourceReference) {
+ location = (ISeamTextSourceReference)element;
+ }
+ return location;
+ }
+
+ /**
+ * @param resource
+ * @return true if resource is Jar file
+ */
+ public boolean isJar(IResource resource) {
+ String ext = resource.getFileExtension();
+ return ext!=null && ext.equalsIgnoreCase("jar");
+ }
+
+ /**
+ * @param element
+ * @return true if seam element packed in Jar file
+ */
+ public boolean isJar(ISeamElement element) {
+ return isJar(element.getResource());
+ }
+
+ /**
+ * @param componentXmlFile
+ * @return IType of component for <ComponentName>.component.xml
+ */
+ public IType getClassTypeForComponentXml(IFile componentXmlFile) {
+ String className = getClassNameForComponentXml(componentXmlFile);
+ if(className==null) {
+ return null;
+ }
+ return findType(className);
+ }
+
+ /**
+ * @param type name
+ * @return IType
+ */
+ public IType findType(String fullyQualifiedName) {
+ IProject p = getProject().getProject();
+ try {
+ IJavaProject jp = EclipseResourceUtil.getJavaProject(p);
+ return jp.findType(fullyQualifiedName);
+ } catch (JavaModelException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ return null;
+ }
+ }
+
+ /**
+ * @param componentXmlFile
+ * @return name of component class for <ComponentName>.component.xml
+ */
+ public String getClassNameForComponentXml(IFile componentXmlFile) {
+ String fileName = componentXmlFile.getName();
+ int firstDot = fileName.indexOf('.');
+ if(firstDot==-1) {
+ return null;
+ }
+ String className = fileName.substring(0, firstDot);
+ IProject p = getProject().getProject();
+ try {
+ IJavaProject jp = EclipseResourceUtil.getJavaProject(p);
+ IPackageFragment packageFragment =
jp.findPackageFragment(componentXmlFile.getFullPath().removeLastSegments(1));
+ if(packageFragment==null) {
+ return null;
+ }
+ return packageFragment.getElementName() + "." + className;
+ } catch (JavaModelException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ return null;
+ }
+ }
+
+ /**
+ * Find setter for property
+ * @param type
+ * @param propertyName
+ * @return
+ */
+ public IMethod findSetter(IType type, String propertyName) {
+ if(propertyName == null || propertyName.length()==0) {
+ return null;
+ }
+ String firstLetter = propertyName.substring(0, 1).toUpperCase();
+ String nameWithoutFirstLetter = propertyName.substring(1);
+ String setterName = "set" + firstLetter + nameWithoutFirstLetter;
+ try {
+ return findSetterInHierarchy(type, setterName);
+ } catch (JavaModelException e) {
+ SeamCorePlugin.getDefault().logError(e);
+ }
+ return null;
+ }
+
+ private IMethod findSetterInHierarchy(IType type, String setterName) throws
JavaModelException {
+ IMethod[] methods = type.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ if(methods[i].getElementName().equals(setterName) &&
methods[i].getParameterNames().length==1) {
+ return methods[i];
+ }
+ }
+ String superclassName = type.getSuperclassName();
+ if(superclassName!=null) {
+ String[][] packages = type.resolveType(superclassName);
+ if(packages!=null) {
+ for (int i = 0; i < packages.length; i++) {
+ String packageName = packages[i][0];
+ if(packageName!=null && packageName.length()>0) {
+ packageName = packageName + ".";
+ } else {
+ packageName = "";
+ }
+ String qName = packageName + packages[i][1];
+ IType superclass = type.getJavaProject().findType(qName);
+ if(superclass!=null) {
+ IMethod method = findSetterInHierarchy(superclass, setterName);
+ if(method!=null) {
+ return method;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
org.eclipse.wst.validation.internal.operations.WorkbenchContext#registerResource(org.eclipse.core.resources.IResource)
+ */
+ @Override
+ public void registerResource(IResource resource) {
+ if(resource instanceof IFile) {
+ IFile file = (IFile)resource;
+ if(!file.exists()) {
+ getValidationContext().addRemovedFile(file);
+ } else {
+ getValidationContext().registerFile(file);
+ }
+ }
+ }
+
+ /**
+ * @return Set of changed resources
+ */
+ public Set<IFile> getChangedFiles() {
+ Set<IFile> result = new HashSet<IFile>();
+ String[] uris = getURIs();
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ for (int i = 0; i < uris.length; i++) {
+ IFile currentFile = root.getFile(new Path(uris[i]));
+ result.add(currentFile);
+ }
+ result.addAll(getValidationContext().getRemovedFiles());
+ return result;
+ }
+
+ public SeamValidationContext getValidationContext() {
+ if(validationContext==null) {
+ validationContext = ((SeamProject)getSeamProject()).getValidationContext();
+ }
+ return validationContext;
+ }
+}
\ No newline at end of file
Modified:
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidator.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidator.java 2007-07-20
17:46:54 UTC (rev 2573)
+++
trunk/seam/plugins/org.jboss.tools.seam.core/src/org/jboss/tools/seam/internal/core/validation/SeamValidator.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -12,9 +12,10 @@
import java.util.Set;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.wst.validation.internal.core.Message;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
@@ -24,6 +25,7 @@
import org.jboss.tools.seam.core.ISeamProject;
import org.jboss.tools.seam.core.ISeamTextSourceReference;
import org.jboss.tools.seam.core.SeamPreferences;
+import org.jboss.tools.seam.internal.core.SeamProject;
/**
* Basic seam validator.
@@ -50,8 +52,9 @@
protected static final String UNKNOWN_COMPONENT_CLASS_NAME_MESSAGE_ID =
"UNKNOWN_COMPONENT_CLASS_NAME";
protected static final String UNKNOWN_COMPONENT_PROPERTY_MESSAGE_ID =
"UNKNOWN_COMPONENT_PROPERTY";
- protected SeamCoreValidationHelper coreHelper;
+ protected SeamValidationHelper coreHelper;
protected IReporter reporter;
+ protected SeamValidationContext validationContext;
protected ISeamProject project;
@@ -59,13 +62,47 @@
super();
}
+ /* (non-Javadoc)
+ * @see
org.eclipse.wst.validation.internal.provisional.core.IValidatorJob#getSchedulingRule(org.eclipse.wst.validation.internal.provisional.core.IValidationContext)
+ */
+ public ISchedulingRule getSchedulingRule(IValidationContext helper) {
+ return null;
+ }
+
public IStatus validateInJob(IValidationContext helper, IReporter reporter) throws
ValidationException {
- this.coreHelper = (SeamCoreValidationHelper)helper;
+ this.coreHelper = (SeamValidationHelper)helper;
this.reporter = reporter;
this.project = coreHelper.getSeamProject();
- return OK_STATUS;
+ IStatus status = null;
+ try {
+ this.validationContext = ((SeamProject)project).getValidationContext();
+ Set<IFile> changedFiles = coreHelper.getChangedFiles();
+ if(changedFiles.size()>0) {
+ status = validate(changedFiles);
+ } else {
+ status = validateAll();
+ }
+ } finally {
+ validationContext.getRemovedFiles().clear();
+ validationContext.getRegisteredFiles().clear();
+ }
+ return status;
}
+ /**
+ * Incremental Validation
+ * @return
+ * @throws ValidationException
+ */
+ abstract public IStatus validate(Set<IFile> changedFiles) throws
ValidationException;
+
+ /**
+ * Full Validation
+ * @return
+ * @throws ValidationException
+ */
+ abstract public IStatus validateAll() throws ValidationException;
+
public void cleanup(IReporter reporter) {
reporter = null;
}
Deleted:
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELCompletionEngine.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELCompletionEngine.java 2007-07-20
17:46:54 UTC (rev 2573)
+++
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELCompletionEngine.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -1,764 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Red Hat, Inc.
- * Distributed under license by Red Hat, Inc. All rights reserved.
- * This program is made available under the terms of the
- * Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at
http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributor:
- * Red Hat, Inc. - initial API and implementation
- ******************************************************************************/
-package org.jboss.tools.seam.ui.text.java;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.jdt.core.IMember;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.jface.text.rules.IToken;
-import org.jboss.tools.common.model.util.EclipseJavaUtil;
-import org.jboss.tools.seam.core.ISeamComponent;
-import org.jboss.tools.seam.core.ISeamContextVariable;
-import org.jboss.tools.seam.core.ISeamProject;
-import org.jboss.tools.seam.core.ScopeType;
-import org.jboss.tools.seam.ui.SeamGuiPlugin;
-
-/**
- * Utility class used to find Seam Project content assist proposals
- *
- * @author Jeremy
- */
-public final class SeamELCompletionEngine {
-
- /**
- * Constructs SeamELCompletionEngine object
- */
- public SeamELCompletionEngine() {
-
- }
-
- /**
- * Create the array of suggestions.
- *
- * @param project Seam project
- * @param file File
- * @param document
- * @param prefix the prefix to search for
- * @param position Offset of the prefix
- * @return the list of all possible suggestions
- * @throws BadLocationException if accessing the current document fails
- */
- public List<String> getCompletions(ISeamProject project, IFile file, IDocument
document, CharSequence prefix,
- int position) throws BadLocationException {
-
- List<String> res= new ArrayList<String>();
- SeamELTokenizer tokenizer = new SeamELTokenizer(document, position + prefix.length());
- List<ELToken> tokens = tokenizer.getTokens();
-
- List<ELToken> resolvedExpressionPart = new ArrayList<ELToken>();
- List<ISeamContextVariable> resolvedVariables = new
ArrayList<ISeamContextVariable>();
- ScopeType scope = getScope(project, file);
- List<List<ELToken>> variations = getPossibleVarsFromPrefix(tokens);
-
- if (variations.isEmpty()) {
- resolvedVariables = resolveVariables(project, scope, tokens, tokens);
- } else {
- for (List<ELToken> variation : variations) {
- List<ISeamContextVariable>resolvedVars = new
ArrayList<ISeamContextVariable>();
- resolvedVars = resolveVariables(project, scope, variation, tokens);
- if (resolvedVars != null && !resolvedVars.isEmpty()) {
- resolvedVariables = resolvedVars;
- resolvedExpressionPart = variation;
- break;
- }
- }
- }
-
- // Here we have a list of vars for some part of expression
- // OK. we'll proceed with members of these vars
- if (areEqualExpressions(resolvedExpressionPart, tokens)) {
- // First segment is the last one
- for (ISeamContextVariable var : resolvedVariables) {
- res.add(var.getName().substring(prefix.toString().length()));
- }
- return res;
- }
-
- // First segment is found - proceed with next tokens
- int startTokenIndex = (resolvedExpressionPart == null ? 0 :
resolvedExpressionPart.size());
- Set<IMember> members = new HashSet<IMember>();
- for (ISeamContextVariable var : resolvedVariables) {
- IMember member = SeamExpressionResolver.getMemberByVariable(var);
- if (member != null && !members.contains(member))
- members.add(member);
- }
- for (int i = startTokenIndex;
- tokens != null && i < tokens.size() &&
- members != null && members.size() > 0;
- i++) {
- ELToken token = tokens.get(i);
-
- if (i < tokens.size() - 1) { // inside expression
- if (token.getType() == ELToken.EL_SEPARATOR_TOKEN)
- // proceed with next token
- continue;
-
- if (token.getType() == ELToken.EL_NAME_TOKEN) {
- // Find properties for the token
- String name = token.getText();
- Set<IMember> newMembers = new HashSet<IMember>();
- for (IMember mbr : members) {
- try {
- IType type = (mbr instanceof IType ? (IType)mbr :
EclipseJavaUtil.findType(mbr.getJavaProject(),
EclipseJavaUtil.getMemberTypeAsString(mbr)));
- Set<IMember> properties = SeamExpressionResolver.getProperties(type);
- for (IMember property : properties) {
- StringBuffer propertyName = new StringBuffer(property.getElementName());
- if (property instanceof IMethod) { // Setter or getter
- propertyName.delete(0, 3);
- propertyName.setCharAt(0, Character.toLowerCase(propertyName.charAt(0)));
- }
- if (name.equals(propertyName.toString())) {
- newMembers.add(property);
- }
- }
- } catch (JavaModelException ex) {
- SeamGuiPlugin.getPluginLog().logError(ex);
- }
- }
- members = newMembers;
- }
- if (token.getType() == ELToken.EL_METHOD_TOKEN) {
- // Find methods for the token
- String name = token.getText();
- if (name.indexOf('(') != -1) {
- name = name.substring(0, name.indexOf('('));
- }
- Set<IMember> newMembers = new HashSet<IMember>();
- for (IMember mbr : members) {
- try {
- IType type = (mbr instanceof IType ? (IType)mbr :
EclipseJavaUtil.findType(mbr.getJavaProject(),
EclipseJavaUtil.getMemberTypeAsString(mbr)));
- Set<IMember> methods = SeamExpressionResolver.getMethods(type);
- for (IMember method : methods) {
- if (name.equals(method.getElementName())) {
- newMembers.add(method);
- }
- }
- } catch (JavaModelException ex) {
- SeamGuiPlugin.getPluginLog().logError(ex);
- }
- }
- members = newMembers;
- }
- } else { // Last segment
- Set<String> proposals = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
- if (token.getType() == ELToken.EL_SEPARATOR_TOKEN) {
- // return all the methods + properties
- for (IMember mbr : members) {
- try {
- IType type = (mbr instanceof IType ? (IType)mbr :
EclipseJavaUtil.findType(mbr.getJavaProject(),
EclipseJavaUtil.getMemberTypeAsString(mbr)));
- proposals.addAll(SeamExpressionResolver.getMethodPresentations(type));
- proposals.addAll(SeamExpressionResolver.getPropertyPresentations(type));
- } catch (JavaModelException ex) {
- SeamGuiPlugin.getPluginLog().logError(ex);
- }
- }
- } else if (token.getType() == ELToken.EL_NAME_TOKEN ||
- token.getType() == ELToken.EL_METHOD_TOKEN) {
- // return filtered methods + properties
- Set<String> proposalsToFilter = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
- for (IMember mbr : members) {
- try {
- IType type = null;
- if(mbr instanceof IType) {
- type = (IType)mbr;
- } else {
- type = EclipseJavaUtil.findType(mbr.getJavaProject(),
EclipseJavaUtil.getMemberTypeAsString(mbr));
- }
- proposalsToFilter.addAll(SeamExpressionResolver.getMethodPresentations(type));
- proposalsToFilter.addAll(SeamExpressionResolver.getPropertyPresentations(type));
- } catch (JavaModelException ex) {
- SeamGuiPlugin.getPluginLog().logError(ex);
- }
- }
- for (String proposal : proposalsToFilter) {
- // We do expect nothing but name for method tokens (No round brackets)
- String filter = token.getText();
- if (proposal.startsWith(filter)) {
- proposals.add(proposal.substring(filter.length()));
- }
- }
- }
- res.addAll(proposals);
- }
- }
-
- return res;
- }
-
- private String computeVariableName(List<ELToken> tokens){
- if (tokens == null)
- tokens = new ArrayList<ELToken>();
- StringBuffer sb = new StringBuffer();
- for (ELToken token : tokens) {
- if (token.getType() == ELToken.EL_NAME_TOKEN ||
- token.getType() == ELToken.EL_METHOD_TOKEN ||
- token.getType() == ELToken.EL_SEPARATOR_TOKEN) {
- sb.append(token.getText());
- }
- }
- return sb.toString();
- }
-
- /*
- * Compares to tokenized expressions.
- *
- * @param first
- * @param second
- * @return boolean true if two expressions are equal
- */
- private boolean areEqualExpressions(List<ELToken>first, List<ELToken>second)
{
- if (first == null || second == null)
- return (first == second);
-
- if (first.size() != second.size())
- return false;
-
- for (int i = 0; i < first.size(); i++) {
- if (!first.get(i).equals(second.get(i)))
- return false;
- }
- return true;
- }
-
- /* Returns scope for the resource
- *
- * @param project
- * @param resource
- * @return
- */
- private ScopeType getScope(ISeamProject project, IResource resource) {
- if (project == null || resource == null)
- return null;
-
- Set<ISeamComponent> components =
project.getComponentsByPath(resource.getFullPath());
-
- if (components.size() > 1) // Don't use scope in case of more than one
component
- return null;
- for (ISeamComponent component : components) {
- return component.getScope();
- }
- return null;
- }
-
- /*
- * Tries to resolve variables by part of expression
- *
- * @param project
- * @param scope
- * @param part
- * @param tokens
- * @return
- */
- private List<ISeamContextVariable> resolveVariables(ISeamProject project,
ScopeType scope, List<ELToken>part, List<ELToken> tokens) {
- List<ISeamContextVariable>resolvedVars = new
ArrayList<ISeamContextVariable>();
- String varName = computeVariableName(part);
- if (varName != null) {
- resolvedVars = SeamExpressionResolver.resolveVariables(project, scope, varName);
- }
- if (resolvedVars != null && resolvedVars.size() > 0) {
- List<ISeamContextVariable> newResolvedVars = new
ArrayList<ISeamContextVariable>();
- for (ISeamContextVariable var : resolvedVars) {
- if(!areEqualExpressions(part, tokens)) {
- // Do filter by equals (name)
- // In case of the last pass - do not filter by startsWith(name) instead of equals
- if (varName.equals(var.getName())) {
- newResolvedVars.add(var);
- }
- } else {
- newResolvedVars.add(var);
- }
- }
- return newResolvedVars;
- }
- return new ArrayList<ISeamContextVariable>();
- }
-
- /*
- * Creates and returns list of possible variable name combinations from expression
starting from the longest name
- *
- *
- * @param prefix
- * @return
- */
- private List<List<ELToken>>
getPossibleVarsFromPrefix(List<ELToken>prefix) {
- ArrayList<List<ELToken>> result = new
ArrayList<List<ELToken>>();
- for (int i = 0; prefix != null && i < prefix.size(); i++) {
- ELToken lastToken = prefix.get(i);
- if (lastToken.getType() != ELToken.EL_SEPARATOR_TOKEN) {
- ArrayList<ELToken> prefixPart = new ArrayList<ELToken>();
- for (int j = 0; j <= i; j++) {
- prefixPart.add(prefix.get(j));
- }
- result.add(0, prefixPart);
- }
- }
- return result;
- }
-
- /**
- * Removes duplicates of completion strings
- *
- * @param suggestions a list of suggestions ({@link String}).
- * @return a list of unique completion suggestions.
- */
- public List<String> makeUnique(List<String> suggestions) {
- HashSet<String> present = new HashSet<String>();
- ArrayList<String> unique= new ArrayList<String>();
-
- if (suggestions == null)
- return unique;
-
- for (String item : suggestions) {
- if (!present.contains(item)) {
- present.add(item);
- unique.add(item);
- }
- }
-
- present.clear();
- return unique;
- }
-
- /**
- * EL string parser.
- * Creates list of tokens for the name, method and separator parts
- *
- * @author Jeremy
- */
- public static class SeamELTokenizer {
- static final int STATE_INITIAL = 0;
- static final int STATE_VAR = 1;
- static final int STATE_METHOD = 2;
- static final int STATE_SEPARATOR = 3;
-
- IDocument fDocument;
- List<ELToken> fTokens;
- int index;
-
- /**
- * Constructs SeamELTokenizer object
- *
- * @param document
- * @param offset
- */
- public SeamELTokenizer(IDocument document, int offset) {
- fDocument = document;
- index = (fDocument == null || fDocument.getLength() < offset? -1 : offset);
- fTokens = new ArrayList<ELToken>();
- parseBackward();
- }
-
- /**
- * Returns list of tokens for the expression parsed
- *
- * @return
- */
- public List<ELToken> getTokens() {
- return fTokens;
- }
-
- /*
- * Performs backward parsing of document text for expression
- */
- private void parseBackward() {
- ELToken token;
- fState = STATE_INITIAL;
- while ((token = getNextToken()) != ELToken.EOF) {
-
- if (token.type == ELToken.EL_NAME_TOKEN ||
- token.type == ELToken.EL_METHOD_TOKEN ||
- token.type == ELToken.EL_SEPARATOR_TOKEN) {
-
- fTokens.add(0, token);
- }
- }
- }
-
- int fState;
- int fEndOfToken;
-
- /*
- * Calculates and returns next token for expression
- *
- * @return
- */
- private ELToken getNextToken() {
- switch (fState) {
- case STATE_INITIAL: // Just started
- {
- int ch = readCharBackward();
- if (ch == -1) {
- return ELToken.EOF;
- }
- if (Character.isJavaIdentifierPart((char)ch)) {
- releaseChar();
- return readVarToken();
- }
- if (ch == '.') {
- releaseChar();
- return readSeparatorToken();
- }
- if (ch == ')') {
- releaseChar();
- return readMethodToken();
- }
- return ELToken.EOF;
- }
- case STATE_VAR: // Variable name is read - expecting a separator
- {
- int ch = readCharBackward();
- if (ch == -1) {
- return ELToken.EOF;
- }
- if (ch == '.') {
- releaseChar();
- return readSeparatorToken();
- }
- return ELToken.EOF;
- }
- case STATE_METHOD: // Method name and parameters are read - expecting a separator
- {
- int ch = readCharBackward();
- if (ch == -1) {
- return ELToken.EOF;
- }
- if (ch == '.') {
- releaseChar();
- return readSeparatorToken();
- }
- return ELToken.EOF;
- }
- case STATE_SEPARATOR: // Separator is read - expecting a var or method
- {
- int ch = readCharBackward();
- if (ch == -1) {
- return ELToken.EOF;
- }
- if (Character.isJavaIdentifierPart((char)ch)) {
- releaseChar();
- return readVarToken();
- }
- if (ch == ')') {
- releaseChar();
- return readMethodToken();
- }
- return ELToken.EOF;
- }
- }
- return ELToken.EOF;
- }
-
- /* Reads and returns the method token from the expression
- *
- * @return
- */
- ELToken readMethodToken() {
- fState = STATE_METHOD;
- int endOfToken = index;
-
- // read the method parameters
- if (!skipMethodParameters())
- return ELToken.EOF;
-
- // skip spaces between the method's name and it's parameters
- if (!skipSpaceChars())
- return ELToken.EOF;
- // read the method name
- if (!skipMethodName())
- return ELToken.EOF;
-
- return (endOfToken - index > 0 ? new ELToken(index, endOfToken - index,
getCharSequence(index, endOfToken - index), ELToken.EL_METHOD_TOKEN) : ELToken.EOF);
- }
-
- /*
- * Returns the CharSequence object
- *
- * @param start
- * @param length
- * @return
- */
- private CharSequence getCharSequence(int start, int length) {
- String text = "";
- try {
- text = fDocument.get(start, length);
- } catch (BadLocationException e) {
- text = ""; // For sure
- }
- return text.subSequence(0, text.length());
- }
-
-
- /*
- * Skips the space characters in the document
- */
- boolean skipSpaceChars() {
- int ch;
- while ((ch = readCharBackward()) != -1) {
- if (!Character.isSpaceChar(ch)) {
- releaseChar();
- break;
- }
- }
- return true;
- }
-
- /*
- * Skips the method name characters in the document
- *
- * @return boolean true if at least 1 character had been read
- */
- boolean skipMethodName() {
- int endOfToken = index;
- int ch;
- while((ch = readCharBackward()) != -1) {
- if (!Character.isJavaIdentifierPart(ch)) {
- releaseChar();
- return (endOfToken - index > 0);
- }
- }
- return false;
- }
-
- /*
- * Skips the method parameters characters in the document
- *
- * @return boolean true if complete parameters set had been read
- */
- boolean skipMethodParameters() {
- int ch = readCharBackward();
- if (ch != ')')
- return false;
- int pCount = 1;
- while (pCount > 0) {
- ch = readCharBackward();
- if (ch == -1)
- return false;
-
- if (ch == '"' || ch == '\'') {
- skipQuotedChars((char)ch);
- continue;
- }
- if (ch == ')') {
- pCount++;
- continue;
- }
- if (ch == '(') {
- pCount--;
- continue;
- }
- }
- return true;
- }
-
- /*
- * Skips the quoted characters
- *
- */
- void skipQuotedChars(char pair) {
- int ch = readCharBackward();
-
- while (ch != -1) {
- if (ch == pair) {
- ch = readCharBackward();
- if (ch == '\\') {
- int backSlashCount = 0;
- while (ch == '\\') {
- backSlashCount++;
- ch = readCharBackward();
- }
- releaseChar(); // Return the last non-slash char to the buffer
- if ((backSlashCount/2)*2 == backSlashCount) {
- return;
- }
- }
- }
- ch = readCharBackward();
- }
- }
-
- /* Reads and returns the separator token from the expression
- *
- * @return
- */
- ELToken readSeparatorToken() {
- fState = STATE_SEPARATOR;
- int ch = readCharBackward();
-
- return (ch == '.' ? new ELToken(index, 1, getCharSequence(index, 1),
ELToken.EL_SEPARATOR_TOKEN) :
- ELToken.EOF);
- }
-
- /* Reads and returns the variable token from the expression
- *
- * @return
- */
- ELToken readVarToken() {
- fState = STATE_VAR;
- int endOfToken = index;
- int ch;
- while((ch = readCharBackward()) != -1) {
- if (!Character.isJavaIdentifierPart(ch)) {
- releaseChar();
- return (endOfToken - index > 0 ? new ELToken(index, endOfToken - index,
getCharSequence(index, endOfToken - index), ELToken.EL_NAME_TOKEN) : ELToken.EOF);
- }
- }
- releaseChar();
- return (endOfToken - index > 0 ? new ELToken(index, endOfToken - index,
getCharSequence(index, endOfToken - index), ELToken.EL_NAME_TOKEN) : ELToken.EOF);
- }
-
- /* Reads the next character in the document
- *
- * @return
- */
- int readCharBackward() {
- if (--index < 0 ||
- fDocument == null ||
- fDocument.getLength() <= index)
- return -1;
-
- try {
- return fDocument.getChar(index);
- } catch (BadLocationException e) {
- return -1;
- }
- }
-
- /*
- * returns the character to the document
- */
- void releaseChar() {
- if (index < fDocument.getLength())
- index++;
- }
- }
-
- /**
- * Calculates the EX expression operand string
- *
- * @param viewer
- * @param offset
- * @return
- * @throws BadLocationException
- */
- public static String getPrefix(ITextViewer viewer, int offset) throws
BadLocationException {
- IDocument doc= viewer.getDocument();
- if (doc == null || offset > doc.getLength())
- return null;
-
- SeamELTokenizer tokenizer = new SeamELTokenizer(doc, offset);
- List<ELToken> tokens = tokenizer.getTokens();
-
- if (tokens == null || tokens.size() == 0)
- return null;
-
- return doc.get(tokens.get(0).start, offset - tokens.get(0).start);
- }
-}
-
-/**
- * Token for the EX expression
- *
- * @author Jeremy
- */
-class ELToken implements IToken {
- static final ELToken EOF = new ELToken(-1, -1, null, -1);
- static final int EL_NAME_TOKEN = 1;
- static final int EL_METHOD_TOKEN = 2;
- static final int EL_SEPARATOR_TOKEN = 3;
-
- int start;
- int length;
- CharSequence chars;
- int type;
-
- /**
- * Constructs the ELToken object
- *
- * @param start
- * @param length
- * @param chars
- * @param type
- */
- public ELToken(int start, int length, CharSequence chars, int type) {
- this.start = start;
- this.length = length;
- this.chars = chars;
- this.type = type;
- }
-
- /**
- * Returns string representation for the token
- */
- public String toString() {
- return "ELToken(" + start + ", " + length + ", " + type +
") [" + (chars == null ? "<Empty>" : chars.toString()) +
"]";
- }
-
- /*
- * @see org.eclipse.jface.text.rules.IToken#getData()
- */
- public Object getData() {
- return (chars == null ? null : chars.subSequence(start, start+length).toString());
- }
-
- /*
- * @see org.eclipse.jface.text.rules.IToken#isEOF()
- */
- public boolean isEOF() {
- return (start == -1 && length == -1 && chars == null);
- }
-
- /*
- * @see org.eclipse.jface.text.rules.IToken#isOther()
- */
- public boolean isOther() {
- return false;
- }
-
- /*
- * @see org.eclipse.jface.text.rules.IToken#isUndefined()
- */
- public boolean isUndefined() {
- return false;
- }
-
- /*
- * @see org.eclipse.jface.text.rules.IToken#isWhitespace()
- */
- public boolean isWhitespace() {
- return false;
- }
-
- /*
- * Returns the token type
- */
- public int getType(){
- return type;
- }
-
- /*
- * Returns the token text
- */
- public String getText() {
- return chars.toString();
- }
-}
Modified:
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalComputer.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalComputer.java 2007-07-20
17:46:54 UTC (rev 2573)
+++
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalComputer.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -67,4 +67,4 @@
*/
public void sessionEnded() {
}
-}
+}
\ No newline at end of file
Modified:
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalProcessor.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalProcessor.java 2007-07-20
17:46:54 UTC (rev 2573)
+++
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamELProposalProcessor.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -45,6 +45,7 @@
import org.jboss.tools.common.text.ext.IEditorWrapper;
import org.jboss.tools.seam.core.ISeamProject;
import org.jboss.tools.seam.core.SeamCorePlugin;
+import org.jboss.tools.seam.internal.core.el.SeamELCompletionEngine;
import org.jboss.tools.seam.ui.SeamGuiPlugin;
/**
@@ -254,6 +255,8 @@
return (ICompletionProposal[]) result.toArray(new
ICompletionProposal[uniqueSuggestions.size()]);
} catch (BadLocationException x) {
return NO_PROPOSALS;
+ } catch (StringIndexOutOfBoundsException e) {
+ return NO_PROPOSALS;
}
}
Deleted:
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamExpressionResolver.java
===================================================================
---
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamExpressionResolver.java 2007-07-20
17:46:54 UTC (rev 2573)
+++
trunk/seam/plugins/org.jboss.tools.seam.ui/src/org/jboss/tools/seam/ui/text/java/SeamExpressionResolver.java 2007-07-20
18:43:09 UTC (rev 2574)
@@ -1,284 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007 Red Hat, Inc.
- * Distributed under license by Red Hat, Inc. All rights reserved.
- * This program is made available under the terms of the
- * Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at
http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributor:
- * Red Hat, Inc. - initial API and implementation
- ******************************************************************************/
-
-package org.jboss.tools.seam.ui.text.java;
-
-import java.lang.reflect.Modifier;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.eclipse.jdt.core.IField;
-import org.eclipse.jdt.core.IMember;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.jboss.tools.seam.core.IBijectedAttribute;
-import org.jboss.tools.seam.core.ISeamComponent;
-import org.jboss.tools.seam.core.ISeamContextVariable;
-import org.jboss.tools.seam.core.ISeamElement;
-import org.jboss.tools.seam.core.ISeamJavaComponentDeclaration;
-import org.jboss.tools.seam.core.ISeamJavaSourceReference;
-import org.jboss.tools.seam.core.ISeamProject;
-import org.jboss.tools.seam.core.ISeamXmlFactory;
-import org.jboss.tools.seam.core.ScopeType;
-
-/**
- * Utility class used to resolve Seam project variables and to get the methods/properties
and their presentation strings from type
- *
- * @author Jeremy
- */
-public class SeamExpressionResolver {
-
- /**
- * Returns Seam project variables which names start from specified value
- *
- * @param project
- * @param scope
- * @param name
- * @return
- */
- public static List<ISeamContextVariable> resolveVariables(ISeamProject project,
ScopeType scope, String name) {
- if (project == null || name == null) return null;
- return (scope == null ? internalResolveVariables(project, name) :
- internalResolveVariablesByScope(project, scope, name));
- }
-
- /**
- * Returns Seam project variables which names start from specified value
- * No scope used
- *
- * @param project
- * @param name
- * @return
- */
- private static List<ISeamContextVariable> internalResolveVariables(ISeamProject
project, String name) {
- List<ISeamContextVariable> resolvedVariables = new
ArrayList<ISeamContextVariable>();
- Set<ISeamContextVariable> variables = project.getVariables();
- for (ISeamContextVariable variable : variables) {
- if (variable.getName().startsWith(name)) {
- resolvedVariables.add(variable);
- }
- }
- return resolvedVariables;
- }
-
- /**
- * Returns Seam project variables which names start from specified value
- * Search is performed using scope
- *
- * @param project
- * @param scope
- * @param name
- * @return
- */
- private static List<ISeamContextVariable>
internalResolveVariablesByScope(ISeamProject project, ScopeType scope, String name) {
- List<ISeamContextVariable> resolvedVariables = new
ArrayList<ISeamContextVariable>();
- Set<ISeamContextVariable> variables = project.getVariablesByScope(scope);
- for (ISeamContextVariable variable : variables) {
- if (variable.getName().startsWith(name)) {
- resolvedVariables.add(variable);
- }
- }
- return resolvedVariables;
- }
-
- /**
- * Returns the IMember for the variable specified
- *
- * @param variable
- * @return
- */
- public static IMember getMemberByVariable(ISeamContextVariable variable) {
- IMember member = null;
- if (variable instanceof ISeamComponent) {
- ISeamComponent component = (ISeamComponent)variable;
- ISeamJavaComponentDeclaration decl = component.getJavaDeclaration();
- if (decl != null) {
- member = decl.getSourceMember();
- }
- }
- if (member == null && variable instanceof IBijectedAttribute) {
- member = ((ISeamJavaSourceReference)variable).getSourceMember();
- }
- if (member == null && variable instanceof ISeamJavaSourceReference) {
- member = ((ISeamJavaSourceReference)variable).getSourceMember();
- }
- if (member == null && variable instanceof ISeamXmlFactory) {
- ISeamXmlFactory factory = (ISeamXmlFactory)variable;
- String value = factory.getValue();
- if (value != null && value.length() > 0) {
- if (value.startsWith("#{") || value.startsWith("${"))
- value = value.substring(2);
- if (value.endsWith("}"))
- value = value.substring(0, value.length() - 1);
- }
- if (value != null && value.length() > 0) {
- // TODO: Need to make sure that it's correct way to get the project and
- // the scope from the factory
- ISeamProject project = ((ISeamElement)factory).getSeamProject();
-// ISeamProject project = getSeamProject(factory.getResource());
- if (project != null) {
- List<ISeamContextVariable> resolvedValues = resolveVariables(project,
factory.getScope(), value);
- for (ISeamContextVariable var : resolvedValues) {
- if (var.getName().equals(value)) {
- member = getMemberByVariable(var);
- break;
- }
- }
- }
- }
- }
- return member;
- }
-
- /**
- * Returns the methods for the type specified
- *
- * @param type
- * @return
- */
- public static Set<IMember> getMethods(IType type) {
- Set<IMember> methods = new HashSet<IMember>();
- if (type != null) {
- try {
- IMethod[] mthds = type.getMethods();
- for (int i = 0; mthds != null && i < mthds.length; i++) {
- IMethod m = mthds[i];
- if (Modifier.isPublic(m.getFlags()) &&
- (!m.getElementName().startsWith("get") &&
!m.getElementName().startsWith("set")) ||
- "get".equals(m.getElementName()) ||
"set".equals(m.getElementName())) {
- methods.add(m);
- }
- }
- } catch (JavaModelException e) {
- }
- }
- return methods;
- }
-
- /**
- * Returns the method presentation strings for the type specified
- *
- * @param type
- * @return
- */
- public static Set<String> getMethodPresentations(IType type) {
- Set<String> methods = new HashSet<String>();
- if (type != null) {
- try {
- IMethod[] mthds = type.getMethods();
- for (int i = 0; mthds != null && i < mthds.length; i++) {
- IMethod m = mthds[i];
- if (Modifier.isPublic(m.getFlags()) &&
- (!m.getElementName().startsWith("get") &&
!m.getElementName().startsWith("set")) ||
- "get".equals(m.getElementName()) ||
"set".equals(m.getElementName())) {
-
- StringBuffer name = new StringBuffer(m.getElementName());
-
- name.append('(');
- String[] mParams = null;
- mParams = m.getParameterNames();
- for (int j = 0; mParams != null && j < mParams.length; j++) {
- if (j > 0) name.append(", ");
- name.append(mParams[j]);
- }
- name.append(')');
-
- methods.add(name.toString());
- }
- }
- } catch (JavaModelException e) {
- }
- }
- return methods;
- }
-
- /**
- * Returns the properties for the type specified
- *
- * @param type
- * @return
- */
- public static Set<IMember> getProperties(IType type) {
- Set<IMember> properties = new HashSet<IMember>();
- if (type != null) {
- try {
- IMethod[] props = type.getMethods();
- for (int i = 0; props != null && i < props.length; i++) {
- IMethod m = props[i];
- if (Modifier.isPublic(m.getFlags()) &&
- (m.getElementName().startsWith("get") &&
!"get".equals(m.getElementName())) ||
- (m.getElementName().startsWith("set") &&
!"set".equals(m.getElementName()))) {
- properties.add(m);
- }
- }
- } catch (JavaModelException e) {
- }
-
- try {
- IField[] fields = type.getFields();
- for (int i = 0; fields != null && i < fields.length; i++) {
- IField f = fields[i];
- if (Modifier.isPublic(f.getFlags())) {
- properties.add(f);
- }
- }
- } catch (JavaModelException e) {
- }
- }
- return properties;
- }
-
- /**
- * Returns the property presentation strings for the type specified
- *
- * @param type
- * @return
- */
- public static Set<String> getPropertyPresentations(IType type) {
- Set<String> properties = new
TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
- if (type != null) {
- try {
- IMethod[] props = type.getMethods();
- for (int i = 0; props != null && i < props.length; i++) {
- IMethod m = props[i];
- if (Modifier.isPublic(m.getFlags()) &&
- (m.getElementName().startsWith("get") &&
!"get".equals(m.getElementName())) ||
- (m.getElementName().startsWith("set") &&
!"set".equals(m.getElementName()))) {
-
- StringBuffer name = new StringBuffer(m.getElementName());
- name.delete(0, 3);
- name.setCharAt(0, Character.toLowerCase(name.charAt(0)));
-
- properties.add(name.toString());
- }
- }
- } catch (JavaModelException e) {
- }
-
- try {
- IField[] fields = type.getFields();
- for (int i = 0; fields != null && i < fields.length; i++) {
- IField f = fields[i];
- if (Modifier.isPublic(f.getFlags())) {
- properties.add(f.getElementName());
- }
- }
- } catch (JavaModelException e) {
- }
- }
- return properties;
- }
-}