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 package io.github.prolobjectlink.prolog;
27
28 import java.util.ArrayList;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.NoSuchElementException;
32
33
34
35
36
37
38
39 public abstract class AbstractClause implements PrologClause {
40
41 private String see = "";
42 private String since = "";
43 private String author = "";
44 private String version = "";
45 private String description = "";
46
47 private boolean dynamic;
48 private boolean multifile;
49 private boolean discontiguous;
50
51 private final PrologTerm head;
52 private final PrologTerm body;
53
54 protected final PrologProvider provider;
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 protected AbstractClause(PrologProvider provider, PrologTerm head, boolean dynamic, boolean multifile,
70 boolean discontiguous) {
71 this(provider, head, null, dynamic, multifile, discontiguous);
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 protected AbstractClause(PrologProvider provider, PrologTerm head, PrologTerm body, boolean dynamic,
88 boolean multifile, boolean discontiguous) {
89 this.head = head;
90 this.body = body;
91 this.provider = provider;
92 this.dynamic = dynamic;
93 this.multifile = multifile;
94 this.discontiguous = discontiguous;
95 }
96
97 public PrologTerm getTerm() {
98 PrologTerm h = getHead();
99 if (isRule()) {
100 PrologTerm b = getBody();
101 return provider.newStructure(":-", h, b);
102 }
103 return h;
104 }
105
106 public final PrologTerm getHead() {
107 return head;
108 }
109
110 public final PrologTerm getBody() {
111 return body;
112 }
113
114 public final PrologTerm[] getBodyArray() {
115 PrologTerm ptr = getBody();
116 List<PrologTerm> terms = new ArrayList<PrologTerm>();
117 while (ptr != null && ptr.isCompound() && ptr.hasIndicator(",", 2)) {
118 terms.add(ptr.getArgument(0));
119 ptr = ptr.getArgument(1);
120 }
121 terms.add(ptr);
122 return terms.toArray(new PrologTerm[0]);
123 }
124
125 public final Iterator<PrologTerm> getBodyIterator() {
126 return new BodyIterator(getBodyArray());
127 }
128
129 public final String getFunctor() {
130 return head.getFunctor();
131 }
132
133 public final int getArity() {
134 return head.getArity();
135 }
136
137 public PrologTerm[] getArguments() {
138 return head.getArguments();
139 }
140
141 public PrologTerm getArgument(int index) {
142 return head.getArgument(index);
143 }
144
145 public final boolean hasIndicator(String functor, int arity) {
146 return getHead().hasIndicator(functor, arity);
147 }
148
149 public final String getIndicator() {
150 return head.getIndicator();
151 }
152
153 public final boolean isDirective() {
154 return head == null && body != null;
155 }
156
157 public final boolean isFact() {
158 return head != null && body == null;
159 }
160
161 public final boolean isRule() {
162 return head != null && body != null;
163 }
164
165 public boolean isMethod() {
166 return false;
167 }
168
169 public boolean isFunction() {
170 return false;
171 }
172
173 public final boolean isClause() {
174 return true;
175 }
176
177 public final boolean isTerm() {
178 return false;
179 }
180
181 public final boolean unify(PrologClause clause) {
182 return head.unify(clause.getHead()) && body.unify(clause.getBody());
183 }
184
185 public final boolean isDynamic() {
186 return dynamic;
187 }
188
189 public final boolean isMultifile() {
190 return multifile;
191 }
192
193 public final boolean isDiscontiguous() {
194 return discontiguous;
195 }
196
197 public PrologIndicator getPrologIndicator() {
198 return new DefaultPrologIndicator(getFunctor(), getArity());
199 }
200
201 public final <T extends PrologClause> T cast() {
202 return (T) this;
203 }
204
205 public final String getSee() {
206 return see;
207 }
208
209 public final void setSee(String see) {
210 this.see = see;
211 }
212
213 public final String getSince() {
214 return since;
215 }
216
217 public final void setSince(String since) {
218 this.since = since;
219 }
220
221 public final String getAuthor() {
222 return author;
223 }
224
225 public final void setAuthor(String author) {
226 this.author = author;
227 }
228
229 public final String getVersion() {
230 return version;
231 }
232
233 public final void setVersion(String version) {
234 this.version = version;
235 }
236
237 public final String getDescription() {
238 return description;
239 }
240
241 public final void setDescription(String description) {
242 this.description = description;
243 }
244
245 public final boolean hasDescription() {
246 return !getDescription().isEmpty();
247 }
248
249 public final boolean hasVersion() {
250 return !getVersion().isEmpty();
251 }
252
253 public final boolean hasAuthor() {
254 return !getAuthor().isEmpty();
255 }
256
257 public final boolean hasSince() {
258 return !getSince().isEmpty();
259 }
260
261 public final boolean hasSee() {
262 return !getSee().isEmpty();
263 }
264
265 public final boolean hasDocumentation() {
266 return hasDescription() || hasVersion() || hasAuthor() || hasSince() || hasSee();
267 }
268
269 @Override
270 public int hashCode() {
271 final int prime = 31;
272 int result = 1;
273 result = prime * result + ((author == null) ? 0 : author.hashCode());
274 result = prime * result + ((body == null) ? 0 : body.hashCode());
275 result = prime * result + ((description == null) ? 0 : description.hashCode());
276 result = prime * result + (discontiguous ? 1231 : 1237);
277 result = prime * result + (dynamic ? 1231 : 1237);
278 result = prime * result + ((head == null) ? 0 : head.hashCode());
279 result = prime * result + (multifile ? 1231 : 1237);
280 result = prime * result + ((see == null) ? 0 : see.hashCode());
281 result = prime * result + ((since == null) ? 0 : since.hashCode());
282 result = prime * result + ((version == null) ? 0 : version.hashCode());
283 return result;
284 }
285
286 @Override
287 public boolean equals(Object obj) {
288 if (this == obj)
289 return true;
290 if (obj == null)
291 return false;
292 if (getClass() != obj.getClass())
293 return false;
294 AbstractClause other = (AbstractClause) obj;
295 if (author == null) {
296 if (other.author != null)
297 return false;
298 } else if (!author.equals(other.author))
299 return false;
300 if (body == null) {
301 if (other.body != null)
302 return false;
303 } else if (!body.equals(other.body))
304 return false;
305 if (description == null) {
306 if (other.description != null)
307 return false;
308 } else if (!description.equals(other.description))
309 return false;
310 if (discontiguous != other.discontiguous)
311 return false;
312 if (dynamic != other.dynamic)
313 return false;
314 if (head == null) {
315 if (other.head != null)
316 return false;
317 } else if (!head.equals(other.head))
318 return false;
319 if (multifile != other.multifile)
320 return false;
321 if (see == null) {
322 if (other.see != null)
323 return false;
324 } else if (!see.equals(other.see))
325 return false;
326 if (since == null) {
327 if (other.since != null)
328 return false;
329 } else if (!since.equals(other.since))
330 return false;
331 if (version == null) {
332 if (other.version != null)
333 return false;
334 } else if (!version.equals(other.version))
335 return false;
336 return true;
337 }
338
339 @Override
340 public String toString() {
341 StringBuilder b = new StringBuilder();
342 if (hasDocumentation()) {
343 b.append("/*");
344 if (hasDescription()) {
345 b.append(getDescription());
346 b.append("\n");
347 }
348 if (hasVersion()) {
349 b.append(getVersion());
350 b.append("\n");
351 }
352 if (hasAuthor()) {
353 b.append(getAuthor());
354 b.append("\n");
355 }
356 if (hasSince()) {
357 b.append(getSince());
358 b.append("\n");
359 }
360 if (hasSee()) {
361 b.append(getSee());
362 b.append("\n");
363 }
364 b.append("*/");
365 }
366 b.append(getHead());
367 if (isRule()) {
368 b.append(":-\n\t");
369 Iterator<PrologTerm> i = getBodyIterator();
370 while (i.hasNext()) {
371 b.append(i.next());
372 if (i.hasNext()) {
373 b.append(",\n\t");
374 }
375 }
376 }
377 b.append('.');
378 return "" + b + "";
379 }
380
381 private class BodyIterator extends AbstractIterator<PrologTerm> implements Iterator<PrologTerm> {
382
383 private int nextIndex;
384
385 private final PrologTerm[] elements;
386
387 protected BodyIterator(PrologTerm[] elements) {
388 this.elements = elements;
389 }
390
391 public boolean hasNext() {
392 return nextIndex < elements.length;
393 }
394
395 public PrologTerm next() {
396 if (!hasNext()) {
397 throw new NoSuchElementException();
398 }
399 return elements[nextIndex++];
400 }
401
402 }
403
404 }