/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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.core.factmodel.traits; 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.LinkedHashMap; import java.util.List; import java.util.Map; import org.drools.core.WorkingMemory; import org.drools.core.util.ClassUtils; import org.drools.core.util.MVELSafeHelper; import org.drools.core.util.bitmask.BitMask; import static org.drools.core.reteoo.PropertySpecificUtil.onlyTraitBitSetMask; import static org.drools.core.reteoo.PropertySpecificUtil.setPropertyOnMask; public class TraitFieldTMSImpl implements TraitFieldTMS, Externalizable { private Map<String, TraitField> fieldTMS = new LinkedHashMap<String, TraitField>(); private transient WorkingMemory workingMemory; private TypeCache typeCache = new TypeCache(); private BitMask modificationMask = onlyTraitBitSetMask(); public void init( WorkingMemory wm ) { this.workingMemory = wm; if ( getTypeCache().needsInit() ) { getTypeCache().init( wm ); } } public TraitFieldTMSImpl() { } public void registerField( Class domainKlass, String name ) { registerField( domainKlass, name, Object.class, null, null ); } public void registerField( Class domainKlass, String name, Class rangeKlass, Object value, String initial ) { short pos = (short) ClassUtils.getAccessibleProperties( domainKlass ).indexOf( name ); TraitField fld = new TraitField( getKlass( rangeKlass ), value, initial != null ? MVELSafeHelper.getEvaluator().eval( initial, rangeKlass ) : null, pos ); fieldTMS.put( name, fld ); } public Object set( String name, Object value, Class klass ) { return fieldTMS.get( name ).set( value, getKlass( klass ), workingMemory ); } public Object get( String name, Class klass ) { return fieldTMS.get( name ).get( getKlass( klass ) ); } public boolean isManagingField( String name ) { return fieldTMS.containsKey( name ); } public Object donField( String name, TraitType trait, String defaultValue, Class klass, boolean logical ) { TraitField fld = fieldTMS.get( name ); modificationMask = setPropertyOnMask(modificationMask, fld.getPosition()); return fld.don( trait, defaultValue != null ? MVELSafeHelper.getEvaluator().eval( defaultValue, klass ) : null, getKlass( klass ), logical, workingMemory ); } public Object shedField( String name, TraitType trait, Class rangeKlass, Class asKlass ) { TraitField fld = fieldTMS.get( name ); modificationMask = setPropertyOnMask(modificationMask, fld.getPosition()); return fld.shed( trait, getKlass( rangeKlass ), getKlass( asKlass ), workingMemory ); } private TypeWrapper getKlass( Class klass ) { TypeWrapper wrapper = getTypeCache().get( klass.getName() ); if ( wrapper == null ) { wrapper = new TypeWrapper( klass ); getTypeCache().put( wrapper.getName(), wrapper ); } return wrapper; } public boolean needsInit() { return workingMemory == null; } public BitMask getModificationMask() { return modificationMask; } public void resetModificationMask() { modificationMask = onlyTraitBitSetMask(); } public TraitField getRegisteredTraitField( String name ) { return fieldTMS.get( name ); } public void writeExternal( ObjectOutput out ) throws IOException { out.writeInt( fieldTMS.size() ); List<String> keys = new ArrayList<String>( fieldTMS.keySet() ); Collections.sort( keys ); for ( String k : keys ) { out.writeObject( k ); out.writeObject( fieldTMS.get( k ) ); } out.writeObject( typeCache ); out.writeObject(modificationMask); } public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException { fieldTMS = new HashMap<String, TraitField>(); int n = in.readInt(); for ( int j = 0; j < n; j++ ) { String k = (String) in.readObject(); TraitField tf = (TraitField) in.readObject(); fieldTMS.put( k, tf ); } typeCache = (TypeCache) in.readObject(); modificationMask = (BitMask) in.readObject(); } public TypeCache getTypeCache() { if ( typeCache == null ) { typeCache = new TypeCache(); } return typeCache; } }