/*
* 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.reteoo;
import java.util.Collection;
import java.util.List;
import org.drools.core.base.ClassObjectType;
import org.drools.core.factmodel.traits.TraitableBean;
import org.drools.core.impl.InternalKnowledgeBase;
import org.drools.core.reteoo.builder.BuildContext;
import org.drools.core.rule.TypeDeclaration;
import org.drools.core.spi.ObjectType;
import org.drools.core.util.bitmask.AllSetBitMask;
import org.drools.core.util.bitmask.AllSetButLastBitMask;
import org.drools.core.util.bitmask.BitMask;
import org.drools.core.util.bitmask.EmptyBitMask;
import org.drools.core.util.bitmask.EmptyButLastBitMask;
public class PropertySpecificUtil {
public static final int TRAITABLE_BIT = 0;
public static final int CUSTOM_BITS_OFFSET = 1;
public static boolean isPropertyReactive(BuildContext context, ObjectType objectType) {
return objectType instanceof ClassObjectType && isPropertyReactive(context, ((ClassObjectType) objectType).getClassType());
}
public static boolean isPropertyReactive(BuildContext context, Class<?> objectClass) {
TypeDeclaration typeDeclaration = context.getKnowledgeBase().getTypeDeclaration( objectClass );
return typeDeclaration != null && typeDeclaration.isPropertyReactive();
}
public static BitMask getEmptyPropertyReactiveMask(int settablePropertiesSize) {
return BitMask.Factory.getEmpty(settablePropertiesSize + CUSTOM_BITS_OFFSET);
}
public static BitMask onlyTraitBitSetMask() {
return EmptyButLastBitMask.get();
}
public static BitMask allSetBitMask() {
return AllSetBitMask.get();
}
public static BitMask allSetButTraitBitMask() {
return AllSetButLastBitMask.get();
}
public static boolean isAllSetPropertyReactiveMask(BitMask mask) {
return mask instanceof AllSetButLastBitMask;
}
public static BitMask calculatePositiveMask( Collection<String> listenedProperties, List<String> accessibleProperties ) {
return calculatePatternMask(listenedProperties, accessibleProperties, true);
}
public static BitMask calculateNegativeMask(Collection<String> listenedProperties, List<String> accessibleProperties) {
return calculatePatternMask(listenedProperties, accessibleProperties, false);
}
private static BitMask calculatePatternMask(Collection<String> listenedProperties, List<String> accessibleProperties, boolean isPositive) {
if (listenedProperties == null) {
return EmptyBitMask.get();
}
BitMask mask = getEmptyPropertyReactiveMask(accessibleProperties.size());
if (listenedProperties.contains( TraitableBean.TRAITSET_FIELD_NAME )) {
if (isPositive && listenedProperties.contains( TraitableBean.TRAITSET_FIELD_NAME ) ) {
mask = mask.set(TRAITABLE_BIT);
}
}
for (String propertyName : listenedProperties) {
if (propertyName.equals(isPositive ? "*" : "!*")) {
return isPositive ? AllSetBitMask.get() : allSetButTraitBitMask();
}
if (propertyName.startsWith("!") ^ !isPositive) {
continue;
}
if (!isPositive) {
propertyName = propertyName.substring(1);
}
mask = setPropertyOnMask(mask, accessibleProperties, propertyName);
}
return mask;
}
public static BitMask setPropertyOnMask(BitMask mask, List<String> settableProperties, String propertyName) {
int index = settableProperties.indexOf(propertyName);
if (index < 0) {
throw new RuntimeException("Unknown property: " + propertyName);
}
return setPropertyOnMask(mask, index);
}
public static BitMask setPropertyOnMask(BitMask mask, int index) {
return mask.set(index + CUSTOM_BITS_OFFSET);
}
public static boolean isPropertySetOnMask(BitMask mask, int index) {
return mask.isSet(index + CUSTOM_BITS_OFFSET);
}
public static List<String> getAccessibleProperties( InternalKnowledgeBase kBase, Class<?> nodeClass ) {
return kBase.getOrCreateExactTypeDeclaration(nodeClass).getAccessibleProperties();
}
}