blob: e831308b115cce3b537b85d2a05e2743f8819d43 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Oracle Corporation.
* All rights reserved. This program and the accompanying materials
* are 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:
* Cameron Bateman/Oracle - initial API and implementation
*
********************************************************************************/
package org.eclipse.jst.jsf.validation.internal.el;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.jst.jsf.common.internal.types.CompositeType;
import org.eclipse.jst.jsf.common.internal.types.SignatureBasedType;
import org.eclipse.jst.jsf.context.structureddocument.internal.provisional.IStructuredDocumentContext;
import org.eclipse.jst.jsf.validation.internal.el.diagnostics.DiagnosticFactory;
import org.eclipse.jst.jsf.validation.internal.el.diagnostics.ValidationMessageFactory;
import org.eclipse.jst.jsp.core.internal.java.jspel.ASTExpression;
import org.eclipse.jst.jsp.core.internal.java.jspel.JSPELParser;
import org.eclipse.jst.jsp.core.internal.java.jspel.ParseException;
import org.eclipse.jst.jsp.core.internal.java.jspel.Token;
import org.eclipse.jst.jsp.core.internal.java.jspel.TokenMgrError;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
import org.eclipse.wst.validation.internal.provisional.core.IValidator;
/**
* Validates a single expression string
*
* @author cbateman
*
*/
public class ELExpressionValidator
{
private final IStructuredDocumentContext _context;
private final String _elText;
private final IFile _file;
private final List _syntaxProblems;
private ASTSemanticValidator _semanticValidator;
/**
* @param context
* @param contentLength
* @param elText
* @param file
*/
public ELExpressionValidator(final IStructuredDocumentContext context,
final String elText,
final IFile file)
{
_context = context;
_elText = elText;
_file = file;
_syntaxProblems = new ArrayList();
}
/**
* Validates a single EL expression in an XML attribute value
* @return an ASTExpression for the node
*/
public ASTExpression validateXMLNode()
{
JSPELParser elParser = JSPELParser.createParser(_elText);
// =
try {
//final long startParsing = System.currentTimeMillis();
final ASTExpression expr = elParser.Expression();
//final long endParsing = System.currentTimeMillis();
//final long startSemantics = System.currentTimeMillis();
validateSemantics(expr, _context);
//final long endSemantics = System.currentTimeMillis();
//System.out.println("Time to parse '"+elText+"' = "+(endParsing-startParsing));
//System.out.println("Time to semantic checking '"+elText+"' = "+(endSemantics-startSemantics));
// if the parser bailed before parsing the whole
// expression, raise a warning that there is probably
// some syntatical issue
if (expr.getLastToken().endColumn < _elText.trim().length()-1)
{
int offset = _context.getDocumentPosition() + expr.getLastToken().endColumn;
int length = _elText.trim().length() - expr.getLastToken().endColumn;
_syntaxProblems.add(
ValidationMessageFactory.createFromDiagnostic(
DiagnosticFactory.create_GENERAL_SYNTAX_ERROR(),
offset, length, _file));
}
return expr;
}
catch (ParseException e) {
Token curTok = e.currentToken;
int offset = _context.getDocumentPosition() + curTok.beginColumn;
int length = curTok.endColumn - curTok.beginColumn + 1;
_syntaxProblems.add(
ValidationMessageFactory.createFromDiagnostic(
DiagnosticFactory.create_GENERAL_SYNTAX_ERROR(),
offset, length, _file));
return null;
}
catch (TokenMgrError te) {
final int offset = _context.getDocumentPosition();
final int length = _elText.length();
_syntaxProblems.add(
ValidationMessageFactory.createFromDiagnostic(
DiagnosticFactory.create_GENERAL_SYNTAX_ERROR(),
offset, length, _file));
return null;
}
}
/**
* Report the results of this EL Expression validation to reportor
* using validator as a source
*
* @param validator
* @param reporter
*/
public void reportFindings(IValidator validator, IReporter reporter)
{
for (final Iterator it = _syntaxProblems.iterator(); it.hasNext();)
{
IMessage message = (IMessage) it.next();
reporter.addMessage(validator, message);
}
if (_semanticValidator != null)
{
_semanticValidator.reportFindings(validator,reporter);
}
}
/**
* @return the type of the expression or null if
* the type could not be evaluated
*/
public CompositeType getExpressionType()
{
if (_semanticValidator != null)
{
final SignatureBasedType type =
_semanticValidator.getExpressionType();
if (type != null)
{
return type.toCompositeType();
}
}
return null;
}
/**
* @return an unmodifiable list containing all the detected syntax errors
* or an empty list if validate has not yet been called.
*/
public List getSyntaxProblems()
{
return Collections.unmodifiableList(_syntaxProblems);
}
/**
* @return the EL semantic validator for this expression validitor or
* null if one has not yet been constructor. One will only be construct
* if validate is called and the expression does not have any syntax errors.
*/
public IExpressionSemanticValidator getSemanticValidator()
{
return _semanticValidator;
}
/**
* Validates the context-specific data for one EL expressino
*
* @param expr
* @param file
* @param reporter
* @param context
*/
private void validateSemantics(ASTExpression expr,IStructuredDocumentContext context)
{
_semanticValidator = new ASTSemanticValidator(expr, context);
_semanticValidator.validate();
}
}