/*
* Copyright (c) 2017 OBiBa. All rights reserved.
*
* This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.obiba.magma.js.methods;
import javax.annotation.Nullable;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.obiba.magma.Value;
import org.obiba.magma.ValueSequence;
import org.obiba.magma.ValueType;
import org.obiba.magma.js.ScriptableValue;
import org.obiba.magma.type.IntegerType;
import org.obiba.magma.type.TextType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
/**
* Methods of the {@code ScriptableValue} javascript class that apply to all data ValueTypes.
*/
public class ScriptableValueMethods {
private static final Logger log = LoggerFactory.getLogger(ScriptableValueMethods.class);
private ScriptableValueMethods() {}
/**
* Returns the javascript value of a {@code ScriptableValue}. Useful to turn BooleanType ScriptableValues into native
* javascript values to be used inside if/else statements.
* <p/>
* <pre>
* if($('Admin.Interview.exportLog.destination').empty().value()) {
* // true
* } else {
* // false
* }
* </pre>
*/
public static Object value(Context ctx, Scriptable thisObj, Object[] args, Function funObj) {
ScriptableValue sv = (ScriptableValue) thisObj;
if(sv.getValue().isNull()) {
return null;
}
return sv.getDefaultValue(null);
}
/**
* 1) Invoked with no arguments - ex: type()
* <p/>
* Returns a new {@code ScriptableValue} of type "text" containing the name of the {@code ValueType}.
* <p/>
* 2) Invoked with type argument - ex: type("text")
* <p/>
* Performs a {@code ValueType} conversion and returns a new {@code ScriptableValue} of the requested type.
*/
public static ScriptableValue type(Context ctx, Scriptable thisObj, Object[] args, Function funObj) {
ScriptableValue sv = (ScriptableValue) thisObj;
ValueType valueType = sv.getValueType();
// Return the ValueType name
if(args.length == 0) {
return new ScriptableValue(thisObj, TextType.get().valueOf(valueType.getName()));
}
if(args.length > 1) {
log.warn("{} extra parameters were passed to the javascript method. These will be ignored.", args.length - 1);
}
// Perform a ValueType conversion
return new ScriptableValue(thisObj, ValueType.Factory.forName(args[0].toString()).convert(sv.getValue()));
}
/**
* Get the value length: length of the string representation (default) or number of bytes for a binary value.
* If it is a sequence, a sequence of each value length is returned.
*/
public static ScriptableValue length(Context ctx, Scriptable thisObj, @Nullable Object[] args,
@Nullable Function funObj) {
ScriptableValue sv = (ScriptableValue) thisObj;
Value value = sv.getValue();
if(value.isSequence()) {
ValueSequence valueSequence = value.asSequence();
Value rval = valueSequence.isNull()
? IntegerType.get().nullSequence()
: IntegerType.get().sequenceOf(Lists.newArrayList(
Iterables.transform(valueSequence.getValue(), new com.google.common.base.Function<Value, Value>() {
@Nullable
@Override
public Value apply(@Nullable Value input) {
return input == null || input.isNull()
? IntegerType.get().nullValue()
: IntegerType.get().valueOf(input.getLength());
}
})));
return new ScriptableValue(sv, rval);
}
Value rval = value.isNull() ? IntegerType.get().nullValue() : IntegerType.get().valueOf(value.getLength());
return new ScriptableValue(thisObj, rval);
}
/**
* Transform a Value into a ValueSequence
*/
public static ScriptableValue asSequence(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
ScriptableValue sv = (ScriptableValue) thisObj;
Value value = sv.getValue();
return value.isSequence()
? sv
: new ScriptableValue(thisObj, value.getValueType().sequenceOf(Lists.newArrayList(value)));
}
}