/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
//
/**
* @author Xiping Wang
*
*/
package org.apache.imperius.spl.parser.expressions.impl;
import java.util.List;
import java.util.logging.Logger;
import org.apache.imperius.spl.core.TypeConstants;
import org.apache.imperius.spl.core.TypeInfo;
import org.apache.imperius.spl.parser.exceptions.SPLException;
import org.apache.imperius.spl.parser.expressions.StringExpression;
import org.apache.imperius.spl.parser.expressions.TripleArgumentExpression;
import org.apache.imperius.spl.parser.util.TypeResolver;
import org.apache.imperius.util.Messages;
import org.apache.imperius.util.SPLLogger;
public class RightSubstring extends TripleArgumentExpression implements
StringExpression
{
public static final String className = RightSubstring.class.getName();
private static Logger logger = SPLLogger.getSPLLogger().getLogger();
private static final String sourceClass="RightSubstring";
public RightSubstring(List exprList, boolean validateExpression)
throws SPLException
{
super(exprList);
logger.entering(sourceClass,Thread.currentThread().getName()+" "+ "RightSubstring");
if (validateExpression)
{
if (!validate())
{
logger.severe(Thread.currentThread().getName()+" "+"validation error: " + className
+ " has wrong data type passed in.");
throw new SPLException(Messages.getString(
"SPL_VALIDATION_ERROR_MSG", new Object[] { className }));
}
}
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "RightSubstring");
}
public Object evaluate() throws SPLException
{
logger.entering(sourceClass,Thread.currentThread().getName()+" "+ "evaluate");
try
{
String o1 = (String) _lhsExp.evaluate();
Object o2 = _midExp.evaluate();
String o3 = (String) _rhsExp.evaluate();
boolean leftToRight;
if (o3.equals("LeftToRight"))
{
leftToRight = true;
}
else if (o3.equals("RightToLeft"))
{
leftToRight = false;
}
else
{
logger.severe(
"Illegal direction argument.");
throw new IllegalArgumentException(Messages
.getString("SPL_INVALID_DIRECTION_ARGUMENT_ERROR_MSG"));
}
if (o2 instanceof String)
{
String result = _rightSubstring(o1, (String) o2, leftToRight);
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "evaluate" + result);
return result;
}
else
{
String result = _rightSubstring(o1, ((Number) o2).intValue(), leftToRight);
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "evaluate" + result);
return result;
}
}
catch (Exception e)
{
logger.severe(Thread.currentThread().getName()+" "+"evaluation error: " + toString());
throw new SPLException(Messages.getString(
"SPL_EVALUATION_ERROR_MSG", new Object[] { e
.getLocalizedMessage() }));
}
}
/**
* Returns a <code>String</code> representation of this
* <code>Expression</code> in a format
* <code>[ RightSubstring (Expression1) (Expression2) (Expression3) (LeftToRight | RightToLeft) ]</code>.
* <p>
*
* @return a String representation of this <code>Expression</code>
* @see java.lang.Object#toString()
*/
public String toString()
{
logger.entering(sourceClass,Thread.currentThread().getName()+" "+ "toString");
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "toString");
// return " RightSubstring (" + super.toString() + " ) ";
return " RightSubstring (" + _lhsExp.toString() + ","
+ _midExp.toString() + "," + _rhsExp.toString() + " ) ";
}
/**
* Returns a specified RightSubstring from a string. If directionLeftToRight
* is true, numberChars is the number of characters to return from the end
* of the string. If the number is 2, the last two characters of the string
* are returned; if the number is 5, the last five characters are returned,
* and so on. If the number is negative, the entire string is returned. If
* instead directionLeftToRight is false, numberChars counting from left to
* right is the number of characters to skip. All the characters to the
* right of that number are returned. If the number is negative, the empty
* string is returned.<br>
* Examples: RightSubstring("AutonomicComputing", 4, LeftToRight) = "ting".
* RightSubstring("AutonomicComputing", 4, RightToLeft) = "nomicComputing".
* <p>
*
* @param string
* @param numberChars
* @param directionLeftToRight
*
* @return the resulting substring
*/
private String _rightSubstring(String string, int numberChars,
boolean directionLeftToRight)
{
logger.entering(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring");
if (directionLeftToRight)
{
if (numberChars < 0)
{
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring");
return string;
}
else if (numberChars > string.length())
{
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring");
return string;
}
else
{
String result = string.substring(string.length() - numberChars, string
.length());
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring" + result);
return result;
}
}
else
{
if (numberChars < 0)
{
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring");
return "";
}
else if (numberChars > string.length())
{
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring");
return "";
}
else
{
String result = string.substring(numberChars, string.length());
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring" + result);
return result;
}
}
}
/**
* Returns a specified RightSubstring from a string. RightSubstring returns
* the characters from the String to the right of the startString, not
* including the startString characters. If directionLeftToRight is true,
* then it finds StartString by searching the string from left to right. If
* directionLeftToRight is false, then it finds startString by searching the
* String from right to left. In either case, if the StartString is not
* found in the String, then the empty string is returned. <br>
*
* Examples: RightSubstring("AutonomicComputing", "om",
* LeftToRight)="icComputing" RightSubstring("AutonomicComputing", "om",
* RightToLeft)="puting".
* <p>
*
* @param string
* @param startString
* @param directionLeftToRight
*
* @return the resulting substring
*/
private String _rightSubstring(String string, String startString,
boolean directionLeftToRight)
{
logger.entering(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring");
int offsetpoint; // Position of the beginning of the startString
if (directionLeftToRight)
{
offsetpoint = string.indexOf(startString);
if (offsetpoint < 0)
{
// Did not find the string
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring");
return "";
}
else
{
// found string
offsetpoint += startString.length();
}
}
else
{
offsetpoint = string.lastIndexOf(startString);
if (offsetpoint < 0)
{
// Did not find the string
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring");
return "";
}
else
{
offsetpoint += startString.length();
}
}
if (offsetpoint > string.length())
{
// no characters after string
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring");
return "";
}
else
{
String result = string.substring(offsetpoint, string.length());
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "rightSubstring" + result);
return result;
}
}
public boolean validate() throws SPLException
{
logger.entering(sourceClass,Thread.currentThread().getName()+" "+ "validate");
TypeInfo lType = _lhsExp.getType();
TypeInfo mType = _midExp.getType();
TypeInfo rType = _rhsExp.getType();
if (!lType.getIsArray() && !mType.getIsArray() && !rType.getIsArray() &&
TypeResolver.isString(lType)
&& (TypeResolver.isString(mType) || TypeResolver
.isNumeric(mType)) && TypeResolver.isString(rType))
{
_dataType.setType(TypeConstants.stringType);
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "validate");
return true;
}
logger.exiting(sourceClass,Thread.currentThread().getName()+" "+ "validate");
return false;
}
}