1 /* 2 * #%L 3 * prolobjectlink-jpi 4 * %% 5 * Copyright (C) 2019 Prolobjectlink Project 6 * %% 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 * #L% 25 */ 26 package io.github.prolobjectlink.prolog; 27 28 import java.io.Reader; 29 import java.io.Writer; 30 import java.util.List; 31 import java.util.Map; 32 import java.util.Set; 33 34 /** 35 * A PrologEngine instance is used in order to interact with the concrete prolog 36 * engine. Is used for interact with the Prolog database or to invoke a built-in 37 * predicate. It is initialized using a provider instance and calling new engine 38 * {@link PrologProvider#newEngine()} 39 * 40 * <pre> 41 * PrologProvider provider = Prolog.getProvider(Some_PrologProvider_Impl.class); 42 * PrologEngine engine = provider.newEngine(); 43 * </pre> 44 * 45 * The {@link PrologProvider#newEngine(String)} method is used if the specified 46 * file to consult is provided. 47 * 48 * The prolog engine have a life cycle on the user application. After create an 49 * instance we can consult any file with prolog programs using 50 * {@link #consult(Reader)} or {@link #consult(String)}. If another prolog file 51 * need to be include in main memory we can use {@link #include(Reader)} or 52 * {@link #include(String)}. We can include so much files as we needed. 53 * 54 * <pre> 55 * engine.consult("family.pl"); 56 * engine.include("company.pl"); 57 * engine.include("zoo.pl"); 58 * </pre> 59 * 60 * To check if the given goal have solution using the resolution engine 61 * mechanism we can use {@link #contains(String)} or 62 * {@link #contains(PrologTerm, PrologTerm...)}. Both methods returning true if 63 * the given goal have solution or false in other case. 64 * 65 * <pre> 66 * boolean b = engine.clause("parent( pam, bob)"); 67 * </pre> 68 * 69 * To check if there are a clause in the prolog engine we can use 70 * {@link #clause(String)} or {@link #clause(PrologTerm, PrologTerm...)}. This 71 * methods is based on the prolog engine built-in clause/2 that check if in the 72 * currents predicates exist a clause definition that match with the given 73 * clause. This methods return true if the given clause is defined in the prolog 74 * engine or false in other case. The following cases return true. 75 * 76 * <pre> 77 * engine.assertz("parent( pam, bob)"); 78 * boolean b = engine.clause("parent( X, Y); 79 * boolean t = engine.clause("parent( pam, bob)") 80 * </pre> 81 * 82 * Java Prolog Interface have an special interface to query to prolog engine 83 * about some specific clauses an operate over solution set. {@link PrologQuery} 84 * is the mechanism to query the prolog database loaded in prolog engine. The 85 * way to create a new prolog query is invoking 86 * {@link PrologEngine#query(String)}, 87 * {@link PrologEngine#query(PrologTerm, PrologTerm...)} or 88 * {@link PrologEngine#query(PrologTerm[])}. This interface have several methods 89 * to obtain one, at least N or all query results. 90 * 91 * <pre> 92 * PrologEngine engine = provider.newEngine("zoo.pl"); 93 * PrologVariable x = provider.newVariable("X", 0); 94 * PrologQuery query = engine.query(provider.newStructure("dark", x)); 95 * List<Object> solution = query.oneResult(); 96 * for (int i = 0; i < solution.size(); i++) { 97 * System.out.println(solution.get(i)); 98 * } 99 * </pre> 100 * 101 * Java Prolog Interface have shortcuts methods to obtain queries result from 102 * the engine. The shortcuts methods to obtain one result are 103 * {@link PrologEngine#queryOne(PrologTerm)}, 104 * {@link PrologEngine#queryOne(String)}, 105 * {@link PrologEngine#queryOne(PrologTerm, PrologTerm...)}. This methods are 106 * equivalent to call {@code PrologEngine.query(...).oneVariablesResult()}. 107 * 108 * queryN 109 * 110 * The shortcuts methods to obtain all results are 111 * {@link PrologEngine#queryAll(PrologTerm)}, 112 * {@link PrologEngine#queryAll(String)}, 113 * {@link PrologEngine#queryAll(PrologTerm, PrologTerm...)}. This methods are 114 * equivalent to call {@code PrologEngine.query(...).allVariablesResult()}. 115 * 116 * After create an empty prolog engine and load any prolog program, we can 117 * modify the program/database. For this propose we have the methods 118 * {@link #asserta(String)}, {@link #asserta(PrologTerm,PrologTerm...)} or 119 * {@link #assertz(String)}, {@link #assertz(PrologTerm,PrologTerm...)}. The 120 * asserta methods are used when we need store a prolog clause term on top in 121 * the clause family and assertz by other hand, are when we need store a prolog 122 * clause term on the tail in the clause family. 123 * 124 * <pre> 125 * engine.asserta("grandparent(X,Z):-parent(X,Y),parent(Y,Z)"); 126 * engine.asserta("parent( pat, jim)"); 127 * </pre> 128 * 129 * <pre> 130 * engine.assertz("parent( pat, jim)"); 131 * engine.assertz("grandparent(X,Z):-parent(X,Y),parent(Y,Z)"); 132 * </pre> 133 * 134 * For remove clauses in the main memory program if the clause exist can be used 135 * {@link #retract(String)} or {@link #retract(PrologTerm, PrologTerm...)}. Both 136 * methods after build internal clause representation find the specific clause 137 * and if this exist remove it. By other hand if we need remove all clause 138 * family we can use {@link #abolish(String, int)}. This method remove all 139 * predicates that match with the predicate indicator (PI) formed by the 140 * concatenation of the given string functor and integer arity separated by 141 * slash (functor/arity). 142 * 143 * <pre> 144 * engine.retract("parent( tom, bob)"); 145 * </pre> 146 * 147 * <pre> 148 * engine.abolish("parent", 2); 149 * </pre> 150 * 151 * All change that take place in the current engine can save to some specific 152 * file using {@link #persist(String)} or {@link #persist(Writer)}. 153 * 154 * <pre> 155 * engine.assertz(provider.newStructure("parent", pam, bob)); 156 * engine.assertz(provider.newStructure("parent", tom, bob)); 157 * engine.assertz(provider.newStructure("parent", tom, liz)); 158 * engine.assertz(provider.newStructure("parent", bob, ann)); 159 * engine.assertz(provider.newStructure("parent", bob, pat)); 160 * engine.assertz(provider.newStructure("parent", pat, jim)); 161 * 162 * engine.persist("family.pl"); 163 * </pre> 164 * 165 * By the last {@link #dispose()} clear program in main memory. Release all 166 * resources used and prepare the current engine for realize some new task. 167 * 168 * <pre> 169 * engine.dispose(); 170 * </pre> 171 * 172 * An additional capability of the prolog engine is the {@link Iterable} 173 * implementation. This allow to prolog engine iterate over all user defined 174 * clauses using a for-each loop or iterator loop. 175 * 176 * <pre> 177 * for (PrologClause c : engine) { 178 * // do something 179 * } 180 * </pre> 181 * 182 * <pre> 183 * Iterator<?> i = engine.iterator(); 184 * while (i.hasNext()) { 185 * // do something 186 * } 187 * </pre> 188 * 189 * The shortcuts methods to obtain N results are 190 * 191 * {@code PrologEngine.queryN(Class)}, {@code PrologEngine.queryN(Object)}, 192 * {@code PrologEngine.queryN(PrologTerm)}, {@code PrologEngine.queryN(String)}, 193 * {@code PrologEngine.queryN(Class, Class...)}, 194 * {@code PrologEngine.queryN(Object, Object...)}, 195 * {@code PrologEngine.queryN(PrologTerm, PrologTerm...)}. 196 * 197 * This methods are equivalent to call 198 * {@code PrologEngine.query(...).nVariablesResult()}. 199 * 200 * Java Prolog Interface have shortcuts methods to obtain queries result from 201 * the engine. The shortcuts methods to obtain one result are 202 * {@code PrologEngine.queryOne(Class)}, {@code PrologEngine.queryOne(Object)}, 203 * {@code PrologEngine.queryOne(PrologTerm)}, 204 * {@code PrologEngine.queryOne(String)}, 205 * {@code PrologEngine.queryOne(Class, Class...)}, 206 * {@code PrologEngine.queryOne(Object, Object...)}, 207 * {@code PrologEngine.queryOne(PrologTerm, PrologTerm...)}. This methods are 208 * equivalent to call {@code PrologEngine.query(...).oneVariablesResult()}. 209 * 210 * The shortcuts methods to obtain N results are 211 * {@code PrologEngine.queryN(Class)}, {@code PrologEngine.queryN(Object)}, 212 * {@code PrologEngine.queryN(PrologTerm)}, {@code PrologEngine.queryN(String)}, 213 * {@code PrologEngine.queryN(Class, Class...)}, 214 * {@code PrologEngine.queryN(Object, Object...)}, 215 * {@code PrologEngine.queryN(PrologTerm, PrologTerm...)}. This methods are 216 * equivalent to call {@code PrologEngine.query(...).nVariablesResult()}. 217 * 218 * The shortcuts methods to obtain all results are 219 * {@code PrologEngine.queryAll(Class)}, {@code PrologEngine.queryAll(Object)}, 220 * {@code PrologEngine.queryAll(PrologTerm)}, 221 * {@code PrologEngine.queryAll(String)}, 222 * {@code PrologEngine.queryAll(Class, Class...)}, 223 * {@code PrologEngine.queryAll(Object, Object...)}, 224 * {@code PrologEngine.queryAll(PrologTerm, PrologTerm...)}. This methods are 225 * equivalent to call {@code PrologEngine.query(...).allVariablesResult()}. 226 * 227 * 228 * 229 * 230 * @author Jose Zalacain 231 * @since 1.0 232 */ 233 public interface PrologEngine extends Iterable<PrologClause> { 234 235 /** 236 * Check if the host operating system name refer to Windows OS. 237 * 238 * @return true if the host operating system name refer to Windows OS and false 239 * otherwise. 240 * @since 1.0 241 */ 242 public boolean runOnWindows(); 243 244 /** 245 * Check if the host operating system name refer to Linux OS. 246 * 247 * @return true if the host operating system name refer to Linux OS and false 248 * otherwise. 249 * @since 1.0 250 */ 251 public boolean runOnLinux(); 252 253 /** 254 * Check if the host operating system name refer to OsX. 255 * 256 * @return true if the host operating system name refer to OsX and false 257 * otherwise. 258 * @since 1.0 259 */ 260 public boolean runOnOSX(); 261 262 /** 263 * Return the host operating system name. Is a shortcut to 264 * {@code System.getProperty("os.name");}. 265 * 266 * @return the host operating system name. 267 * @since 1.0 268 */ 269 public String getOSName(); 270 271 /** 272 * Return the host operating system version. Is a shortcut to 273 * {@code System.getProperty("os.version");}. 274 * 275 * @return the host operating system version. 276 * @since 1.1 277 */ 278 public String getOSVersion(); 279 280 /** 281 * Return the host operating system architecture. Is a shortcut to 282 * {@code System.getProperty("os.arch");}. 283 * 284 * @return the host operating system architecture. 285 * @since 1.0 286 */ 287 public String getOSArch(); 288 289 /** 290 * Test the correct integration between under-laying prolog engine and top level 291 * interface. Return a string list with the needed conditions to link the 292 * under-laying prolog engine. if the under-laying prolog engine is linked the 293 * returned set only contain the "OK" string indicating a correct integration. 294 * 295 * @return string list with only "OK" string if the prolog engine integration is 296 * correct or the conditions string list needed to link the prolog 297 * engine. 298 * @since 1.0 299 */ 300 public List<String> verify(); 301 302 /** 303 * Consult a file specified by the string path loading an parsing the prolog 304 * program. If the prolog program contains syntax error a syntax exception 305 * should be raised. 306 * 307 * @param path location of the file to be consulted 308 * @since 1.0 309 */ 310 public void consult(String path); 311 312 /** 313 * Consult a prolog program from specified reader parsing the prolog program and 314 * put this program into prolog engine. If the prolog program contains syntax 315 * error a syntax exception should be raised. 316 * 317 * @param reader The reader to read the prolog program from character streams 318 * @since 1.0 319 */ 320 public void consult(Reader reader); 321 322 /** 323 * Consult a file specified by the string path loading an parsing the prolog 324 * program and include the loaded program into current engine. If the prolog 325 * program contains syntax error a syntax exception should be raised. 326 * 327 * @param path location of the file to be included 328 * @since 1.0 329 */ 330 public void include(String path); 331 332 /** 333 * Consult a prolog program from specified reader parsing the prolog program and 334 * include this program into current prolog engine. If the prolog program 335 * contains syntax error a syntax exception should be raised. 336 * 337 * @param reader The reader to read the prolog program from character streams 338 * @since 1.0 339 */ 340 public void include(Reader reader); 341 342 /** 343 * Save the prolog program present in the current engine to some specific file 344 * specified by string path. 345 * 346 * @param path location of the file. 347 * @since 1.0 348 */ 349 public void persist(String path); 350 351 /** 352 * Write the prolog clauses in program present in the current engine using the 353 * given driver. 354 * 355 * @param writer writer for write prolog clauses in the program. 356 * @since 1.0 357 */ 358 public void persist(Writer writer); 359 360 /** 361 * Remove all predicates that match with the predicate indicator (PI) formed by 362 * the concatenation of the given string functor and integer arity separated by 363 * slash (functor/arity). 364 * 365 * <pre> 366 * engine.abolish("parent", 2); // remove all parent/2 predicates 367 * </pre> 368 * 369 * @param functor string functor that identify the predicate family to be 370 * remove. 371 * @param arity argument number that identify the predicate family to be 372 * remove. 373 * @since 1.0 374 */ 375 public void abolish(String functor, int arity); 376 377 /** 378 * Parse the string creating internal prolog clause and add the clause in the 379 * main memory program if the clause non exist. If the clause exist, will not 380 * overwritten and the clause will not added. The string have prolog fact or 381 * rule syntax. The added clause will be the first clause for a clause lot with 382 * the same predicate indicator (PI). 383 * 384 * <pre> 385 * engine.asserta("grandparent(X,Z):-parent(X,Y),parent(Y,Z)"); 386 * engine.asserta("parent( pat, jim)"); 387 * engine.asserta("parent( bob, pat)"); 388 * engine.asserta("parent( bob, ann)"); 389 * engine.asserta("parent( tom, liz)"); 390 * engine.asserta("parent( tom, bob)"); 391 * engine.asserta("parent( pam, bob)"); 392 * </pre> 393 * 394 * @param stringClause - string for create internal prolog clause 395 * @since 1.0 396 */ 397 public void asserta(String stringClause); 398 399 /** 400 * Create internal prolog clause and add the clause in the main memory program 401 * if the clause non exist. If the clause exist, will not overwritten and the 402 * clause will not added. The added clause will be the first clause for a clause 403 * lot with the same predicate indicator (PI). 404 * 405 * @param term term to be added 406 * @since 1.1 407 */ 408 public void asserta(PrologTerm term); 409 410 /** 411 * Add a rule specified by the rule head and rule body if the specified rule 412 * clause non exist. If the rule clause exist, will not overwritten and the 413 * clause will not added. The head term is the first argument and the body is 414 * constituted by the terms array followed of the rule head. If the body array 415 * is empty the clause will be considered like fact specified by head only. The 416 * added clause will be the first clause for a clause lot with the same 417 * predicate indicator (PI). The shared variables in the clause are declared 418 * once and use for build the terms that conform the clause to be added 419 * 420 * <pre> 421 * String parent = "parent"; 422 * String grandparent = "grandparent"; 423 * 424 * PrologAtom pam = provider.newAtom("pam"); 425 * PrologAtom bob = provider.newAtom("bob"); 426 * PrologAtom ann = provider.newAtom("ann"); 427 * PrologAtom pat = provider.newAtom("pat"); 428 * 429 * PrologVariable x = provider.newVariable("X"); 430 * PrologVariable y = provider.newVariable("Y"); 431 * PrologVariable z = provider.newVariable("Z"); 432 * 433 * engine.asserta(provider.newStructure(grandparent, x, z), provider.newStructure(parent, x, y), 434 * provider.newStructure(parent, y, z)); 435 * engine.asserta(provider.newStructure(parent, pat, jim)); 436 * engine.asserta(provider.newStructure(parent, bob, pat)); 437 * engine.asserta(provider.newStructure(parent, bob, ann)); 438 * engine.asserta(provider.newStructure(parent, tom, liz)); 439 * engine.asserta(provider.newStructure(parent, tom, bob)); 440 * engine.asserta(provider.newStructure(parent, pam, bob)); 441 * </pre> 442 * 443 * @param head head of rule 444 * @param body array of terms that compound the body of the rule 445 * @since 1.0 446 */ 447 public void asserta(PrologTerm head, PrologTerm... body); 448 449 /** 450 * Parse the string creating internal prolog clause and add the clause in the 451 * main memory program if the clause non exist. If the clause exist, will not 452 * overwritten and the clause will not added. The string have prolog fact or 453 * rule syntax. The added clause will be the last clause for a clause lot with 454 * the same predicate indicator (PI). 455 * 456 * <pre> 457 * engine.assertz("parent( pam, bob)"); 458 * engine.assertz("parent( tom, bob)"); 459 * engine.assertz("parent( tom, liz)"); 460 * engine.assertz("parent( bob, ann)"); 461 * engine.assertz("parent( bob, pat)"); 462 * engine.assertz("parent( pat, jim)"); 463 * engine.assertz("grandparent(X,Z):-parent(X,Y),parent(Y,Z)"); 464 * </pre> 465 * 466 * @param stringClause string clause to be added 467 * @since 1.0 468 */ 469 public void assertz(String stringClause); 470 471 /** 472 * Create internal prolog clause and add the clause in the main memory program 473 * if the clause non exist. If the clause exist, will not overwritten and the 474 * clause will not added. The added clause will be the last clause for a clause 475 * lot with the same predicate indicator (PI). 476 * 477 * @param term term to be added 478 * @since 1.1 479 */ 480 public void assertz(PrologTerm term); 481 482 /** 483 * <p> 484 * Add a rule specified by the rule head and rule body if the specified rule 485 * clause non exist. If the rule clause exist, will not overwritten and the 486 * clause will not added. The head term is the first argument and the body is 487 * constituted by the terms array followed of the rule head. If the body array 488 * is empty the clause will be considered like fact specified by head only. The 489 * added clause will be the last clause for a clause lot with the same predicate 490 * indicator (PI). The shared variables in the clause are declared once and use 491 * for build the terms that conform the clause to be added 492 * </p> 493 * 494 * <pre> 495 * String parent = "parent"; 496 * String grandparent = "grandparent"; 497 * PrologAtom pam = provider.newAtom("pam"); 498 * PrologAtom bob = provider.newAtom("bob"); 499 * PrologAtom ann = provider.newAtom("ann"); 500 * PrologAtom pat = provider.newAtom("pat"); 501 * PrologVariable x = provider.newVariable("X"); 502 * PrologVariable y = provider.newVariable("Y"); 503 * PrologVariable z = provider.newVariable("Z"); 504 * engine.assertz(provider.newStructure(parent, pam, bob)); 505 * engine.assertz(provider.newStructure(parent, tom, bob)); 506 * engine.assertz(provider.newStructure(parent, tom, liz)); 507 * engine.assertz(provider.newStructure(parent, bob, ann)); 508 * engine.assertz(provider.newStructure(parent, bob, pat)); 509 * engine.assertz(provider.newStructure(parent, pat, jim)); 510 * engine.assertz(provider.newStructure(grandparent, x, z), provider.newStructure(parent, x, y), 511 * provider.newStructure(parent, y, z)); 512 * </pre> 513 * 514 * @param head head of rule 515 * @param body array of terms that compound the body of the rule 516 * @since 1.0 517 */ 518 public void assertz(PrologTerm head, PrologTerm... body); 519 520 /** 521 * Parse the string creating internal prolog clause and returning true if the 522 * clause in the main memory program unify with the given clause. If the clause 523 * not exist in main memory program or exist but not unify with the given clause 524 * false value is returned. The string have prolog fact or rule syntax. 525 * 526 * <pre> 527 * boolean b = engine.clause("parent( pam, bob)"); 528 * </pre> 529 * 530 * <pre> 531 * boolean b = engine.clause("grandparent(X,Z):-parent(X,Y),parent(Y,Z)"); 532 * </pre> 533 * 534 * @param stringClause string clause to be match 535 * @return true if the clause in the main memory program unify with the given 536 * clause, false otherwise 537 * @since 1.0 538 */ 539 public boolean clause(String stringClause); 540 541 /** 542 * Find a rule specified by the rule head and rule body in main memory program 543 * that unify with the given clause returning true in this case.If the clause 544 * not exist in main memory program or exist but not unify with the given clause 545 * false value is returned. The shared variables in the clause are declared once 546 * and use for build the terms that conform the clause to be found. 547 * 548 * @param term term to be match with some clause in main memory program 549 * @return true if the clause in the main memory program unify with the clause 550 * equivalent to the given term, false otherwise 551 * @since 1.1 552 */ 553 public boolean clause(PrologTerm term); 554 555 /** 556 * Find a rule specified by the rule head and rule body in main memory program 557 * that unify with the given clause returning true in this case.If the clause 558 * not exist in main memory program or exist but not unify with the given clause 559 * false value is returned. The head term is the first argument and the body is 560 * constituted by the terms array followed of the rule head. If the body array 561 * is empty the clause will be considered like fact specified by head only. The 562 * shared variables in the clause are declared once and use for build the terms 563 * that conform the clause to be found. 564 * 565 * <pre> 566 * String parent = "parent"; 567 * PrologAtom pam = provider.newAtom("pam"); 568 * PrologAtom bob = provider.newAtom("bob"); 569 * boolean b = engine.clause(provider.newStructure(parent, pam, bob)); 570 * </pre> 571 * 572 * <pre> 573 * String grandparent = "grandparent"; 574 * PrologVariable x = provider.newVariable("X"); 575 * PrologVariable y = provider.newVariable("Y"); 576 * PrologVariable z = provider.newVariable("Z"); 577 * boolean b = engine.clause(provider.newStructure(grandparent, x, z), provider.newStructure(parent, x, y), 578 * provider.newStructure(parent, y, z)); 579 * </pre> 580 * 581 * @param head head of rule 582 * @param body array of terms that compound the body of the rule 583 * @return true if the clause in the main memory program unify with the given 584 * clause, false otherwise 585 * @since 1.0 586 */ 587 public boolean clause(PrologTerm head, PrologTerm... body); 588 589 /** 590 * Parse the string creating internal prolog clause and remove the clause in the 591 * main memory program if the clause exist. The string have prolog fact or rule 592 * syntax. 593 * 594 * <pre> 595 * engine.retract("parent( pam, bob)."); 596 * engine.retract("parent( tom, bob)."); 597 * engine.retract("parent( tom, liz)."); 598 * engine.retract("parent( bob, ann)."); 599 * engine.retract("parent( bob, pat)."); 600 * engine.retract("parent( pat, jim)."); 601 * engine.retract("grandparent(X,Z):-parent(X,Y),parent(Y,Z)"); 602 * </pre> 603 * 604 * @param stringClause string clause to be removed 605 * @since 1.0 606 */ 607 public void retract(String stringClause); 608 609 /** 610 * Remove a fact specified by the head if the specified fact clause exist. The 611 * shared variables in the clause are declared once and use for build the terms 612 * that conform the clause to be removed. 613 * 614 * @param term fact to be removed 615 * @since 1.1 616 */ 617 public void retract(PrologTerm term); 618 619 /** 620 * Remove a rule specified by the rule head and rule body if the specified rule 621 * clause exist. The head term is the first argument and the body is constituted 622 * by the terms array followed of the rule head. If the body array is empty the 623 * clause will be considered like fact specified by head only. The shared 624 * variables in the clause are declared once and use for build the terms that 625 * conform the clause to be removed. 626 * 627 * <pre> 628 * String parent = "parent"; 629 * String grandparent = "grandparent"; 630 * PrologAtom pam = provider.newAtom("pam"); 631 * PrologAtom bob = provider.newAtom("bob"); 632 * PrologAtom ann = provider.newAtom("ann"); 633 * PrologAtom pat = provider.newAtom("pat"); 634 * PrologVariable x = provider.newVariable("X"); 635 * PrologVariable y = provider.newVariable("Y"); 636 * PrologVariable z = provider.newVariable("Z"); 637 * engine.retract(provider.newStructure(parent, pam, bob)); 638 * engine.retract(provider.newStructure(parent, tom, bob)); 639 * engine.retract(provider.newStructure(parent, tom, liz)); 640 * engine.retract(provider.newStructure(parent, bob, ann)); 641 * engine.retract(provider.newStructure(parent, bob, pat)); 642 * engine.retract(provider.newStructure(parent, pat, jim)); 643 * engine.retract(provider.newStructure(grandparent, x, z), provider.newStructure(parent, x, y), 644 * provider.newStructure(parent, y, z)); 645 * </pre> 646 * 647 * @param head head of rule 648 * @param body array of terms that compound the body of the rule 649 * @since 1.0 650 */ 651 public void retract(PrologTerm head, PrologTerm... body); 652 653 /** 654 * Check that two terms (x and y) unify. Prolog unification algorithm is based 655 * on three principals rules: 656 * <ul> 657 * <li>If x and y are atomics constants then x and y unify only if they are same 658 * object.</li> 659 * <li>If x is a variable and y is anything then they unify and x is 660 * instantiated to y. Conversely, if y is a variable then this is instantiated 661 * to x.</li> 662 * <li>If x and y are structured terms then unify only if they match (equals 663 * funtor and arity) and all their correspondents arguments unify.</li> 664 * </ul> 665 * 666 * 667 * @param t1 the term to unify. 668 * @param t2 the term to unify. 669 * @return true if the specified term unify whit the current term, false 670 * otherwise. 671 * @since 1.0 672 */ 673 public boolean unify(PrologTerm t1, PrologTerm t2); 674 675 /** 676 * Match to other term returning list of substitutions. Used to compute the most 677 * general unifier. 678 * 679 * @param t1 the term to unify. 680 * @param t2 the term to unify. 681 * @return true if the specified term unify whit the current term, false 682 * otherwise. 683 * @since 1.2 684 */ 685 public Map<String, PrologTerm> match(PrologTerm t1, PrologTerm t2); 686 687 /** 688 * Parse the string creating internal prolog clause and returning true if the 689 * given goal have solution using the resolution engine mechanism. If wrapped 690 * engine not support a dedicated method then contains can be defined like 691 * 692 * {@code query(goal).hasSolution()} 693 * 694 * @param goal goal to be queried 695 * @return true if the given goal has solution 696 * @since 1.0 697 */ 698 public boolean contains(String goal); 699 700 /** 701 * Check if the given goal array have solution using the resolution engine 702 * mechanism. If wrapped engine not support a dedicated method then contains can 703 * be defined like: 704 * 705 * {@code query(goal).hasSolution()} 706 * 707 * @param goal goal to be checked 708 * @return true if the given goal has solution 709 * @since 1.1 710 */ 711 public boolean contains(PrologTerm goal); 712 713 /** 714 * Check if the given goal array have solution using the resolution engine 715 * mechanism. If wrapped engine not support a dedicated method then contains can 716 * be defined like: 717 * 718 * {@code query(goal).hasSolution()} 719 * 720 * @param goal goal to be checked 721 * @param goals goals array with the rest of conjunctive goals term (can be 722 * empty) 723 * @return true if the given goal has solution 724 * @since 1.0 725 */ 726 public boolean contains(PrologTerm goal, PrologTerm... goals); 727 728 /** 729 * Create a new query being the goal the given string with prolog syntax. The 730 * query creation process call the wrapped prolog engine and after query 731 * creation the query instance is ready to use. This particular query method can 732 * raise an syntax exception if the string query have prolog errors. 733 * 734 * <pre> 735 * PrologQuery query = engine.query("parent(X, Y)"); 736 * </pre> 737 * 738 * @param query string goal with prolog syntax. 739 * @return a new query instance. 740 * @since 1.0 741 */ 742 public PrologQuery query(String query); 743 744 /** 745 * 746 * @param goal 747 * @return 748 * @since 1.1 749 */ 750 public PrologQuery query(PrologTerm goal); 751 752 /** 753 * Create a new query being the goal the given prolog term array. The given 754 * array is treated like a conjunctive goal and after success the first element 755 * the next term will be resolved. The query creation process call the wrapped 756 * prolog engine and after query creation the query instance is ready to use. 757 * 758 * <pre> 759 * PrologTerm x = provider.newVariable("X", 0); 760 * PrologTerm dark = provider.newStructure("dark", x); 761 * PrologTerm big = provider.newStructure("big", x); 762 * PrologTerm[] goals = new PrologTerm[] { dark, big }; 763 * PrologQuery query = engine.query(goals); 764 * </pre> 765 * 766 * @param terms prolog term array to be query. 767 * @return a new query instance. 768 * @since 1.0 769 */ 770 public PrologQuery query(PrologTerm[] terms); 771 772 /** 773 * Create a new query with at least one prolog term goal. The rest terms are 774 * treated like a conjunctive goal and after success the first element the next 775 * term will be resolved. The query creation process call the wrapped prolog 776 * engine and after query creation the query instance is ready to use. 777 * 778 * <pre> 779 * PrologTerm x = provider.newVariable("X", 0); 780 * PrologTerm dark = provider.newStructure("dark", x); 781 * PrologTerm big = provider.newStructure("big", x); 782 * PrologQuery query = engine.query(dark, big); 783 * </pre> 784 * 785 * @param term prolog term to be query 786 * @param terms prolog term array to be query. 787 * @return a new query instance. 788 * @since 1.0 789 */ 790 public PrologQuery query(PrologTerm term, PrologTerm... terms); 791 792 /** 793 * Create a new prolog query and return the prolog terms that conform the 794 * solution set for the current query. The solution set is a prolog terms map 795 * and every map entry is a pair variable name and variable instance value for 796 * the variables not anonymous involved in the query. 797 * 798 * <pre> 799 * List<Map<String, PrologTerm>> m = engine.queryAll("parent(X, Y)"); 800 * </pre> 801 * 802 * @param goal string query with prolog format. 803 * @return variable name - variable instance (key - value) map that conform the 804 * solution set for the current query. 805 * @since 1.0 806 */ 807 public Map<String, PrologTerm> queryOne(String goal); 808 809 /** 810 * 811 * @param goal 812 * @return 813 * @since 1.1 814 */ 815 public Map<String, PrologTerm> queryOne(PrologTerm goal); 816 817 /** 818 * Create a new prolog query and return the prolog terms that conform the 819 * solution set for the current query. The solution set is a prolog terms map 820 * and every map entry is a pair variable name and variable instance value for 821 * the variables not anonymous involved in the query. 822 * 823 * <pre> 824 * PrologVariable x = provider.newVariable("X", 0); 825 * PrologVariable y = provider.newVariable("Y", 1); 826 * Map<String, PrologTerm> m = engine.queryOne(provider.newStructure("parent", x, y)); 827 * </pre> 828 * 829 * @param term prolog term to be query 830 * @param terms prolog term array to be query. 831 * @return variable name - variable instance (key - value) map that conform the 832 * solution set for the current query. 833 * @since 1.0 834 */ 835 public Map<String, PrologTerm> queryOne(PrologTerm term, PrologTerm... terms); 836 837 /** 838 * Create a new prolog query and return the list of (N) prolog terms that 839 * conform the solution set for the current query. Each list item is a prolog 840 * terms map and every map entry is a pair variable name and variable instance 841 * value for the variables not anonymous involved in the query. 842 * 843 * @param n query result instance number 844 * @param goal string with prolog syntax to be query 845 * @return the list of prolog terms that conform the solution set for the 846 * current query. 847 * @since 1.0 848 */ 849 public List<Map<String, PrologTerm>> queryN(int n, String goal); 850 851 /** 852 * 853 * @param n 854 * @param goal 855 * @return 856 * @since 1.1 857 */ 858 public List<Map<String, PrologTerm>> queryN(int n, PrologTerm goal); 859 860 /** 861 * Create a new prolog query and return the list of (N) prolog terms that 862 * conform the solution set for the current query. Each list item is a prolog 863 * terms map and every map entry is a pair variable name and variable instance 864 * value for the variables not anonymous involved in the query. 865 * 866 * <pre> 867 * PrologVariable x = provider.newVariable("X", 0); 868 * PrologVariable y = provider.newVariable("Y", 1); 869 * List<Map<String, PrologTerm>> m = engine.queryN(5, provider.newStructure("parent", x, y)); 870 * </pre> 871 * 872 * @param n query result instance number 873 * @param term prolog term to be query 874 * @param terms prolog term array to be query. 875 * @return the list of prolog terms that conform the solution set for the 876 * current query. 877 * @since 1.0 878 */ 879 public List<Map<String, PrologTerm>> queryN(int n, PrologTerm term, PrologTerm... terms); 880 881 /** 882 * Create a new prolog query and return the list of prolog terms that conform 883 * the solution set for the current query. Each list item is a prolog terms map 884 * and every map entry is a pair variable name and variable instance value for 885 * the variables not anonymous involved in the query. 886 * 887 * @param goal string with prolog syntax to be query 888 * @return the list of prolog terms that conform the solution set for the 889 * current query. 890 * @since 1.0 891 */ 892 public List<Map<String, PrologTerm>> queryAll(String goal); 893 894 /** 895 * 896 * @param goal 897 * @return 898 * @since 1.1 899 */ 900 public List<Map<String, PrologTerm>> queryAll(PrologTerm goal); 901 902 /** 903 * Create a new prolog query and return the list of prolog terms that conform 904 * the solution set for the current query. Each list item is a prolog terms map 905 * and every map entry is a pair variable name and variable instance value for 906 * the variables not anonymous involved in the query. 907 * 908 * <pre> 909 * PrologVariable x = provider.newVariable("X", 0); 910 * PrologVariable y = provider.newVariable("Y", 1); 911 * List<Map<String, PrologTerm>> m = engine.queryAll(provider.newStructure("parent", x, y)); 912 * </pre> 913 * 914 * @param term prolog term to be query 915 * @param terms prolog term array to be query. 916 * @return the list of prolog terms that conform the solution set for the 917 * current query. 918 * @since 1.0 919 */ 920 public List<Map<String, PrologTerm>> queryAll(PrologTerm term, PrologTerm... terms); 921 922 /** 923 * Create a new clause builder instance to build prolog clauses 924 * programmatically. 925 * 926 * @return a new clause builder instance 927 * @since 1.0 928 */ 929 public PrologClauseBuilder newClauseBuilder(); 930 931 /** 932 * Create a new query builder instance to build prolog goal programmatically. 933 * 934 * @return a new query builder instance 935 * @since 1.0 936 */ 937 public PrologQueryBuilder newQueryBuilder(); 938 939 /** 940 * Define an operator in the wrapped prolog engine with priority between 0 and 941 * 1200 and associativity determined by specifier according to the table below 942 * 943 * <table BORDER > <caption>Specification table</caption> 944 * <tr> 945 * <td ALIGN=CENTER><b>Specifier</b></td> 946 * <td ALIGN=CENTER><b>Type</b></td> 947 * <td ALIGN=CENTER><b>Associativity</b></td> 948 * </tr> 949 * <tr> 950 * <td>fx</td> 951 * <td>prefix</td> 952 * <td>no</td> 953 * </tr> 954 * <tr> 955 * <td>fy</td> 956 * <td>prefix</td> 957 * <td>yes</td> 958 * </tr> 959 * <tr> 960 * <td>xf</td> 961 * <td>postfix</td> 962 * <td>no</td> 963 * </tr> 964 * <tr> 965 * <td>yf</td> 966 * <td>postfix</td> 967 * <td>yes</td> 968 * </tr> 969 * <tr> 970 * <td>xfx</td> 971 * <td>infix</td> 972 * <td>no</td> 973 * </tr> 974 * <tr> 975 * <td>yfx</td> 976 * <td>infix</td> 977 * <td>left</td> 978 * </tr> 979 * <tr> 980 * <td>xfy</td> 981 * <td>infix</td> 982 * <td>right</td> 983 * </tr> 984 * </table> 985 * 986 * @since 1.0 987 * @param priority operator priority between 0 and 1200 988 * @param specifier associative and position of the operator 989 * @param operator operator to be defined 990 */ 991 public void operator(int priority, String specifier, String operator); 992 993 /** 994 * Check if in the wrapped prolog engine is defined some particular predicate 995 * specified by your predicate indicator (PI = functor/arity). If the predicate 996 * is defined by prolog engine built-in or by user definition return true and 997 * false in other case. If wrapped engine not support a dedicated method the 998 * 999 * {@link #currentPredicate(String, int)} will be defined like 1000 * 1001 * {@code currentPredicates().contains(new PredicateIndicator(functor, arity));} 1002 * 1003 * @since 1.0 1004 * @param functor name of the predicate to be check. 1005 * @param arity argument number of the predicate to be check. 1006 * @return true in functor/arity predicate is defined and false otherwise. 1007 */ 1008 public boolean currentPredicate(String functor, int arity); 1009 1010 /** 1011 * Check if in the wrapped prolog engine is defined some particular operator 1012 * specified by your Priority, Specifier and Operator. If the operator is 1013 * defined by prolog engine built-in or by user definition return true or false 1014 * in other case. If wrapped engine not support a dedicated method the 1015 * 1016 * {@link #currentOperator(int, String, String)} 1017 * 1018 * will be defined like 1019 * 1020 * {@code currentOperators().contains(new PrologOperator(priority, specifier, operator));} 1021 * 1022 * @param priority operator priority between 0 and 1200 1023 * @param specifier associative and position of the operator 1024 * @param operator operator to be checked 1025 * @return true if the operator is defined by prolog engine built-in or by user 1026 * definition, false otherwise. 1027 * @since 1.0 1028 */ 1029 public boolean currentOperator(int priority, String specifier, String operator); 1030 1031 /** 1032 * Predicate set defined in the wrapped prolog engine. The predicate set will be 1033 * constituted by the supported built-ins predicate in the wrapped prolog engine 1034 * and user defined predicates present in the prolog program/database. More 1035 * formally current predicate set is defined by the union between user defined 1036 * predicates and prolog engine built-ins. 1037 * 1038 * <pre> 1039 * Set<PrologIndicator> cp = new HashSet<PrologIndicator>(); 1040 * cp.addAll(getPredicates()); 1041 * cp.addAll(getBuiltIns()); 1042 * </pre> 1043 * 1044 * @return Defined Predicate Set. 1045 * @since 1.0 1046 */ 1047 public Set<PrologIndicator> currentPredicates(); 1048 1049 /** 1050 * Operator set defined in the wrapped prolog engine. The operator set will be 1051 * constituted by the supported built-ins operator in the wrapped prolog engine 1052 * and user defined operators present in the prolog program/database. 1053 * 1054 * @return defined operator set. 1055 * @since 1.0 1056 */ 1057 public Set<PrologOperator> currentOperators(); 1058 1059 /** 1060 * Make and return a copy of the clause map present in the current engine. The 1061 * map key is a functor/arity string and the value is a prolog clause family 1062 * list. 1063 * 1064 * @return a clause map present in the current engine. 1065 * @since 1.0 1066 */ 1067 public Map<String, List<PrologClause>> getProgramMap(); 1068 1069 /** 1070 * Make and return a copy of the clause set present in the current engine. 1071 * 1072 * @return a clause set present in the current engine. 1073 * @since 1.0 1074 */ 1075 public Set<PrologClause> getProgramClauses(); 1076 1077 /** 1078 * Make and return a copy of the program. 1079 * 1080 * @return a program in the current engine. 1081 * @since 1.1 1082 */ 1083 public PrologProgram getProgram(); 1084 1085 /** 1086 * Number of clauses in the current engine. 1087 * 1088 * @return number of clauses in the engine. 1089 * @since 1.0 1090 */ 1091 public int getProgramSize(); 1092 1093 /** 1094 * Check if the program in main memory is empty returning true if the clause 1095 * number in the program is 0 and false in otherwise. If wrapped engine not 1096 * support a dedicated method {@link #isProgramEmpty()} will be defined like 1097 * {@code PrologEngine#getProgramSize()==0;}. 1098 * 1099 * @return true if the clause number in the program is 0 and false in otherwise. 1100 * @since 1.0 1101 */ 1102 public boolean isProgramEmpty(); 1103 1104 /** 1105 * User defined predicate set defined in the wrapped prolog engine. The 1106 * predicate set will be constituted by user defined predicates present in the 1107 * prolog program/database. The supported built-ins predicate in the wrapped 1108 * prolog engine not be include in this set. 1109 * 1110 * @return User Defined Predicate Set. 1111 * @since 1.0 1112 */ 1113 public Set<PrologIndicator> getPredicates(); 1114 1115 /** 1116 * Predicate set defined by the supported built-ins predicate in the wrapped 1117 * prolog engine. The user defined predicates in the wrapped prolog engine not 1118 * be include in this set. 1119 * 1120 * @return built-ins predicates set. 1121 * @since 1.0 1122 */ 1123 public Set<PrologIndicator> getBuiltIns(); 1124 1125 /** 1126 * Get a Prolog provider instance hold in the current engine. 1127 * 1128 * @return a Prolog provider instance. 1129 * @since 1.0 1130 */ 1131 public PrologProvider getProvider(); 1132 1133 /** 1134 * Get the prolog system logger instance to report any errors or exceptions 1135 * 1136 * @return prolog system logger instance 1137 * @since 1.0 1138 */ 1139 public PrologLogger getLogger(); 1140 1141 /** 1142 * License of the wrapped engine. 1143 * 1144 * @return String license of the wrapped engine. 1145 * @since 1.0 1146 */ 1147 public String getLicense(); 1148 1149 /** 1150 * Version of the wrapped engine. 1151 * 1152 * @return String version of the wrapped engine. 1153 * @since 1.0 1154 */ 1155 public String getVersion(); 1156 1157 /** 1158 * Under-laying engine vendor 1159 * 1160 * @return engine vendor 1161 * @since 1.1 1162 */ 1163 public String getVendor(); 1164 1165 /** 1166 * Name of the wrapped engine. 1167 * 1168 * @return String name of the wrapped engine. 1169 * @since 1.0 1170 */ 1171 public String getName(); 1172 1173 /** 1174 * Clear program in main memory. Release all resources used and prepare the 1175 * current engine for realize some new task. 1176 * 1177 * @since 1.0 1178 */ 1179 public void dispose(); 1180 1181 }