1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package io.github.prolobjectlink.prolog.jpl7;
30
31 import java.util.AbstractSet;
32 import java.util.Iterator;
33 import java.util.LinkedHashMap;
34 import java.util.LinkedList;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38
39 import org.jpl7.Term;
40
41 import io.github.prolobjectlink.prolog.ArrayIterator;
42 import io.github.prolobjectlink.prolog.PrologClauses;
43 import io.github.prolobjectlink.prolog.PrologError;
44
45
46
47
48
49
50 final class JplProgram extends AbstractSet<List<Term>> {
51
52
53 private final JplParser parser = new JplParser();
54
55
56 private final List<Term> goals = new LinkedList<Term>();
57
58
59 private final List<Term> directives = new LinkedList<Term>();
60
61
62 private final LinkedHashMap<String, List<Term>> clauses = new LinkedHashMap<String, List<Term>>();
63
64 private String getKey(Term clause) {
65 String key = clause.name();
66 key += "/" + clause.arity();
67 if (key.equals(":-/2")) {
68 key = clause.arg(1).name();
69 key += "/";
70 key += clause.arg(1).arity();
71 }
72 return key;
73 }
74
75 private String getKey(List<Term> cls) {
76 String msg = "Empty clause list";
77 if (!cls.isEmpty()) {
78 Term t = cls.get(0);
79 String key = t.name();
80 key += "/" + t.arity();
81 return key;
82 }
83 throw new PrologError(msg);
84 }
85
86 public List<Term> get(String key) {
87 return clauses.get(key);
88 }
89
90 public void add(Term clause) {
91 String key = getKey(clause);
92 List<Term> family = get(key);
93 if (family == null) {
94 family = new LinkedList<Term>();
95 family.add(clause);
96 clauses.put(key, family);
97 } else if (!family.contains(clause)) {
98 family.add(clause);
99 }
100 }
101
102 @Override
103 public boolean add(List<Term> cls) {
104 String key = getKey(cls);
105 List<Term> family = get(key);
106 if (family != null) {
107 family.addAll(cls);
108 } else {
109 clauses.put(key, cls);
110 }
111 return true;
112 }
113
114 public void add(JplProgram program) {
115 goals.addAll(program.getGoals());
116 clauses.putAll(program.getClauses());
117 directives.addAll(program.getDirectives());
118 }
119
120 @Override
121 public boolean remove(Object o) {
122
123 if (o instanceof Term) {
124 Term c = (Term) o;
125 String key = getKey(c);
126 List<Term> family = get(key);
127 if (family != null) {
128 return family.remove(c);
129 }
130 }
131
132 else if (o instanceof PrologClauses) {
133 PrologClauses cs = (PrologClauses) o;
134 String key = cs.getIndicator();
135 List<Term> oldFamily = clauses.remove(key);
136 return oldFamily != null;
137 }
138
139 return false;
140 }
141
142 public boolean remove(Term o) {
143
144 if (o instanceof Term) {
145 String key = getKey(o);
146 List<Term> family = get(key);
147 if (family != null) {
148 return family.remove(o);
149 }
150 }
151
152 return false;
153 }
154
155 public void push(Term clause) {
156 String key = getKey(clause);
157 List<Term> family = clauses.remove(key);
158 List<Term> cs = new LinkedList<Term>();
159 if (family != null && !family.contains(clause)) {
160 cs.add(clause);
161 for (Term term : family) {
162 cs.add(term);
163 }
164 } else {
165 cs.add(clause);
166 }
167 clauses.put(key, cs);
168 }
169
170 public void removeAll(String key) {
171 clauses.remove(key);
172 }
173
174 public void removeAll(String functor, int arity) {
175 removeAll(functor + "/" + arity);
176 }
177
178 public List<Term> getDirectives() {
179 return directives;
180 }
181
182 public boolean addDirective(Term directive) {
183 return directives.add(directive);
184 }
185
186 public boolean removeDirective(Term directive) {
187 return directives.remove(directive);
188 }
189
190 public List<Term> getGoals() {
191 return goals;
192 }
193
194 public boolean addGoal(Term goal) {
195 return goals.add(goal);
196 }
197
198 public boolean removeGoal(Term goal) {
199 return goals.remove(goal);
200 }
201
202 public Set<String> getIndicators() {
203 return clauses.keySet();
204 }
205
206 public Map<String, List<Term>> getClauses() {
207 return clauses;
208 }
209
210 @Override
211 public String toString() {
212
213 StringBuilder families = new StringBuilder();
214
215 if (!directives.isEmpty()) {
216 Iterator<Term> i = directives.iterator();
217 while (i.hasNext()) {
218 families.append(":-");
219 families.append(i.next());
220 families.append('.');
221 families.append(i.hasNext() ? "\n" : "\n\n");
222 }
223 }
224
225 if (!clauses.isEmpty()) {
226 Iterator<List<Term>> i = iterator();
227 while (i.hasNext()) {
228 List<Term> l = i.next();
229 Iterator<Term> j = l.iterator();
230 while (j.hasNext()) {
231 Term term = j.next();
232 String key = term.name();
233 key += "/" + term.arity();
234 if (term.arity() == 2 && key.equals(":-/2")) {
235 Term h = term.arg(1);
236 Term b = term.arg(2);
237 families.append(h);
238 families.append(" :- ");
239 families.append('\n');
240 families.append('\t');
241 Term[] array = parser.parseTerms(b);
242 Iterator<Term> k = new ArrayIterator<Term>(array);
243 while (k.hasNext()) {
244 Term item = k.next();
245 families.append(item);
246 if (k.hasNext()) {
247 families.append(',');
248 families.append('\n');
249 families.append('\t');
250 }
251 }
252 } else {
253 families.append(term);
254 }
255 families.append('.');
256 families.append('\n');
257 }
258 if (i.hasNext()) {
259 families.append('\n');
260 }
261 }
262 }
263
264 return "" + families + "";
265 }
266
267 @Override
268 public Iterator<List<Term>> iterator() {
269 return clauses.values().iterator();
270 }
271
272 @Override
273 public int size() {
274 int size = 0;
275 Iterator<List<Term>> i = iterator();
276 while (i.hasNext()) {
277 List<Term> l = i.next();
278 Iterator<Term> j = l.iterator();
279 while (j.hasNext()) {
280 j.next();
281 size++;
282 }
283 }
284 return size;
285 }
286
287 @Override
288 public void clear() {
289 goals.clear();
290 clauses.clear();
291 directives.clear();
292 }
293
294 @Override
295 public int hashCode() {
296 final int prime = 31;
297 int result = super.hashCode();
298 result = prime * result + clauses.hashCode();
299 result = prime * result + directives.hashCode();
300 result = prime * result + goals.hashCode();
301 return result;
302 }
303
304 @Override
305 public boolean equals(Object obj) {
306 if (this == obj)
307 return true;
308 if (!super.equals(obj))
309 return false;
310 if (getClass() != obj.getClass())
311 return false;
312 JplProgram other = (JplProgram) obj;
313 if (!clauses.equals(other.clauses)) {
314 return false;
315 }
316 if (!directives.equals(other.directives)) {
317 return false;
318 }
319 return goals.equals(other.goals);
320 }
321
322 }