Permalink
Browse files

[DROOLS-91] fix property reactivity masks for inherited properties

  • Loading branch information...
1 parent 69113ff commit 8f3c68105c0605eb73a804bbf1c413130e499676 @mariofusco mariofusco committed Mar 26, 2013
@@ -1523,4 +1523,64 @@ public void testAvoidUnwantedSemicolonWhenDelimitingExpression() {
assertEquals("http://onefineday.123", l.get(0));
}
+
+ @Test
+ public void testScrambleProperties() {
+ // DROOLS-91
+ String str =
+ "package org.drools.test\n" +
+ " global java.util.List list" +
+ "\n" +
+ " declare Parent\n" +
+ " @propertyReactive\n" +
+ " a : int\n" +
+ " k : int\n" +
+ " z : int\n" +
+ " end\n" +
+ "\n" +
+ " declare Child extends Parent\n" +
+ " @propertyReactive\n" +
+ " p : int\n" +
+ " end\n" +
+ "\n" +
+ "\n" +
+ " rule Init\n" +
+ " when\n" +
+ " then\n" +
+ " insert( new Child( 1, 3, 5, 7 ) );\n" +
+ " end\n" +
+ "\n" +
+ " rule Mod\n" +
+ " when\n" +
+ " $p : Parent()\n" +
+ " then\n" +
+ " modify( $p ) { setZ( 99 ); }\n" +
+ " end\n" +
+ "\n" +
+ " rule React2\n" +
+ " when\n" +
+ " Child( p == 7 )\n" +
+ " then\n" +
+ " list.add( \"React2\" );\n" +
+ " end\n" +
+ "\n" +
+ " rule React\n" +
+ " when\n" +
+ " Child( z == 99 )\n" +
+ " then\n" +
+ " list.add( \"React\" );\n" +
+ " end";
+
+ KnowledgeBase kbase = loadKnowledgeBaseFromString(str);
+ StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+
+ List<String> list = new ArrayList<String>();
+ ksession.setGlobal("list", list);
+
+ ksession.fireAllRules();
+
+ assertEquals(2, list.size());
+ assertTrue(list.contains("React"));
+ assertTrue(list.contains("React2"));
+ }
}
@@ -170,7 +170,7 @@ public void testFixThrows() {
String fixed = fixBlockDescr(context, analysis, context.getDeclarationResolver().getDeclarations( context.getRule() ) );
String expected =
- " { $cheese.setPrice( 10 ); $cheese.setOldPrice( age ); drools.update( $cheese__Handle__, 12L ); }\r\n" +
+ " { $cheese.setPrice( 10 ); $cheese.setOldPrice( age ); drools.update( $cheese__Handle__, 6L ); }\r\n" +
" throw new java.lang.RuntimeException(\"xxx\");\r\n" +
" Cheese c1 = $cheese;\r\n" +
" { org.drools.compiler.Cheese __obj__ = ( c1 ); org.drools.core.FactHandle __obj____Handle2__ = drools.getFactHandle(__obj__);__obj__.setPrice( 10 ); __obj__.setOldPrice( age ); drools.update( __obj____Handle2__, 9223372036854775807L ); }\r\n" +
@@ -298,7 +298,7 @@ public void testFixModifyBlocks() throws Exception {
" Cheese c3 = $cheese;\r\n" +
" { org.drools.compiler.Cheese __obj__ = ( c3 ); org.drools.core.FactHandle __obj____Handle2__ = drools.getFactHandle(__obj__);__obj__.setPrice( 10 ); __obj__.setOldPrice( age ); drools.update( __obj____Handle2__, 9223372036854775807L ); }\r\n" +
" }\r\n" +
- " { $cheese.setPrice( 10 ); $cheese.setOldPrice( age ); drools.update( $cheese__Handle__, 12L ); }\r\n" +
+ " { $cheese.setPrice( 10 ); $cheese.setOldPrice( age ); drools.update( $cheese__Handle__, 6L ); }\r\n" +
" System.out.println(\"we are done\");\r\n" +
" \r\n" +
"";
@@ -32,6 +32,7 @@
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
@@ -48,6 +49,7 @@
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.TreeSet;
public final class ClassUtils {
private static final ProtectionDomain PROTECTION_DOMAIN;
@@ -74,7 +76,7 @@ public static boolean areNullSafeEquals(Object obj1, Object obj2) {
* org/my/Class.xxx -> org.my.Class
*/
public static String convertResourceToClassName(final String pResourceName) {
- return stripExtension(pResourceName).replace( '/', '.' );
+ return stripExtension(pResourceName).replace('/', '.');
}
/**
@@ -95,7 +97,7 @@ public static String convertClassToResourcePath(final String pName) {
* org/my/Class.xxx -> org/my/Class
*/
public static String stripExtension(final String pResourceName) {
- final int i = pResourceName.lastIndexOf( '.' );
+ final int i = pResourceName.lastIndexOf('.');
return pResourceName.substring( 0, i );
}
@@ -111,7 +113,7 @@ public static String clazzName(final File base,
final String absFileName = file.getAbsolutePath();
final int p = absFileName.lastIndexOf( '.' );
final String relFileName = absFileName.substring( rootLength + 1, p );
- return relFileName.replace( File.separatorChar, '.' );
+ return relFileName.replace(File.separatorChar, '.');
}
public static String relative(final File base,
@@ -339,32 +341,87 @@ public static String getPackage(Class<?> cls) {
}
public static List<String> getSettableProperties(Class<?> clazz) {
- Set<String> props = new HashSet<String>();
+ Set<SetterInClass> props = new TreeSet<SetterInClass>();
for (Method m : clazz.getMethods()) {
if (m.getParameterTypes().length == 1) {
String propName = setter2property(m.getName());
if (propName != null) {
- props.add(propName);
+ props.add( new SetterInClass( propName, m.getDeclaringClass() ) );
}
}
- Modifies modifies = m.getAnnotation( Modifies.class );
- if (modifies != null) {
- for (String prop : modifies.value()) {
- props.add( prop.trim() );
- }
- }
+ processModifiesAnnotation(clazz, props, m);
}
for (Field f : clazz.getFields()) {
- props.add(f.getName());
+ if ( !Modifier.isFinal(f.getModifiers()) && !Modifier.isStatic(f.getModifiers()) ) {
+ props.add( new SetterInClass( f.getName(), f.getDeclaringClass() ) );
+ }
}
- List<String> settableProperties = new ArrayList<String>(props);
- Collections.sort(settableProperties);
+ List<String> settableProperties = new ArrayList<String>();
+ for ( SetterInClass setter : props ) {
+ settableProperties.add(setter.setter);
+ }
return settableProperties;
}
+ private static void processModifiesAnnotation(Class<?> clazz, Set<SetterInClass> props, Method m) {
+ Modifies modifies = m.getAnnotation( Modifies.class );
+ if (modifies != null) {
+ for (String prop : modifies.value()) {
+ prop = prop.trim();
+ try {
+ Field field = clazz.getField(prop);
+ props.add( new SetterInClass( field.getName(), field.getDeclaringClass() ) );
+ } catch (NoSuchFieldException e) {
+ String getter = "get" + prop.substring(0, 1).toUpperCase() + prop.substring(1);
+ try {
+ Method method = clazz.getMethod(getter);
+ props.add( new SetterInClass( prop, method.getDeclaringClass() ) );
+ } catch (NoSuchMethodException e1) {
+ getter = "is" + prop.substring(0, 1).toUpperCase() + prop.substring(1);
+ try {
+ Method method = clazz.getMethod(getter);
+ props.add( new SetterInClass( prop, method.getDeclaringClass() ) );
+ } catch (NoSuchMethodException e2) {
+ throw new RuntimeException(e2);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static class SetterInClass implements Comparable {
+ private final String setter;
+ private final Class<?> clazz;
+
+ private SetterInClass(String setter, Class<?> clazz) {
+ this.setter = setter;
+ this.clazz = clazz;
+ }
+
+ public int compareTo(Object o) {
+ SetterInClass other = (SetterInClass) o;
+ if (clazz == other.clazz) {
+ return setter.compareTo(other.setter);
+ }
+ return clazz.isAssignableFrom(other.clazz) ? -1 : 1;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ SetterInClass other = (SetterInClass) obj;
+ return clazz == other.clazz && setter.equals(other.setter);
+ }
+
+ @Override
+ public int hashCode() {
+ return 29 * clazz.hashCode() + 31 * setter.hashCode();
+ }
+ }
+
public static String getter2property(String methodName) {
if (methodName.startsWith("get") && methodName.length() > 3) {
return Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);

0 comments on commit 8f3c681

Please sign in to comment.