/**
* Copyright 2010 JBoss Inc
*
* Licensed 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.
*/
package org.drools.rule;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.drools.base.mvel.MVELCompileable;
import org.drools.spi.Wireable;
import org.drools.util.CompositeClassLoader;
import org.mvel2.integration.VariableResolver;
import org.mvel2.integration.impl.MapVariableResolverFactory;
public class MVELDialectRuntimeData
implements
DialectRuntimeData,
Externalizable {
private MapFunctionResolverFactory functionFactory;
private Map<Wireable, MVELCompileable> invokerLookups;
private CompositeClassLoader rootClassLoader;
private List<Wireable> wireList = Collections.<Wireable> emptyList();
public MVELDialectRuntimeData() {
this.functionFactory = new MapFunctionResolverFactory();
invokerLookups = new IdentityHashMap<Wireable, MVELCompileable>();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject( invokerLookups );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
invokerLookups = (Map<Wireable, MVELCompileable>) in.readObject();
if ( !invokerLookups.isEmpty() ) {
// we need a wireList for serialisation
wireList = new ArrayList<Wireable>( invokerLookups.keySet() );
}
}
public void merge(DialectRuntimeRegistry registry,
DialectRuntimeData newData) {
MVELDialectRuntimeData other = (MVELDialectRuntimeData) newData;
for ( Entry<Wireable, MVELCompileable> entry : other.invokerLookups.entrySet() ) {
invokerLookups.put( entry.getKey(),
entry.getValue() );
if ( this.wireList == Collections.<Wireable> emptyList() ) {
this.wireList = new ArrayList<Wireable>();
}
wireList.add( entry.getKey() );
// // first make sure the MVELCompilationUnit is compiled
// MVELCompilable component = entry.getValue();
// component.compile( rootClassLoader );
//
// // now wire up the target
// Wireable target = entry.getKey();
// target.wire( component );
// System.out.println( component );
}
}
public DialectRuntimeData clone(DialectRuntimeRegistry registry,
CompositeClassLoader rootClassLoader) {
DialectRuntimeData clone = new MVELDialectRuntimeData();
clone.merge( registry,
this );
clone.onAdd( registry,
rootClassLoader );
return clone;
}
public void onAdd(DialectRuntimeRegistry registry,
CompositeClassLoader rootClassLoader) {
this.rootClassLoader = rootClassLoader;
// for (Entry<Wireable, MVELCompilable> entry : this.invokerLookups.entrySet() ) {
// // first make sure the MVELCompilationUnit is compiled
// MVELCompilable component = entry.getValue();
// component.compile( rootClassLoader );
//
// // now wire up the target
// Wireable target = entry.getKey();
// target.wire( component );
// }
}
public void onRemove() {
}
public void onBeforeExecute() {
for ( Wireable target : wireList ) {
MVELCompileable compileable = invokerLookups.get( target );
compileable.compile( rootClassLoader );
// now wire up the target
target.wire( compileable );
}
wireList.clear();
}
public MapFunctionResolverFactory getFunctionFactory() {
return this.functionFactory;
}
public void removeRule(Package pkg,
Rule rule) {
}
public void addFunction(org.mvel2.ast.Function function) {
this.functionFactory.addFunction( function );
}
// TODO: FIXME: make it consistent with above
public void removeFunction(Package pkg,
org.drools.rule.Function function) {
this.functionFactory.removeFunction( function.getName() );
}
public boolean isDirty() {
return false;
}
public void setDirty(boolean dirty) {
}
public void reload() {
}
public static class MapFunctionResolverFactory extends MapVariableResolverFactory
implements
Externalizable {
public MapFunctionResolverFactory() {
super( new HashMap<String, Object>() );
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject( this.variables );
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.variables = (Map) in.readObject();
}
public void addFunction(org.mvel2.ast.Function function) {
this.variables.put( function.getName(),
function );
}
public void removeFunction(String functionName) {
this.variables.remove( functionName );
this.variableResolvers.remove( functionName );
}
public VariableResolver createVariable(String name,
Object value) {
throw new RuntimeException( "variable is a read-only function pointer" );
}
public VariableResolver createIndexedVariable(int index,
String name,
Object value,
Class< ? > type) {
throw new RuntimeException( "variable is a read-only function pointer" );
}
}
public void addCompileable(Wireable wireable,
MVELCompileable compilable) {
// if ( this.wireList == Collections.<Wireable> emptyList() ) {
// this.wireList = new ArrayList<Wireable>();
// }
// wireList.add( wireable );
invokerLookups.put( wireable,
compilable );
}
public Map<Wireable, MVELCompileable> getLookup() {
return this.invokerLookups;
}
}