org.eclipse.persistence.sdo.helper.extension.OPStack Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.sdo.helper.extension;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* Utility class used for processing an XPath Expression into postfix
* notation. For example, consider the following expression:
*
* quantity=5 and (specialOrder='false' or productName='Lawnmower')
*
* The operations performed to create a postfix expression are:
* 1) add "quantity" to the list
* 2) push "=" onto the stack
* 3) add "5" to the list
* 4) pop "=" off the stack, and add to the list
* 5) push "and" onto the stack
* 6) push "(" onto the stack
* 7) add "specialOrder" to the list
* 8) push "=" onto the stack
* 9) add "'false'" to the list
* 10) pop "=" off the stack, and add to the list
* 11) push "or" onto the stack
* 12) add "productName" to the list
* 13) push "=" onto the stack
* 14) add "'Lawnmower'" to the list
* 15) pop "=" off the stack, and add to the list
* 16) pop "or" off the stack, and add to the list
* 17) push ")" onto the stack
* 18) pop "(" ")" pair off the stack
* 19) pop "and" off the stack, and add to the list
*
* The resulting postfix expression is:
*
* quantity 5 = specialOrder 'false' = productName 'Lawnmower' = or and
*/
public class OPStack {
/** Visibility reduced from [public] in 2.1.0. May 15 2007 */
private int state;
/** Visibility reduced from [public] in 2.1.0. May 15 2007 */
private Stack stack;
/** Visibility reduced from [public] in 2.1.0. May 15 2007 */
//private String expression;
/** Visibility reduced from [public] in 2.1.0. May 15 2007 */
private ArrayList tokens;
/** Visibility reduced from [public] in 2.1.0. May 15 2007 */
private List out;
/**
* The default constructor initializes the stack and
* Token list.
*/
public OPStack() {
stack = new Stack();
tokens = new ArrayList();
}
/**
* Removes a '(' ')' pair from the stack.
*/
private void removeOCpair() {
stack.pop();
stack.pop();
}
/**
* Removes lower priority tokens from the stack (adding them to the
* List that will be returned), then push the new token onto the
* stack.
*
* @param outList
* @param t
*/
private void pushSpew(List outList, Token t) {
while (!stack.empty() && (((Token)stack.peek()).getPriority() >= t.getPriority())) {
outList.add(stack.pop());
}
stack.push(t);
}
/**
* Returns the next Token in the list.
*
* @return
*/
private Token getNextToken() {
if (tokens.size() > 0) {
Token tok = (Token)tokens.get(0);
tokens.remove(0);
return tok;
}
return null;
}
/**
* Parse an XPath Expression into Token objects.
*
* @param exp
*/
private void parseExpression(String exp) {
StringBuffer sbuf = new StringBuffer();
char ch;
Token tok;
for (int i = 0; i < exp.length(); i++) {
ch = exp.charAt(i);
// 'and' and 'or' should be preceded by whitespace
if (ch == ' ') {
if (((i + 2) < exp.length()) && ((exp.charAt(i + 1) == 'o') && (exp.charAt(i + 2) == 'r'))) {
tok = new Token(sbuf.toString(), Token.ARG);
tokens.add(tok);
sbuf = new StringBuffer();
sbuf.append(exp.charAt(++i));
sbuf.append(exp.charAt(++i));
tok = new Token(sbuf.toString(), Token.DI, Token.OR_PR);
tokens.add(tok);
sbuf = new StringBuffer();
} else if (((i + 3) < exp.length()) && ((exp.charAt(i + 1) == 'a') && (exp.charAt(i + 2) == 'n') && (exp.charAt(i + 3) == 'd'))) {
tok = new Token(sbuf.toString(), Token.ARG);
tokens.add(tok);
sbuf = new StringBuffer();
sbuf.append(exp.charAt(++i));
sbuf.append(exp.charAt(++i));
sbuf.append(exp.charAt(++i));
tok = new Token(sbuf.toString(), Token.DI, Token.AND_PR);
tokens.add(tok);
sbuf = new StringBuffer();
}
} else if (ch == '=') {
tok = new Token(sbuf.toString(), Token.ARG);
tokens.add(tok);
tok = new Token(Character.toString(ch), Token.DI, Token.EQ_PR);
tokens.add(tok);
sbuf = new StringBuffer();
} else if ((ch == '!') && (((i + 1) < exp.length()) && (exp.charAt(i + 1) == '='))) {
tok = new Token(sbuf.toString(), Token.ARG);
tokens.add(tok);
sbuf = new StringBuffer();
sbuf.append(ch);
sbuf.append(exp.charAt(++i));
tok = new Token(sbuf.toString().trim(), Token.DI, Token.NEQ_PR);
tokens.add(tok);
sbuf = new StringBuffer();
} else if (ch == '<') {
tok = new Token(sbuf.toString(), Token.ARG);
tokens.add(tok);
sbuf = new StringBuffer();
sbuf.append(ch);
if (((i + 1) < exp.length()) && (exp.charAt(i + 1) == '=')) {
sbuf.append(exp.charAt(++i));
tok = new Token(sbuf.toString().trim(), Token.DI, Token.LEQ_PR);
} else {
tok = new Token(sbuf.toString().trim(), Token.DI, Token.LT_PR);
}
tokens.add(tok);
sbuf = new StringBuffer();
} else if (ch == '>') {
tok = new Token(sbuf.toString(), Token.ARG);
tokens.add(tok);
sbuf = new StringBuffer();
sbuf.append(ch);
if (((i + 1) < exp.length()) && (exp.charAt(i + 1) == '=')) {
sbuf.append(exp.charAt(++i));
tok = new Token(sbuf.toString().trim(), Token.DI, Token.GEQ_PR);
} else {
tok = new Token(sbuf.toString().trim(), Token.DI, Token.GT_PR);
}
tokens.add(tok);
sbuf = new StringBuffer();
} else if (ch == '(') {
if (sbuf.length() > 0) {
tok = new Token(sbuf.toString(), Token.ARG);
tokens.add(tok);
sbuf = new StringBuffer();
}
tok = new Token(Character.toString(ch), Token.OPEN);
tokens.add(tok);
} else if (ch == ')') {
if (sbuf.length() > 0) {
tok = new Token(sbuf.toString(), Token.ARG);
tokens.add(tok);
sbuf = new StringBuffer();
}
tok = new Token(Character.toString(ch), Token.CLOSE);
tokens.add(tok);
} else {
if (ch != ' ') {
sbuf.append(ch);
}
}
}
if (sbuf.length() > 0) {
tok = new Token(sbuf.toString(), Token.ARG);
tokens.add(tok);
sbuf = new StringBuffer();
}
}
/**
* Process an XPath Expression into postfix notation.
*
* @param exp
* @return
*/
public List processExpression(String exp) {
parseExpression(exp);
out = new ArrayList();
state = 0;
stack.push(Token.OpenExp);// start off with an open of the expression
Token t;
while ((t = getNextToken()) != null) {
switch (t.getType()) {
case Token.ARG:
if (state != 0) {
out.clear();
return out;
}
out.add(t);
state = 1;
break;
case Token.PRE:
if (state != 0) {
out.clear();
return out;
}
stack.push(t);
break;
case Token.OPEN:
stack.push(t);
break;
case Token.DI:
if (state != 1) {
out.clear();
return out;
}
pushSpew(out, t);
state = 0;
break;
case Token.POST:
if (state != 1) {
out.clear();
return out;
}
pushSpew(out, t);
out.add(stack.pop());
break;
case Token.CLOSE:
pushSpew(out, t);
removeOCpair();
}
}
pushSpew(out, Token.CloseExp);
removeOCpair();
if (state != 1) {
out.clear();
}
return out;
}
}