Project

General

Profile

1
package eu.dnetlib.utils.cql;
2

    
3
import java.util.ArrayList;
4
import java.util.List;
5

    
6
/**
7
 * @author stoumpos
8
 * 
9
 */
10
public class CqlQuery {
11

    
12
	CqlClause root = null;
13

    
14
	CqlQuery() {
15
		this(null);
16
	}
17

    
18
	CqlQuery(CqlClause root) {
19
		this.root = root;
20
	}
21

    
22
	public CqlClause getRoot() {
23
		return root;
24
	}
25

    
26
	public void setRoot(CqlClause root) {
27
		this.root = root;
28
	}
29

    
30
	@Override
31
	public String toString() {
32
		return (root == null) ? "null" : root.toCqlString();
33
	}
34

    
35

    
36
	/**
37
	 * Return <code>true</code> if this query is a superset of
38
	 * <code>query</code>, otherwise <code>false</code>.
39
	 */
40
	public boolean contains(CqlQuery query) {
41
		return contains(root, query.getRoot());
42
	}
43
	
44
	private boolean contains(CqlClause big, CqlClause small) {
45
		
46
		if (big.type ==  CqlClause.CqlClauseType.BOOLEAN && small.type ==  CqlClause.CqlClauseType.BOOLEAN) {
47
			return containsBooleans((CqlBoolean) big, (CqlBoolean) small);
48
		
49
		} else if (big.type ==  CqlClause.CqlClauseType.BOOLEAN) {
50
			// small is either term or relation
51
			return containsBooleanTerm((CqlBoolean) big, small);
52
			
53
		} else if (small.type ==  CqlClause.CqlClauseType.BOOLEAN) {
54
			// big is either term or relation
55
			return containsTermBoolean(big, (CqlBoolean) small);
56
			
57
		} else if (big.type == CqlClause.CqlClauseType.RELATION && small.type == CqlClause.CqlClauseType.RELATION) {
58
			CqlRelation bigRelation = (CqlRelation) big;
59
			CqlRelation smallRelation = (CqlRelation) small;
60
			return bigRelation.index.equals(smallRelation.index)
61
				&& bigRelation.operator.equals(smallRelation.operator)
62
				&& bigRelation.value.equals(smallRelation.value);
63
			
64
		} else if (big.type == CqlClause.CqlClauseType.TERM && small.type == CqlClause.CqlClauseType.TERM) {
65
			return ((CqlTerm) big).term.equals(((CqlTerm) small).term);
66
		}
67
				
68
		return false;
69
	}
70

    
71
	private boolean containsBooleans(CqlBoolean a, CqlBoolean b) {
72
		if (a.getOperator().equalsIgnoreCase(b.getOperator())) {
73
			
74
			ArrayList<CqlClause> aList = unfold(a);
75
			ArrayList<CqlClause> bList = unfold(b);
76
			
77
			if (a.operator.equalsIgnoreCase("and")) {
78
				return subset(aList, bList);
79
				
80
			} else if (a.operator.equalsIgnoreCase("or")) {
81
				return superset(bList, aList);
82
				
83
			} else {
84
				throw new IllegalArgumentException(
85
						"Unsupported operator: " + a.operator);
86
			}
87
			
88
		} else {
89
			return contains(a, b.getLeft()) && contains(a, b.getRight());
90
				
91
		}
92
	}
93
	
94
	public ArrayList<CqlClause> unfold(CqlBoolean bool) {
95
		
96
		String op = bool.operator;
97
		ArrayList<CqlClause> siblings = new ArrayList<CqlClause>();
98
		
99
		if (bool.left.type == CqlClause.CqlClauseType.BOOLEAN
100
				&& ((CqlBoolean) bool.left).operator.equalsIgnoreCase(op)) {
101
			siblings.addAll(unfold((CqlBoolean) bool.left));
102
		} else {
103
			siblings.add(bool.left);
104
		}
105
		
106
		if (bool.right.type == CqlClause.CqlClauseType.BOOLEAN
107
				&& ((CqlBoolean) bool.right).operator.equalsIgnoreCase(op)) {
108
			siblings.addAll(unfold((CqlBoolean) bool.right));
109
		} else {
110
			siblings.add(bool.right);
111
		}
112
		
113
		return siblings;
114
	}
115

    
116
	
117
	private boolean superset(List<CqlClause> superset, List<CqlClause> subset) {
118
		if (subset.size() > superset.size()) {
119
			return false;
120
		}
121
		for (CqlClause sub : subset) {
122
			boolean found = false;
123
			for (CqlClause sup : superset) {
124
				if (contains(sup, sub)) {
125
					found = true;
126
					break;
127
				}
128
			}
129
			if (!found) {
130
				return false;
131
			}
132
		}
133
		return true;
134
	}
135

    
136
	private boolean subset(List<CqlClause> subset, List<CqlClause> superset) {
137
		if (subset.size() > superset.size()) {
138
			return false;
139
		}
140
		for (CqlClause sub : subset) {
141
			boolean found = false;
142
			for (CqlClause sup : superset) {
143
				if (contains(sub, sup)) {
144
					found = true;
145
					break;
146
				}
147
			}
148
			if (!found) {
149
				return false;
150
			}
151
		}
152
		return true;
153
	}
154

    
155
	private boolean containsBooleanTerm(CqlBoolean bool, CqlClause clause) {
156

    
157
		if (bool.getOperator().equalsIgnoreCase("and")) {
158
			// warn: assume clause is either term or relation
159
			return false;
160
		}
161
		
162
		return contains(bool.getLeft(), clause)
163
				|| contains(bool.getRight(), clause);
164
	}
165
	
166
	private boolean containsTermBoolean(CqlClause clause, CqlBoolean bool) {
167
		
168
		if (bool.getOperator().equalsIgnoreCase("or")) {
169
			// warn: assume clause is either term or relation
170
			return false;
171
		}
172
		
173
		return contains(clause, bool.getLeft())
174
				|| contains(clause, bool.getRight());
175
	}
176
}
(7-7/10)