/*
* 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;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.mozilla.javascript.FunctionObject;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
public abstract class AbstractPrototypeFactory {
// private static final Logger log = LoggerFactory.getLogger(AbstractPrototypeFactory.class);
private static final Set<String> EXCLUDED_METHODS = ImmutableSet
.of("wait", "toString", "getClass", "equals", "hashCode", "notify", "notifyAll", "$$YJP$$wait");
private final Collection<Class<?>> methodProviders = new HashSet<>();
public void addMethodProvider(Class<?> methodProvider) {
methodProviders.add(methodProvider);
}
public Scriptable buildPrototype() {
Scriptable ctor = newPrototype();
ScriptableObject prototype = new NativeObject();
createMethods(prototype);
ScriptableObject.putConstProperty(ctor, "prototype", prototype);
return ctor;
}
protected void createMethods(ScriptableObject scriptableObject) {
Iterable<Method> methods = Iterables
.concat(Iterables.transform(methodProviders, new Function<Class<?>, Iterable<Method>>() {
@Override
public Iterable<Method> apply(Class<?> from) {
return Iterables.filter(Arrays.asList(from.getMethods()), new Predicate<Method>() {
@Override
public boolean apply(Method input) {
return !EXCLUDED_METHODS.contains(input.getName());
}
});
}
}));
for(Method method : methods) {
// log.trace("Define JS method {}", method.getName());
scriptableObject.defineProperty(method.getName(), new FunctionObject(method.getName(), method, scriptableObject),
ScriptableObject.DONTENUM);
}
}
protected abstract Scriptable newPrototype();
}