/****************************************************************************** * Copyright (c) 2016 Oracle * 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: * Konstantin Komissarchik - initial implementation and ongoing maintenance ******************************************************************************/ package org.eclipse.sapphire.modeling.el; import org.eclipse.sapphire.Value; /** * Function that ensures that the returned value is of specified type and prevents function * exceptions from propagating. * * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> */ public class FailSafeFunction extends Function { public static Function create( final Function operand, final Class<?> expectedType ) { return create( operand, expectedType, null ); } public static Function create( final Function operand, final Class<?> expectedType, final Object defaultValue ) { return create( operand, Literal.create( expectedType ), Literal.create( defaultValue ) ); } public static Function create( final Function operand, final Function expectedType ) { return create( operand, expectedType, Literal.NULL ); } public static Function create( Function operand, Function expectedType, Function defaultValue ) { if( operand == null ) { operand = Literal.NULL; } if( expectedType == null ) { throw new IllegalArgumentException(); } if( defaultValue == null ) { defaultValue = Literal.NULL; } if( operand instanceof Literal && expectedType instanceof Literal && defaultValue instanceof Literal ) { final Object op = ( (Literal) operand ).value(); final Object et = ( (Literal) expectedType ).value(); final Object dv = ( (Literal) defaultValue ).value(); if( dv == null && ( op == null || op.getClass().equals( et ) ) ) { return operand; } } final FailSafeFunction function = new FailSafeFunction(); function.init( operand, expectedType, defaultValue ); function.initOrigin( operand.origin(), false ); return function; } @Override public String name() { return "FailSafe"; } @Override public FunctionResult evaluate( final FunctionContext context ) { return new FunctionResult( this, context ) { @Override protected Object evaluate() { final Class<?> type = cast( operand( 1 ), Class.class ); Object val = operand( 0 ); if( val instanceof Value ) { final Value<?> value = (Value<?>) val; if( type == String.class ) { val = value.text(); } else { val = value.content(); } } if( val == null ) { val = operand( 2 ); } try { return cast( val, type ); } catch( FunctionException e ) { return handleFunctionException( e ); } } }; } protected Object handleFunctionException( final FunctionException e ) { return null; } }