capture
[rrq/gorite.git] / com / intendico / data / addon / TextQueryCapability.java
1 /*********************************************************************
2 Copyright 2012, Ralph Ronnquist.
3
4 This file is part of GORITE.
5
6 GORITE is free software: you can redistribute it and/or modify it
7 under the terms of the Lesser GNU General Public License as published
8 by the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 GORITE is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14 License for more details.
15
16 You should have received a copy of the Lesser GNU General Public
17 License along with GORITE.  If not, see <http://www.gnu.org/licenses/>.
18 **********************************************************************/
19
20 package com.intendico.data.addon;
21
22 import com.intendico.data.*;
23 import com.intendico.gorite.addon.Reflector;
24 import com.intendico.gorite.*;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.Observer;
28 import java.util.Vector;
29
30 /**
31  * This is a Capability extension that offers the use of predicates in
32  * text form using the language defined by the {@link Language}
33  * grammar.
34  *
35  * <p> The method {@link #textQuery(Data,String)} is used for
36  * immediate {@link com.intendico.data.Query Query} construction,
37  * which is suitable for the {@link Plan#context(Data)}
38  * implementations. The following is an illustration of its use:
39  *
40  * <pre>
41  * addGoal( new Plan( ... ) {
42  *     public Query context(Data d) {
43  *         return <b>textQuery</b>( d, "And( foo( 45, $x ), bar( $x ) )" );
44  *     }
45  * } );
46  * </pre>
47  *
48  * <p> The method {@link #addRule(String)} provides a deferred {@link
49  * Rule} installation from a text form rule. The following is an
50  * illustration of its use:
51  *
52  * <pre>
53  * addRule( "Lost primary($a,$b,$c) => secondary($a,$c)" );
54  * </pre>
55  *
56  * <p> The method {@link #addReflector(String,String,String)} provides
57  * a deferred {@link Reflector} installation with a text form
58  * query. The following is an illustration of its use:
59  *
60  * <pre>
61  * addReflector( "secondary lost", "percept","Lost secondary($a,$c)" );
62  * </pre>
63  *
64  * The deferred declarations are processed and installed by the first
65  * invokation of the {@link Capability#shareInquirables(Collection)}
66  * method, when all the inquirables have been shared. In that way the
67  * text form references get resolved to actual relations when
68  * translated into the actual {@link Query} or {@link Rule} structure.
69  *
70  * <p> Note that more arbitrary conditions in text form predicates
71  * need to be supported by appropriate {@link Inquirable}
72  * implementations.  For example, the following could be a way to
73  * define a computed "greater" relation between Integer values:
74  *
75  * <pre>
76  * putInquirable( new Inquirable() {
77  *     public String getName() { return "greater"; }
78  *     public Query get(final Object [] args) {
79  *         return new Condition() {
80  *             public boolean condition() {
81  *                 int a = ((Integer) Ref.deref( args[0] )).intValue();
82  *                 int b = ((Integer) Ref.deref( args[1] )).intValue();
83  *                 return a > b;
84  *             }
85  *         };
86  *     }
87  * } );
88  * </pre>
89  *
90  * @see Language
91  */
92 public class TextQueryCapability extends Capability {
93
94     /**
95      * Adds a textual rule definition. {@link Rule} creation is set up
96      * to be deferred until after the first {@link
97      * Capability#shareInquirables} invocation.
98      */
99     public void addRule(final String rule) {
100         add( new Deferred() {
101             /**
102              * Installs this as a proper {@link Reflector}.
103              */
104             public void install() {
105                 Vector/*<Query>*/ q =
106                     Language.textToRule( rule, getInquirables().values() );
107                 addRule( (Query) q.get( 0 ), (Query) q.get( 1 ) );
108             }
109         } );
110     }
111
112     /**
113      * Utility method to declare a {@link Reflector} for the owner
114      * {@link Performer} using a text form query. This is deferred to
115      * after the first {@link Capability#shareInquirables(Collection)}
116      * as needed.
117      */
118     public void addReflector(
119         final String goal,final String todo,final String query) {
120         add( new Deferred() {
121             /**
122              * Installs this as a proper {@link Reflector}.
123              */
124             public void install() {
125                 Reflector r = new Reflector( getPerformer(), goal, todo );
126                 r.addQuery( Language.textToQuery(
127                                 query,
128                                 getInquirables().values(), null, null ),
129                             goal );
130             }
131         } );
132     }
133
134     /**
135      * Utility method that creates a {@link Query} by resolving to the
136      * {@link Capability#inquirables} and the given {@link Data} context.
137      * Note that using this method before inquirables are shared, or more
138      * specifically if relation names are undefined, may result in an
139      * {@link Error}. Further, if the method returns null if the
140      * predicate is not parsable.
141      */
142     public Query textQuery(Data data,String predicate) {
143         return Language.textToQuery(
144             predicate, getInquirables().values(), null, data );
145     }
146
147 }