Skip to main content
summaryrefslogtreecommitdiffstats
blob: 58661da4eda0c163f719319d956a39cee1b92d57 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*******************************************************************************
 * 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.operators;

import org.eclipse.core.resources.IProject;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.jst.jsf.common.internal.types.ValueType;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IStructuredDocumentContextResolverFactory;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IWorkspaceContextResolver;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext;
import org.eclipse.jst.jsf.core.jsfappconfig.JSFAppConfigUtils;
import org.eclipse.jst.jsf.validation.internal.el.diagnostics.DiagnosticFactory;
import org.eclipse.jst.jsp.core.internal.java.jspel.JSPELParserConstants;
import org.eclipse.jst.jsp.core.internal.java.jspel.Token;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;

/**
 * Represents an abstract EL binary operator that always
 * takes arguments and produces a single results
 * 
 * @author cbateman
 *
 */
public abstract class BinaryOperator 
{
    /**
     * the factory used to construct diagnostics
     */
    protected final DiagnosticFactory   _diagnosticFactory;
    
    /**
     * @param operatorToken
     * @param diagnosticFactory 
     * @param context -- the current EL document context; must not be null
     * @return a binary operator based on the provided token
     * @throws IllegalArgumentException if the token is not a recognized
     * EL binary operator token or if context is null
     */
    public static BinaryOperator getBinaryOperator(Token operatorToken, DiagnosticFactory diagnosticFactory, IStructuredDocumentContext context)
    {
        if (context == null)
        {
            throw new IllegalArgumentException("Context must not be null"); //$NON-NLS-1$
        }
        final String facetVersion = determineJSFVersion(context);
        
        switch (operatorToken.kind)
        {
            case JSPELParserConstants.AND1:
            case JSPELParserConstants.AND2:
                return new AndBinaryOperator(diagnosticFactory);
                
            case JSPELParserConstants.OR1:
            case JSPELParserConstants.OR2:
                return new OrBinaryOperator(diagnosticFactory);
                
            case JSPELParserConstants.EQ1:
            case JSPELParserConstants.EQ2:
                return new EqualsBinaryRelationalOperator(diagnosticFactory,facetVersion);
                
            case JSPELParserConstants.NEQ1:
            case JSPELParserConstants.NEQ2:
                return new NotEqualsBinaryRelationalOperator(diagnosticFactory,facetVersion);
                
            case JSPELParserConstants.GT1:
            case JSPELParserConstants.GT2:
                return new GreaterThanRelationalBinaryOperator(diagnosticFactory,facetVersion);
                
            case JSPELParserConstants.GE1:
            case JSPELParserConstants.GE2:
                return new GreaterThanEqRelationalBinaryOperator(diagnosticFactory,facetVersion);
                
            case JSPELParserConstants.LT1:
            case JSPELParserConstants.LT2:
                return new LessThanRelationalBinaryOperator(diagnosticFactory,facetVersion);
                
            case JSPELParserConstants.LE1:
            case JSPELParserConstants.LE2:
                return new LessThanEqRelationalBinaryOperator(diagnosticFactory,facetVersion);
                
            case JSPELParserConstants.PLUS:
                return new AddArithmeticBinaryOperator(diagnosticFactory);
                
            case JSPELParserConstants.MINUS:
                return new SubtractArithmeticBinaryOperator(diagnosticFactory);
                
            case JSPELParserConstants.MULTIPLY:
                return new MultiplyArithmeticBinaryOperator(diagnosticFactory);
                
            case JSPELParserConstants.DIVIDE1:
            case JSPELParserConstants.DIVIDE2:
                return new DivArithmeticBinaryOperator(diagnosticFactory);
            
            case JSPELParserConstants.MODULUS1:
            case JSPELParserConstants.MODULUS2:
                return new ModArithmeticBinaryOperator(diagnosticFactory);
        }
        
        throw new IllegalArgumentException("Unknown binary operator: "+operatorToken.image); //$NON-NLS-1$
    }
    
    /**
     * 
     * Constructor
     */
    BinaryOperator(DiagnosticFactory diagnosticFactory) 
    {
        /* no construction or sub-classing outside package*/
        _diagnosticFactory = diagnosticFactory;
    }
    
    /**
     * If both arguments are literals and the operation can be performed, then
     * the return must be a new LiteralType transformed using this operator.
     * 
     * If one or both of the arg is not a literal and the operaton can be performed, then
     * the return is a new ValueType transformed per the rules of the operator
     * 
     * If the operation cannot be performed on ValueType, return null
     * 
     * @param firstArg 
     * @param secondArg 
     * @return a new value type after the operation is performed
     */
    public abstract ValueType performOperation(ValueType firstArg, ValueType secondArg);
    
    
    /**
     * @param firstArg 
     * @param secondArg 
     * @return a Diagnostic interpreting whether it is valid to perform the
     * operation on the two arguments
     */
    public abstract Diagnostic validate(ValueType firstArg, ValueType secondArg);
    
    private static String determineJSFVersion(IStructuredDocumentContext context)
    {
        final IWorkspaceContextResolver wkResolver = 
            IStructuredDocumentContextResolverFactory.
                INSTANCE.getWorkspaceContextResolver(context);
        
        IProject project = wkResolver.getProject();
        
        IProjectFacetVersion  projectVersion = JSFAppConfigUtils.getProjectFacet(project);
        
        if (projectVersion != null)
        {
            return projectVersion.getVersionString();
        }
        
        return null;
    }
}

Back to the top