You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2018/02/12 22:58:02 UTC

celix git commit: Refactors filter so that it is possible to traverse parsed filter. Also fixes an issue where semantically equal filter where not matched

Repository: celix
Updated Branches:
  refs/heads/develop b0477babb -> f4cd98387


Refactors filter so that it is possible to traverse parsed filter. Also fixes an issue where semantically equal filter where not matched


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/f4cd9838
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/f4cd9838
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/f4cd9838

Branch: refs/heads/develop
Commit: f4cd983871cd2050244743c0dc047c62b11c1adb
Parents: b0477ba
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Mon Feb 12 23:56:42 2018 +0100
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Mon Feb 12 23:56:47 2018 +0100

----------------------------------------------------------------------
 framework/include/filter.h             |  44 ++-
 framework/private/test/filter_test.cpp |  80 +++--
 framework/src/filter.c                 | 519 ++++++++++++++--------------
 framework/src/filter_private.h         |  57 ---
 utils/include/array_list.h             |   2 +
 5 files changed, 351 insertions(+), 351 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/f4cd9838/framework/include/filter.h
----------------------------------------------------------------------
diff --git a/framework/include/filter.h b/framework/include/filter.h
index 687de2a..179ef53 100644
--- a/framework/include/filter.h
+++ b/framework/include/filter.h
@@ -31,22 +31,54 @@
 #include "properties.h"
 #include "celixbool.h"
 #include "framework_exports.h"
+#include "array_list.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef struct filter *filter_pt;
+typedef enum celix_filter_operand_enum
+{
+    CELIX_FILTER_OPERAND_EQUAL,
+    CELIX_FILTER_OPERAND_APPROX,
+    CELIX_FILTER_OPERAND_GREATER,
+    CELIX_FILTER_OPERAND_GREATEREQUAL,
+    CELIX_FILTER_OPERAND_LESS,
+    CELIX_FILTER_OPERAND_LESSEQUAL,
+    CELIX_FILTER_OPERAND_PRESENT,
+    CELIX_FILTER_OPERAND_SUBSTRING,
+    CELIX_FILTER_OPERAND_AND,
+    CELIX_FILTER_OPERAND_OR,
+    CELIX_FILTER_OPERAND_NOT,
+} celix_filter_operand_t;
 
-FRAMEWORK_EXPORT filter_pt filter_create(const char *filterString);
+typedef struct celix_filter_struct filter_t; //deprecated
+typedef struct celix_filter_struct *filter_pt; //deprecated
 
-FRAMEWORK_EXPORT void filter_destroy(filter_pt filter);
+typedef struct celix_filter_struct celix_filter_t;
 
-FRAMEWORK_EXPORT celix_status_t filter_match(filter_pt filter, properties_pt properties, bool *result);
+struct celix_filter_struct {
+    celix_filter_operand_t operand;
+    char *attribute; //NULL for operands AND, OR ot NOT
+    char *value; //NULL for operands AND, OR or NOT NOT
+    char *filterStr;
 
-FRAMEWORK_EXPORT celix_status_t filter_match_filter(filter_pt src, filter_pt dest, bool *result);
+    //type is celix_filter_t* for AND, OR and NOT operator and char* for SUBSTRING
+    //for other operands childern is NULL
+    array_list_t *children;
+};
 
-FRAMEWORK_EXPORT celix_status_t filter_getString(filter_pt filter, const char **filterStr);
+FRAMEWORK_EXPORT celix_filter_t* filter_create(const char *filterString);
+
+FRAMEWORK_EXPORT void filter_destroy(celix_filter_t *filter);
+
+FRAMEWORK_EXPORT celix_status_t filter_match(celix_filter_t *filter, properties_t *properties, bool *result);
+
+FRAMEWORK_EXPORT celix_status_t filter_match_filter(celix_filter_t *src, filter_t *dest, bool *result);
+
+FRAMEWORK_EXPORT celix_status_t filter_getString(celix_filter_t *filter, const char **filterStr);
+
+FRAMEWORK_EXPORT celix_status_t filter_getString(celix_filter_t *filter, const char **filterStr);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/f4cd9838/framework/private/test/filter_test.cpp
----------------------------------------------------------------------
diff --git a/framework/private/test/filter_test.cpp b/framework/private/test/filter_test.cpp
index c9b1ca5..b802923 100644
--- a/framework/private/test/filter_test.cpp
+++ b/framework/private/test/filter_test.cpp
@@ -16,13 +16,7 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * filter_test.cpp
- *
- *  \date       Feb 11, 2013
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -33,8 +27,8 @@
 #include "CppUTestExt/MockSupport.h"
 
 extern "C" {
-#include "filter_private.h"
 #include "celix_log.h"
+#include "filter.h"
 
 framework_logger_pt logger = (framework_logger_pt) 0x42;
 }
@@ -73,7 +67,7 @@ TEST_GROUP(filter) {
 //----------------FILTER TESTS----------------
 TEST(filter, create_destroy){
 	char * filter_str = my_strdup("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3)))");
-	filter_pt get_filter;
+	celix_filter_t * get_filter;
 
 	get_filter = filter_create(filter_str);
 	CHECK(get_filter != NULL);
@@ -88,7 +82,7 @@ TEST(filter, create_destroy){
 
 TEST(filter, create_fail_missing_opening_brackets){
 	char * filter_str;
-	filter_pt get_filter;
+	celix_filter_t * get_filter;
 
 	//test missing opening brackets in main filter
 	mock().expectNCalls(2, "framework_log");
@@ -125,7 +119,7 @@ TEST(filter, create_fail_missing_opening_brackets){
 
 TEST(filter, create_fail_missing_closing_brackets){
 	char * filter_str;
-	filter_pt get_filter;
+	celix_filter_t * get_filter;
 	//test missing closing brackets in substring
 	mock().expectNCalls(5, "framework_log");
 	filter_str = my_strdup("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3");
@@ -145,7 +139,7 @@ TEST(filter, create_fail_missing_closing_brackets){
 
 TEST(filter, create_fail_invalid_closing_brackets){
 	char * filter_str;
-	filter_pt get_filter;
+	celix_filter_t * get_filter;
 	//test missing closing brackets in substring
 	mock().expectNCalls(6, "framework_log");
 	filter_str = my_strdup("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=at(tr3)))");
@@ -165,7 +159,7 @@ TEST(filter, create_fail_invalid_closing_brackets){
 
 TEST(filter, create_misc){
 	char * filter_str;
-	filter_pt get_filter;
+	celix_filter_t * get_filter;
 	//test trailing chars
 	mock().expectOneCall("framework_log");
 	filter_str = my_strdup("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3))) oh no! trailing chars");
@@ -186,8 +180,8 @@ TEST(filter, create_misc){
 	filter_str = my_strdup("(test_attr3=*attr3)");
 	get_filter = filter_create(filter_str);
 	CHECK(get_filter != NULL);
-	LONGS_EQUAL(SUBSTRING, get_filter->operand)
-	LONGS_EQUAL(2, arrayList_size((array_list_pt) get_filter->value));
+	LONGS_EQUAL(CELIX_FILTER_OPERAND_SUBSTRING, get_filter->operand)
+	LONGS_EQUAL(2, arrayList_size((array_list_pt) get_filter->children));
 	filter_destroy(get_filter);
 	free(filter_str);
 	mock().checkExpectations();
@@ -229,7 +223,7 @@ TEST(filter, create_misc){
 
 TEST(filter, match_comparators){
 	char * filter_str;
-	filter_pt filter;
+	celix_filter_t * filter;
 	properties_pt props = properties_create();
 	char * key = my_strdup("test_attr1");
 	char * val = my_strdup("attr1");
@@ -268,7 +262,7 @@ TEST(filter, match_comparators){
 
 TEST(filter, match_operators){
 	char * filter_str;
-	filter_pt filter;
+	celix_filter_t * filter;
 	properties_pt props = properties_create();
 	char * key = my_strdup("test_attr1");
 	char * val = my_strdup("attr1");
@@ -470,7 +464,7 @@ TEST(filter, match_operators){
 TEST(filter, match_recursion){
 
 	char * filter_str = my_strdup("(&(test_attr1=attr1)(|(&(test_attr2=attr2)(!(&(test_attr1=attr1)(test_attr3=attr3))))(test_attr3=attr3)))");
-	filter_pt filter = filter_create(filter_str);
+	celix_filter_t * filter = filter_create(filter_str);
 	properties_pt props = properties_create();
 	char * key = my_strdup("test_attr1");
 	char * val = my_strdup("attr1");
@@ -497,7 +491,7 @@ TEST(filter, match_recursion){
 
 TEST(filter, match_false){
 	char * filter_str = my_strdup("(&(test_attr1=attr1)(&(test_attr2=attr2)(test_attr3=attr3)))");
-	filter_pt filter = filter_create(filter_str);
+	celix_filter_t * filter = filter_create(filter_str);
 	properties_pt props = properties_create();
 	char * key = my_strdup("test_attr1");
 	char * val = my_strdup("attr1");
@@ -523,26 +517,54 @@ TEST(filter, match_false){
 }
 
 TEST(filter, match_filter){
-	char * filter_str = my_strdup("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3)))");
-	char * compareTo_str = my_strdup("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3)))");
-	filter_pt filter = filter_create(filter_str);
-	filter_pt compareTo = filter_create(compareTo_str);
+	mock().ignoreOtherCalls(); //only log
 
-	bool result;
-	filter_match_filter(filter, compareTo, &result);
+	celix_filter_t *filter = filter_create("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3)))");
+    celix_filter_t *compareTo = filter_create("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3)))");
 
+	bool result;
+	filter_match_filter(filter, compareTo, &result); //equal same order
+    CHECK_TRUE(result);
 	//cleanup
 	filter_destroy(filter);
 	filter_destroy(compareTo);
-	free(filter_str);
-	free(compareTo_str);
 
-	mock().checkExpectations();
+    filter = filter_create("(&(test_attr1=attr1)(test_attr2=attr2)(test_attr3=attr3))");
+    compareTo = filter_create("(&(test_attr3=attr3)(test_attr2=attr2)(test_attr1=attr1))");
+	CHECK(filter != NULL);
+	CHECK(compareTo != NULL);
+    filter_match_filter(filter, compareTo, &result); //equal not same order
+    CHECK_TRUE(result);
+    //cleanup
+    filter_destroy(filter);
+    filter_destroy(compareTo);
+
+    filter = filter_create("(&(test_attr1=attr1)(test_attr2=attr2)(test_attr3=attr3))");
+    compareTo = filter_create("(&(test_attr1=attr1)(test_attr2=attr2)(test_attr4=attr4))");
+	CHECK(filter != NULL);
+	CHECK(compareTo != NULL);
+    filter_match_filter(filter, compareTo, &result); //almost, but not equal
+    CHECK_FALSE(result);
+    //cleanup
+    filter_destroy(filter);
+    filter_destroy(compareTo);
+
+	filter_match_filter(NULL, NULL, &result); //both null  -> equal
+	CHECK_TRUE(result);
+
+	filter = filter_create("(attr1=)");
+	filter_match_filter(filter, NULL, &result); //one null  -> not equal
+	CHECK_FALSE(result);
+
+	filter_match_filter(NULL, filter, &result); //one null  -> not equal
+	CHECK_FALSE(result);
+
+	filter_destroy(filter);
 }
 
 TEST(filter, getString){
 	char * filter_str = my_strdup("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3)))");
-	filter_pt filter = filter_create(filter_str);
+	celix_filter_t * filter = filter_create(filter_str);
 
 	const char * get_str;
 	filter_getString(filter, &get_str);

http://git-wip-us.apache.org/repos/asf/celix/blob/f4cd9838/framework/src/filter.c
----------------------------------------------------------------------
diff --git a/framework/src/filter.c b/framework/src/filter.c
index f06d6e8..7077b08 100644
--- a/framework/src/filter.c
+++ b/framework/src/filter.c
@@ -27,23 +27,22 @@
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <assert.h>
 
 #include "celix_log.h"
-#include "filter_private.h"
+#include "filter.h"
 
 static void filter_skipWhiteSpace(char* filterString, int* pos);
-static filter_pt filter_parseFilter(char* filterString, int* pos);
-static filter_pt filter_parseFilterComp(char* filterString, int* pos);
-static filter_pt filter_parseAnd(char* filterString, int* pos);
-static filter_pt filter_parseOr(char* filterString, int* pos);
-static filter_pt filter_parseNot(char* filterString, int* pos);
-static filter_pt filter_parseItem(char* filterString, int* pos);
+static celix_filter_t * filter_parseFilter(char* filterString, int* pos);
+static celix_filter_t * filter_parseFilterComp(char* filterString, int* pos);
+static celix_filter_t * filter_parseAndOrOr(char* filterString, celix_filter_operand_t andOrOr, int* pos);
+static celix_filter_t * filter_parseNot(char* filterString, int* pos);
+static celix_filter_t * filter_parseItem(char* filterString, int* pos);
 static char * filter_parseAttr(char* filterString, int* pos);
 static char * filter_parseValue(char* filterString, int* pos);
 static array_list_pt filter_parseSubstring(char* filterString, int* pos);
 
-static celix_status_t filter_compare(OPERAND operand, char * string, void * value2, bool *result);
-static celix_status_t filter_compareString(OPERAND operand, char * string, void * value2, bool *result);
+static celix_status_t filter_compare(celix_filter_t* filter, const char *propertyValue, bool *result);
 
 static void filter_skipWhiteSpace(char * filterString, int * pos) {
 	int length;
@@ -52,60 +51,69 @@ static void filter_skipWhiteSpace(char * filterString, int * pos) {
 	}
 }
 
-filter_pt filter_create(const char* filterString) {
-	filter_pt filter = NULL;
-	char* filterStr = (char*) filterString;
+celix_filter_t * filter_create(const char* filterString) {
+	celix_filter_t * filter = NULL;
+	char* filterStr = strndup(filterString, 1024*1024);
 	int pos = 0;
 	filter = filter_parseFilter(filterStr, &pos);
 	if (pos != strlen(filterStr)) {
 		fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR,  "Error: Extraneous trailing characters.");
+        free(filterStr);
 		filter_destroy(filter);
 		return NULL;
 	}
-	if(filter != NULL){
-		filter->filterStr = filterStr;
-	} 
+	if (filter != NULL) {
+        filter->filterStr = filterStr;
+
+        if (filter->operand != CELIX_FILTER_OPERAND_OR && filter->operand != CELIX_FILTER_OPERAND_AND &&
+            filter->operand != CELIX_FILTER_OPERAND_NOT && filter->operand != CELIX_FILTER_OPERAND_SUBSTRING &&
+            filter->operand != CELIX_FILTER_OPERAND_PRESENT) {
+            if (filter->attribute == NULL || filter->value == NULL) {
+                filter_destroy(filter);
+                filter = NULL;
+            }
+        }
+    }
 
 	return filter;
 }
 
-void filter_destroy(filter_pt filter) {
+void filter_destroy(celix_filter_t * filter) {
 	if (filter != NULL) {
-		if(filter->value!=NULL){
-			if (filter->operand == SUBSTRING) {
-				int size = arrayList_size(filter->value);
+		if(filter->children != NULL){
+			if (filter->operand == CELIX_FILTER_OPERAND_SUBSTRING) {
+				int size = arrayList_size(filter->children);
 				for (; size > 0; --size) {
-					char* operand = (char*) arrayList_remove(filter->value, 0);
+					char* operand = (char*) arrayList_remove(filter->children, 0);
 					free(operand);
 				}
-				arrayList_destroy(filter->value);
-				filter->value = NULL;
-			} else if ( (filter->operand == OR) || (filter->operand == AND) ) {
-				int size = arrayList_size(filter->value);
-				unsigned int i = 0;
-				for (i = 0; i < size; i++) {
-					filter_pt f = arrayList_get(filter->value, i);
-					filter_destroy(f);
-				}
-				arrayList_destroy(filter->value);
-				filter->value = NULL;
-			} else  if (filter->operand == NOT) {
-				filter_destroy(filter->value);
-				filter->value = NULL;
-			} else {
-				free(filter->value);
-				filter->value = NULL;
-			}
+				arrayList_destroy(filter->children);
+				filter->children = NULL;
+			} else if (filter->operand == CELIX_FILTER_OPERAND_OR || filter->operand == CELIX_FILTER_OPERAND_AND || filter->operand == CELIX_FILTER_OPERAND_NOT) {
+                int size = arrayList_size(filter->children);
+                unsigned int i = 0;
+                for (i = 0; i < size; i++) {
+                    celix_filter_t *f = arrayList_get(filter->children, i);
+                    filter_destroy(f);
+                }
+                arrayList_destroy(filter->children);
+                filter->children = NULL;
+            } else {
+                fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR,  "Error: Corrupt filter. childern has a value, but not an expected operand");
+            }
 		}
+        free(filter->value);
+        filter->value = NULL;
 		free(filter->attribute);
 		filter->attribute = NULL;
 		free(filter);
-		filter = NULL;
+        free(filter->filterStr);
+        filter->filterStr = NULL;
 	}
 }
 
-static filter_pt filter_parseFilter(char * filterString, int * pos) {
-	filter_pt filter;
+static celix_filter_t * filter_parseFilter(char * filterString, int * pos) {
+	celix_filter_t * filter;
 	filter_skipWhiteSpace(filterString, pos);
 	if (filterString[*pos] != '(') {
 		fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error: Missing '(' in filter string '%s'.", filterString);
@@ -127,17 +135,10 @@ static filter_pt filter_parseFilter(char * filterString, int * pos) {
 	(*pos)++;
 	filter_skipWhiteSpace(filterString, pos);
 
-	if(filter != NULL){
-		if(filter->value == NULL && filter->operand!=PRESENT){
-			filter_destroy(filter);
-			return NULL;
-		}
-	}
-
 	return filter;
 }
 
-static filter_pt filter_parseFilterComp(char * filterString, int * pos) {
+static celix_filter_t * filter_parseFilterComp(char * filterString, int * pos) {
 	char c;
 	filter_skipWhiteSpace(filterString, pos);
 
@@ -146,11 +147,11 @@ static filter_pt filter_parseFilterComp(char * filterString, int * pos) {
 	switch (c) {
 		case '&': {
 			(*pos)++;
-			return filter_parseAnd(filterString, pos);
+			return filter_parseAndOrOr(filterString, CELIX_FILTER_OPERAND_AND, pos);
 		}
 		case '|': {
 			(*pos)++;
-			return filter_parseOr(filterString, pos);
+			return filter_parseAndOrOr(filterString, CELIX_FILTER_OPERAND_OR, pos);
 		}
 		case '!': {
 			(*pos)++;
@@ -160,9 +161,9 @@ static filter_pt filter_parseFilterComp(char * filterString, int * pos) {
 	return filter_parseItem(filterString, pos);
 }
 
-static filter_pt filter_parseAnd(char * filterString, int * pos) {
+static celix_filter_t * filter_parseAndOrOr(char * filterString, celix_filter_operand_t andOrOr, int * pos) {
 
-	array_list_pt operands = NULL;
+	array_list_pt children = NULL;
 	filter_skipWhiteSpace(filterString, pos);
 	bool failure = false;
 
@@ -171,78 +172,35 @@ static filter_pt filter_parseAnd(char * filterString, int * pos) {
 		return NULL;
 	}
 
-	arrayList_create(&operands);
+	arrayList_create(&children);
 	while(filterString[*pos] == '(') {
-		filter_pt child = filter_parseFilter(filterString, pos);
-		if(child == NULL){
+		celix_filter_t * child = filter_parseFilter(filterString, pos);
+		if(child == NULL) {
 			failure = true;
 			break;
 		}
-		arrayList_add(operands, child);
+		arrayList_add(children, child);
 	}
 
 	if(failure == true){
-		array_list_iterator_pt listIt = arrayListIterator_create(operands);
-		while(arrayListIterator_hasNext(listIt)){
-			filter_pt f = arrayListIterator_next(listIt);
+        int i;
+		for (i = 0; i < arrayList_size(children); ++i) {
+			celix_filter_t * f = arrayList_get(children, i);
 			filter_destroy(f);
 		}
-		arrayListIterator_destroy(listIt);
-		arrayList_destroy(operands);
-		operands = NULL;
+		arrayList_destroy(children);
+        children = NULL;
 	}
 
-	filter_pt filter = (filter_pt) malloc(sizeof(*filter));
-	filter->operand = AND;
-	filter->attribute = NULL;
-	filter->value = operands;
+	celix_filter_t * filter = (celix_filter_t *) calloc(1, sizeof(*filter));
+	filter->operand = andOrOr;
+    filter->children = children;
 
 	return filter;
 }
 
-static filter_pt filter_parseOr(char * filterString, int * pos) {
-
-	array_list_pt operands = NULL;
-
-	filter_skipWhiteSpace(filterString, pos);
-	bool failure = false;
-
-	if (filterString[*pos] != '(') {
-		fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error: Missing '('.");
-		return NULL;
-	}
-
-	arrayList_create(&operands);
-	while(filterString[*pos] == '(') {
-		filter_pt child = filter_parseFilter(filterString, pos);
-		if(child == NULL){
-			failure = true;
-			break;
-		}
-		arrayList_add(operands, child);
-	}
-
-	if(failure == true){
-		array_list_iterator_pt listIt = arrayListIterator_create(operands);
-		while(arrayListIterator_hasNext(listIt)){
-			filter_pt f = arrayListIterator_next(listIt);
-			filter_destroy(f);
-		}
-		arrayListIterator_destroy(listIt);
-		arrayList_destroy(operands);
-		operands = NULL;
-	}
-
-	filter_pt filter = (filter_pt) malloc(sizeof(*filter));
-	filter->operand = OR;
-	filter->attribute = NULL;
-	filter->value = operands;
-
-	return filter;
-}
-
-static filter_pt filter_parseNot(char * filterString, int * pos) {
-	filter_pt child = NULL;
+static celix_filter_t * filter_parseNot(char * filterString, int * pos) {
+	celix_filter_t * child = NULL;
 	filter_skipWhiteSpace(filterString, pos);
 
 	if (filterString[*pos] != '(') {
@@ -252,16 +210,18 @@ static filter_pt filter_parseNot(char * filterString, int * pos) {
 
 	child = filter_parseFilter(filterString, pos);
 
+    array_list_t* children = NULL;
+    arrayList_create(&children);
+    arrayList_add(children, child);
 
-	filter_pt filter = (filter_pt) malloc(sizeof(*filter));
-	filter->operand = NOT;
-	filter->attribute = NULL;
-	filter->value = child;
+	celix_filter_t * filter = (celix_filter_t *) calloc(1, sizeof(*filter));
+	filter->operand = CELIX_FILTER_OPERAND_NOT;
+	filter->children = children;
 
 	return filter;
 }
 
-static filter_pt filter_parseItem(char * filterString, int * pos) {
+static celix_filter_t * filter_parseItem(char * filterString, int * pos) {
 	char * attr = filter_parseAttr(filterString, pos);
 	if(attr == NULL){
 		return NULL;
@@ -271,9 +231,9 @@ static filter_pt filter_parseItem(char * filterString, int * pos) {
 	switch(filterString[*pos]) {
 		case '~': {
 			if (filterString[*pos + 1] == '=') {
-				filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+				celix_filter_t * filter = (celix_filter_t *) calloc(1, sizeof(*filter));
 				*pos += 2;
-				filter->operand = APPROX;
+				filter->operand = CELIX_FILTER_OPERAND_APPROX;
 				filter->attribute = attr;
 				filter->value = filter_parseValue(filterString, pos);
 				return filter;
@@ -282,17 +242,17 @@ static filter_pt filter_parseItem(char * filterString, int * pos) {
 		}
 		case '>': {
 			if (filterString[*pos + 1] == '=') {
-				filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+				celix_filter_t * filter = (celix_filter_t *) calloc(1, sizeof(*filter));
 				*pos += 2;
-				filter->operand = GREATEREQUAL;
+				filter->operand = CELIX_FILTER_OPERAND_GREATEREQUAL;
 				filter->attribute = attr;
 				filter->value = filter_parseValue(filterString, pos);
 				return filter;
 			}
 			else {
-                filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+                celix_filter_t * filter = (celix_filter_t *) calloc(1, sizeof(*filter));
                 *pos += 1;
-                filter->operand = GREATER;
+                filter->operand = CELIX_FILTER_OPERAND_GREATER;
                 filter->attribute = attr;
                 filter->value = filter_parseValue(filterString, pos);
                 return filter;
@@ -301,17 +261,17 @@ static filter_pt filter_parseItem(char * filterString, int * pos) {
 		}
 		case '<': {
 			if (filterString[*pos + 1] == '=') {
-				filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+				celix_filter_t * filter = (celix_filter_t *) calloc(1, sizeof(*filter));
 				*pos += 2;
-				filter->operand = LESSEQUAL;
+				filter->operand = CELIX_FILTER_OPERAND_LESSEQUAL;
 				filter->attribute = attr;
 				filter->value = filter_parseValue(filterString, pos);
 				return filter;
 			}
 			else {
-                filter_pt filter = (filter_pt) malloc(sizeof(*filter));
+                celix_filter_t * filter = (celix_filter_t *) calloc(1, sizeof(*filter));
                 *pos += 1;
-                filter->operand = LESS;
+                filter->operand = CELIX_FILTER_OPERAND_LESS;
                 filter->attribute = attr;
                 filter->value = filter_parseValue(filterString, pos);
                 return filter;
@@ -319,29 +279,29 @@ static filter_pt filter_parseItem(char * filterString, int * pos) {
 			break;
 		}
 		case '=': {
-			filter_pt filter = NULL;
+			celix_filter_t * filter = NULL;
 			array_list_pt subs;
 			if (filterString[*pos + 1] == '*') {
 				int oldPos = *pos;
 				*pos += 2;
 				filter_skipWhiteSpace(filterString, pos);
 				if (filterString[*pos] == ')') {
-					filter_pt filter = (filter_pt) malloc(sizeof(*filter));
-					filter->operand = PRESENT;
+					celix_filter_t * filter = (celix_filter_t *) calloc(1, sizeof(*filter));
+					filter->operand = CELIX_FILTER_OPERAND_PRESENT;
 					filter->attribute = attr;
 					filter->value = NULL;
 					return filter;
 				}
 				*pos = oldPos;
 			}
-			filter = (filter_pt) malloc(sizeof(*filter));			
+			filter = (celix_filter_t *) calloc(1, sizeof(*filter));			
 			(*pos)++;
 			subs = filter_parseSubstring(filterString, pos);
 			if(subs!=NULL){
 				if (arrayList_size(subs) == 1) {
 					char * string = (char *) arrayList_get(subs, 0);
 					if (string != NULL) {
-						filter->operand = EQUAL;
+						filter->operand = CELIX_FILTER_OPERAND_EQUAL;
 						filter->attribute = attr;
 						filter->value = string;
 
@@ -352,9 +312,9 @@ static filter_pt filter_parseItem(char * filterString, int * pos) {
 					}
 				}
 			}
-			filter->operand = SUBSTRING;
+			filter->operand = CELIX_FILTER_OPERAND_SUBSTRING;
 			filter->attribute = attr;
-			filter->value = subs;
+            filter->children = subs;
 			return filter;
 		}
 	}
@@ -388,7 +348,7 @@ static char * filter_parseAttr(char * filterString, int * pos) {
 		fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Missing attr.");
 		return NULL;
 	} else {
-		char * attr = (char *) malloc(length+1);
+		char * attr = (char *) calloc(1, length+1);
 		strncpy(attr, filterString+begin, length);
 		attr[length] = '\0';
 		return attr;
@@ -504,13 +464,13 @@ static array_list_pt filter_parseSubstring(char * filterString, int * pos) {
 	return operands;
 }
 
-celix_status_t filter_match(filter_pt filter, properties_pt properties, bool *result) {
+celix_status_t filter_match(celix_filter_t * filter, properties_pt properties, bool *result) {
 	switch (filter->operand) {
-		case AND: {
-			array_list_pt filters = (array_list_pt) filter->value;
+		case CELIX_FILTER_OPERAND_AND: {
+			array_list_pt children = filter->children;
 			unsigned int i;
-			for (i = 0; i < arrayList_size(filters); i++) {
-				filter_pt sfilter = (filter_pt) arrayList_get(filters, i);
+			for (i = 0; i < arrayList_size(children); i++) {
+				celix_filter_t * sfilter = (celix_filter_t *) arrayList_get(children, i);
 				bool mresult;
 				filter_match(sfilter, properties, &mresult);
 				if (!mresult) {
@@ -521,11 +481,11 @@ celix_status_t filter_match(filter_pt filter, properties_pt properties, bool *re
 			*result = 1;
 			return CELIX_SUCCESS;
 		}
-		case OR: {
-			array_list_pt filters = (array_list_pt) filter->value;
+		case CELIX_FILTER_OPERAND_OR: {
+			array_list_pt children = filter->children;
 			unsigned int i;
-			for (i = 0; i < arrayList_size(filters); i++) {
-				filter_pt sfilter = (filter_pt) arrayList_get(filters, i);
+			for (i = 0; i < arrayList_size(children); i++) {
+				celix_filter_t * sfilter = (celix_filter_t *) arrayList_get(children, i);
 				bool mresult;
 				filter_match(sfilter, properties, &mresult);
 				if (mresult) {
@@ -536,25 +496,25 @@ celix_status_t filter_match(filter_pt filter, properties_pt properties, bool *re
 			*result = 0;
 			return CELIX_SUCCESS;
 		}
-		case NOT: {
-			filter_pt sfilter = (filter_pt) filter->value;
+		case CELIX_FILTER_OPERAND_NOT: {
+			celix_filter_t * sfilter = arrayList_get(filter->children, 0);
 			bool mresult;
 			filter_match(sfilter, properties, &mresult);
 			*result = !mresult;
 			return CELIX_SUCCESS;
 		}
-		case SUBSTRING :
-		case EQUAL :
-		case GREATER :
-        case GREATEREQUAL :
-		case LESS :
-        case LESSEQUAL :
-		case APPROX : {
+		case CELIX_FILTER_OPERAND_SUBSTRING :
+		case CELIX_FILTER_OPERAND_EQUAL :
+		case CELIX_FILTER_OPERAND_GREATER :
+        case CELIX_FILTER_OPERAND_GREATEREQUAL :
+		case CELIX_FILTER_OPERAND_LESS :
+        case CELIX_FILTER_OPERAND_LESSEQUAL :
+		case CELIX_FILTER_OPERAND_APPROX : {
 			char * value = (properties == NULL) ? NULL: (char*)properties_get(properties, filter->attribute);
 
-			return filter_compare(filter->operand, value, filter->value, result);
+			return filter_compare(filter, value, result);
 		}
-		case PRESENT: {
+		case CELIX_FILTER_OPERAND_PRESENT: {
 			char * value = (properties == NULL) ? NULL: (char*)properties_get(properties, filter->attribute);
 			*result = value != NULL;
 			return CELIX_SUCCESS;
@@ -564,124 +524,165 @@ celix_status_t filter_match(filter_pt filter, properties_pt properties, bool *re
 	return CELIX_SUCCESS;
 }
 
-static celix_status_t filter_compare(OPERAND operand, char * string, void * value2, bool *result) {
-	if (string == NULL) {
-		*result = 0;
-		return CELIX_SUCCESS;
-	}
-	return filter_compareString(operand, string, value2, result);
-
-}
-
-static celix_status_t filter_compareString(OPERAND operand, char * string, void * value2, bool *result) {
-	switch (operand) {
-		case SUBSTRING: {
-			array_list_pt subs = (array_list_pt) value2;
-			int pos = 0;
-			unsigned int i;
-			int size = arrayList_size(subs);
-			for (i = 0; i < size; i++) {
-				char * substr = (char *) arrayList_get(subs, i);
-
-				if (i + 1 < size) {
-					if (substr == NULL) {
-						unsigned int index;
-						char * substr2 = (char *) arrayList_get(subs, i + 1);
-						if (substr2 == NULL) {
-							continue;
-						}
-						index = strcspn(string+pos, substr2);
-						if (index == strlen(string+pos)) {
-							*result = false;
-							return CELIX_SUCCESS;
-						}
-
-						pos = index + strlen(substr2);
-						if (i + 2 < size) {
-							i++;
-						}
-					} else {
-						unsigned int len = strlen(substr);
-						char * region = (char *)malloc(len+1);
-						strncpy(region, string+pos, len);
-						region[len]	= '\0';
-						if (strcmp(region, substr) == 0) {
-							pos += len;
-						} else {
-							free(region);
-							*result = false;
-							return CELIX_SUCCESS;
-						}
-						free(region);
-					}
-				} else {
-					unsigned int len;
-					int begin;
-
-					if (substr == NULL) {
-						*result = true;
-						return CELIX_SUCCESS;
-					}
-					len = strlen(substr);
-					begin = strlen(string)-len;
-					*result = (strcmp(string+begin, substr) == 0);
-					return CELIX_SUCCESS;
-				}
-			}
-			*result = true;
-			return CELIX_SUCCESS;
-		}
-		case APPROX: //TODO: Implement strcmp with ignorecase and ignorespaces
-		case EQUAL: {
-			*result = (strcmp(string, (char *) value2) == 0);
-			return CELIX_SUCCESS;
-		}
-		case GREATER: {
-			*result = (strcmp(string, (char *) value2) > 0);
-			return CELIX_SUCCESS;
-		}
-        case GREATEREQUAL: {
-            *result = (strcmp(string, (char *) value2) >= 0);
+static celix_status_t filter_compare(celix_filter_t* filter, const char *propertyValue, bool *out) {
+    celix_status_t  status = CELIX_SUCCESS;
+    bool result = false;
+
+    if (filter == NULL || propertyValue == NULL) {
+        *out = false;
+        return status;
+    }
+
+    switch (filter->operand) {
+        case CELIX_FILTER_OPERAND_SUBSTRING: {
+            int pos = 0;
+            unsigned int i;
+            int size = arrayList_size(filter->children);
+            for (i = 0; i < size; i++) {
+                char * substr = (char *) arrayList_get(filter->children, i);
+
+                if (i + 1 < size) {
+                    if (substr == NULL) {
+                        unsigned int index;
+                        char * substr2 = (char *) arrayList_get(filter->children, i + 1);
+                        if (substr2 == NULL) {
+                            continue;
+                        }
+                        index = strcspn(propertyValue+pos, substr2);
+                        if (index == strlen(propertyValue+pos)) {
+                            *out = false;
+                            return CELIX_SUCCESS;
+                        }
+
+                        pos = index + strlen(substr2);
+                        if (i + 2 < size) {
+                            i++;
+                        }
+                    } else {
+                        unsigned int len = strlen(substr);
+                        char * region = (char *)calloc(1, len+1);
+                        strncpy(region, propertyValue+pos, len);
+                        region[len]	= '\0';
+                        if (strcmp(region, substr) == 0) {
+                            pos += len;
+                        } else {
+                            free(region);
+                            *out = false;
+                            return CELIX_SUCCESS;
+                        }
+                        free(region);
+                    }
+                } else {
+                    unsigned int len;
+                    int begin;
+
+                    if (substr == NULL) {
+                        *out = true;
+                        return CELIX_SUCCESS;
+                    }
+                    len = strlen(substr);
+                    begin = strlen(propertyValue)-len;
+                    *out = (strcmp(propertyValue+begin, substr) == 0);
+                    return CELIX_SUCCESS;
+                }
+            }
+            *out = true;
             return CELIX_SUCCESS;
         }
-		case LESS: {
-			*result = (strcmp(string, (char *) value2) < 0);
-			return CELIX_SUCCESS;
-		}
-        case LESSEQUAL: {
-            *result = (strcmp(string, (char *) value2) <= 0);
+        case CELIX_FILTER_OPERAND_APPROX: //TODO: Implement strcmp with ignorecase and ignorespaces
+        case CELIX_FILTER_OPERAND_EQUAL: {
+            *out = (strcmp(propertyValue, filter->value) == 0);
             return CELIX_SUCCESS;
         }
-		case AND:
-		case NOT:
-		case OR:
-		case PRESENT: {
-		}
-		/* no break */
-	}
-	*result = false;
-	return CELIX_SUCCESS;
+        case CELIX_FILTER_OPERAND_GREATER: {
+            *out = (strcmp(propertyValue, filter->value) > 0);
+            return CELIX_SUCCESS;
+        }
+        case CELIX_FILTER_OPERAND_GREATEREQUAL: {
+            *out = (strcmp(propertyValue, filter->value) >= 0);
+            return CELIX_SUCCESS;
+        }
+        case CELIX_FILTER_OPERAND_LESS: {
+            *out = (strcmp(propertyValue, filter->value) < 0);
+            return CELIX_SUCCESS;
+        }
+        case CELIX_FILTER_OPERAND_LESSEQUAL: {
+            *out = (strcmp(propertyValue, filter->value) <= 0);
+            return CELIX_SUCCESS;
+        }
+        case CELIX_FILTER_OPERAND_AND:
+        case CELIX_FILTER_OPERAND_NOT:
+        case CELIX_FILTER_OPERAND_OR:
+        case CELIX_FILTER_OPERAND_PRESENT: {
+        }
+            /* no break */
+    }
+
+    if (status == CELIX_SUCCESS && out != NULL) {
+        *out = result;
+    }
+    return status;
 }
 
-celix_status_t filter_getString(filter_pt filter, const char **filterStr) {
+celix_status_t filter_getString(celix_filter_t * filter, const char **filterStr) {
 	if (filter != NULL) {
 		*filterStr = filter->filterStr;
 	}
 	return CELIX_SUCCESS;
 }
 
-celix_status_t filter_match_filter(filter_pt src, filter_pt dest, bool *result) {
-	char *srcStr = NULL;
-	char *destStr = NULL;
-	*result = false;
-
-	if (src) srcStr = src->filterStr;
-	if (dest) destStr = dest->filterStr;
+celix_status_t filter_match_filter(celix_filter_t *src, celix_filter_t *dest, bool *out) {
+    celix_status_t  status = CELIX_SUCCESS;
+	bool result = false;
+
+    if (src == dest) {
+        result = true; //NOTE. also means NULL filter are equal
+    } else if (src != NULL && dest != NULL && src->operand == dest->operand) {
+        if (src->operand == CELIX_FILTER_OPERAND_AND || src->operand == CELIX_FILTER_OPERAND_OR || src->operand == CELIX_FILTER_OPERAND_NOT) {
+            assert(src->children != NULL);
+            assert(dest->children != NULL);
+            int sizeSrc = arrayList_size(src->children);
+            int sizeDest = arrayList_size(dest->children);
+            if (sizeSrc == sizeDest) {
+                int i;
+                int k;
+                int sameCount = 0;
+                for (i =0; i < sizeSrc; ++i) {
+                    bool same = false;
+                    celix_filter_t *srcPart = arrayList_get(src->children, i);
+                    for (k = 0; k < sizeDest; ++k) {
+                        celix_filter_t *destPart = arrayList_get(dest->children, k);
+                        filter_match_filter(srcPart, destPart, &same);
+                        if (same) {
+                            sameCount += 1;
+                            break;
+                        }
+                    }
+                }
+                result = sameCount == sizeSrc;
+            }
+        } else { //compare attr and value
+            bool attrSame = false;
+            bool valSame = false;
+            if (src->attribute == NULL && dest->attribute == NULL) {
+                attrSame = true;
+            } else if (src->attribute != NULL && dest->attribute != NULL) {
+                attrSame = strncmp(src->attribute, dest->attribute, 1024 * 1024) == 0;
+            }
+
+            if (src->value == NULL  && dest->value == NULL) {
+                valSame = true;
+            } else if (src->value != NULL && dest->value != NULL) {
+                valSame = strncmp(src->value, dest->value, 1024 * 1024) == 0;
+            }
+
+            result = attrSame && valSame;
+        }
+    }
 
-	if ((srcStr != NULL) && (destStr != NULL)) {
-		// TODO: should be done smarted, e.g. src="&(a=1)(b=2)" and dest="&(b=2)(a=1)" should result in true
-		*result = (strcmp(srcStr, destStr) == 0);
-	}
+    if (status == CELIX_SUCCESS && out != NULL) {
+        *out = result;
+    }
 
-	return CELIX_SUCCESS;
+	return status;
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/f4cd9838/framework/src/filter_private.h
----------------------------------------------------------------------
diff --git a/framework/src/filter_private.h b/framework/src/filter_private.h
deleted file mode 100644
index d19de2d..0000000
--- a/framework/src/filter_private.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you 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.
- */
-/*
- * filter_private.h
- *
- *  \date       Feb 13, 2013
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
-
-
-#ifndef FILTER_PRIVATE_H_
-#define FILTER_PRIVATE_H_
-
-#include "filter.h"
-#include "array_list.h"
-
-typedef enum operand
-{
-	EQUAL,
-	APPROX,
-	GREATER,
-    GREATEREQUAL,
-	LESS,
-	LESSEQUAL,
-	PRESENT,
-	SUBSTRING,
-	AND,
-	OR,
-	NOT,
-} OPERAND;
-
-struct filter {
-	OPERAND operand;
-	char * attribute;
-	void * value;
-	char *filterStr;
-};
-
-
-#endif /* FILTER_PRIVATE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/f4cd9838/utils/include/array_list.h
----------------------------------------------------------------------
diff --git a/utils/include/array_list.h b/utils/include/array_list.h
index 4f83a45..c816c3d 100644
--- a/utils/include/array_list.h
+++ b/utils/include/array_list.h
@@ -36,8 +36,10 @@ extern "C" {
 #endif
 
 typedef struct arrayList *array_list_pt;
+typedef struct arrayList array_list_t;
 
 typedef struct arrayListIterator *array_list_iterator_pt;
+typedef struct arrayListIterator array_list_iterator_t;
 
 typedef celix_status_t (*array_list_element_equals_pt)(const void *, const void *, bool *equals);