/*
* @(#)OperationFactory.java 1.24 03/12/19
*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.sun.corba.se.spi.orb ;
import java.util.StringTokenizer ;
import java.lang.reflect.Array ;
import java.net.URL ;
import java.net.MalformedURLException ;
import com.sun.corba.se.spi.logging.CORBALogDomains ;
import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
import com.sun.corba.se.impl.orbutil.ORBClassLoader ;
import com.sun.corba.se.impl.orbutil.ObjectUtility ;
/** This is a static factory class for commonly used operations
* for property parsing. The following operations are supported:
*
* - maskErrorAction( Operation op ) executes op and returns the result. If op throws an
* exception, the result is null.
*
- indexAction( int arg ) returns the [arg] element of value, which must be an Object[]
* - identityAction() return the value
* - booleanAction() return a Boolean representing true or false values of the String value
* - integerAction() returns an Integer for the String value, which must be a decimal integer
* - stringAction() returns the String value
* - classAction() returns a class for the String value, as loaded by the ORB classloader
* - setFlagAction() always return Boolean.TRUE
* - URLAction() returns a java.net.URL for the String value, which must be a valid URL
* - integerRangeAction( int min, int max ) returns an Integer for the String value, which must be a
* decimal integer in the range min to max inclusive
* - listAction( String sep, Operation ) tokenizes the String value with sep as separator, then
* applies the Operation to each token, and returns an array of the result
* - sequenceAction( String, Operation[] ) tokenizes the String value with sep as separator, then
* applies each Operation in the Operation array to successive tokens, and returns an array of the results
* - compose( Operation op1, Operation op2 ) is the operation that applies op2 to the result of applying
* op1 to the value
* - mapAction( Operation ) applies the Operation to each element of an array of objects, and returns
* an array of the results
* - mapSequenceAction( Operation[] ) applies the corresponding element of the Operation array to an
* element of the Object[] value, and returns an array of the results
* - convertIntegerToShort coerces an Integer into a Short.
*
* Other operations can be directly defined, and combined using these basic operations.
*/
public abstract class OperationFactory {
private OperationFactory() {}
private static String getString( Object obj )
{
if (obj instanceof String)
return (String)obj ;
else
throw new Error( "String expected" ) ;
}
private static Object[] getObjectArray( Object obj )
{
if (obj instanceof Object[])
return (Object[])obj ;
else
throw new Error( "Object[] expected" ) ;
}
private static StringPair getStringPair( Object obj )
{
if (obj instanceof StringPair)
return (StringPair)obj ;
else
throw new Error( "StringPair expected" ) ;
}
private static abstract class OperationBase implements Operation{
public boolean equals( Object obj )
{
if (this==obj)
return true ;
if (!(obj instanceof OperationBase))
return false ;
OperationBase other = (OperationBase)obj ;
return toString().equals( other.toString() ) ;
}
public int hashCode()
{
return toString().hashCode() ;
}
}
private static class MaskErrorAction extends OperationBase
{
private Operation op ;
public MaskErrorAction( Operation op )
{
this.op = op ;
}
public Object operate( Object arg )
{
try {
return op.operate( arg ) ;
} catch (java.lang.Exception exc) {
return null ;
}
}
public String toString()
{
return "maskErrorAction(" + op + ")" ;
}
}
public static Operation maskErrorAction( Operation op )
{
return new MaskErrorAction( op ) ;
}
private static class IndexAction extends OperationBase
{
private int index ;
public IndexAction( int index )
{
this.index = index ;
}
public Object operate( Object value )
{
return getObjectArray( value )[ index ] ;
}
public String toString()
{
return "indexAction(" + index + ")" ;
}
}
public static Operation indexAction( int index )
{
return new IndexAction( index ) ;
}
private static class SuffixAction extends OperationBase
{
public Object operate( Object value )
{
return getStringPair( value ).getFirst() ;
}
public String toString() { return "suffixAction" ; }
}
private static Operation suffixActionImpl = new SuffixAction() ;
private static class ValueAction extends OperationBase
{
public Object operate( Object value )
{
return getStringPair( value ).getSecond() ;
}
public String toString() { return "valueAction" ; }
}
private static Operation valueActionImpl = new ValueAction() ;
private static class IdentityAction extends OperationBase
{
public Object operate( Object value )
{
return value ;
}
public String toString() { return "identityAction" ; }
}
private static Operation identityActionImpl = new IdentityAction() ;
private static class BooleanAction extends OperationBase
{
public Object operate( Object value )
{
return new Boolean( getString( value ) ) ;
}
public String toString() { return "booleanAction" ; }
}
private static Operation booleanActionImpl = new BooleanAction() ;
private static class IntegerAction extends OperationBase
{
public Object operate( Object value )
{
return new Integer( getString( value ) ) ;
}
public String toString() { return "integerAction" ; }
}
private static Operation integerActionImpl = new IntegerAction() ;
private static class StringAction extends OperationBase
{
public Object operate( Object value )
{
return value ;
}
public String toString() { return "stringAction" ; }
}
private static Operation stringActionImpl = new StringAction() ;
private static class ClassAction extends OperationBase
{
public Object operate( Object value )
{
String className = getString( value ) ;
try {
Class result = ORBClassLoader.loadClass( className ) ;
return result ;
} catch (Exception exc) {
ORBUtilSystemException wrapper = ORBUtilSystemException.get(
CORBALogDomains.ORB_LIFECYCLE ) ;
throw wrapper.couldNotLoadClass( exc, className ) ;
}
}
public String toString() { return "classAction" ; }
}
private static Operation classActionImpl = new ClassAction() ;
private static class SetFlagAction extends OperationBase
{
public Object operate( Object value )
{
return Boolean.TRUE ;
}
public String toString() { return "setFlagAction" ; }
}
private static Operation setFlagActionImpl = new SetFlagAction() ;
private static class URLAction extends OperationBase
{
public Object operate( Object value )
{
String val = (String)value ;
try {
return new URL( val ) ;
} catch (MalformedURLException exc) {
ORBUtilSystemException wrapper = ORBUtilSystemException.get(
CORBALogDomains.ORB_LIFECYCLE ) ;
throw wrapper.badUrl( exc, val ) ;
}
}
public String toString() { return "URLAction" ; }
}
private static Operation URLActionImpl = new URLAction() ;
public static Operation identityAction()
{
return identityActionImpl ;
}
public static Operation suffixAction()
{
return suffixActionImpl ;
}
public static Operation valueAction()
{
return valueActionImpl ;
}
public static Operation booleanAction()
{
return booleanActionImpl ;
}
public static Operation integerAction()
{
return integerActionImpl ;
}
public static Operation stringAction()
{
return stringActionImpl ;
}
public static Operation classAction()
{
return classActionImpl ;
}
public static Operation setFlagAction()
{
return setFlagActionImpl ;
}
public static Operation URLAction()
{
return URLActionImpl ;
}
private static class IntegerRangeAction extends OperationBase
{
private int min ;
private int max ;
IntegerRangeAction( int min, int max )
{
this.min = min ;
this.max = max ;
}
public Object operate( Object value )
{
int result = Integer.parseInt( getString( value ) ) ;
if ((result >= min) && (result <= max))
return new Integer( result ) ;
else
throw new IllegalArgumentException(
"Property value " + result + " is not in the range " +
min + " to " + max ) ;
}
public String toString() {
return "integerRangeAction(" + min + "," + max + ")" ;
}
}
public static Operation integerRangeAction( int min, int max )
{
return new IntegerRangeAction( min, max ) ;
}
private static class ListAction extends OperationBase {
private String sep ;
private Operation act ;
ListAction( String sep, Operation act )
{
this.sep = sep ;
this.act = act ;
}
// Note that this method carefully constructs an array of the type
// of the first result, rather than just using Object[], which is
// not convertible into the correct type. Also note that no tokens
// results in a null result.
public Object operate( Object value )
{
StringTokenizer st = new StringTokenizer( getString( value ),
sep ) ;
int length = st.countTokens() ;
Object result = null ;
int ctr = 0 ;
while (st.hasMoreTokens()) {
String next = st.nextToken() ;
Object val = act.operate( next ) ;
if (result == null)
result = Array.newInstance( val.getClass(), length ) ;
Array.set( result, ctr++, val ) ;
}
return result ;
}
public String toString() {
return "listAction(separator=\"" + sep +
"\",action=" + act + ")" ;
}
}
public static Operation listAction( String sep, Operation act )
{
return new ListAction( sep, act ) ;
}
private static class SequenceAction extends OperationBase
{
private String sep ;
private Operation[] actions ;
SequenceAction( String sep, Operation[] actions )
{
this.sep = sep ;
this.actions = actions ;
}
public Object operate( Object value )
{
StringTokenizer st = new StringTokenizer( getString( value ),
sep ) ;
int numTokens = st.countTokens() ;
if (numTokens != actions.length)
throw new Error(
"Number of tokens and number of actions do not match" ) ;
int ctr = 0 ;
Object[] result = new Object[ numTokens ] ;
while (st.hasMoreTokens()) {
Operation act = actions[ctr] ;
String next = st.nextToken() ;
result[ctr++] = act.operate( next ) ;
}
return result ;
}
public String toString() {
return "sequenceAction(separator=\"" + sep +
"\",actions=" +
ObjectUtility.compactObjectToString(actions) + ")" ;
}
}
public static Operation sequenceAction( String sep,
Operation[] actions )
{
return new SequenceAction( sep, actions ) ;
}
private static class ComposeAction extends OperationBase
{
private Operation op1 ;
private Operation op2 ;
ComposeAction( Operation op1, Operation op2 )
{
this.op1 = op1 ;
this.op2 = op2 ;
}
public Object operate( Object value )
{
return op2.operate( op1.operate( value ) ) ;
}
public String toString() {
return "composition(" + op1 + "," + op2 + ")" ;
}
}
public static Operation compose( Operation op1, Operation op2 )
{
return new ComposeAction( op1, op2 ) ;
}
private static class MapAction extends OperationBase
{
Operation op ;
MapAction( Operation op )
{
this.op = op ;
}
public Object operate( Object value )
{
Object[] values = (Object[])value ;
Object[] result = new Object[ values.length ] ;
for (int ctr=0; ctr