View Javadoc

1   /*-
2    * #%L
3    * prolobjectlink-jpi
4    * %%
5    * Copyright (C) 2012 - 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.BufferedReader;
29  import java.io.IOException;
30  import java.io.Reader;
31  import java.io.StringReader;
32  import java.util.Map;
33  import java.util.Map.Entry;
34  
35  import javax.script.AbstractScriptEngine;
36  import javax.script.Bindings;
37  import javax.script.ScriptContext;
38  import javax.script.ScriptEngine;
39  import javax.script.ScriptEngineFactory;
40  import javax.script.ScriptException;
41  import javax.script.SimpleBindings;
42  
43  /**
44   * Partial implementation of {@link ScriptEngine}
45   * 
46   * @author Jose Zalacain
47   * @since 1.0
48   */
49  public final class PrologScriptEngine extends AbstractScriptEngine implements ScriptEngine {
50  
51  	private final PrologEngine prolog;
52  	private final ScriptEngineFactory factory;
53  
54  	PrologScriptEngine(ScriptEngineFactory factory, PrologEngine prolog) {
55  		this.factory = factory;
56  		this.prolog = prolog;
57  	}
58  
59  	public Bindings createBindings() {
60  		return new SimpleBindings();
61  	}
62  
63  	public ScriptEngineFactory getFactory() {
64  		return factory;
65  	}
66  
67  	public Object eval(String script, ScriptContext context) throws ScriptException {
68  		return eval(script, context.getBindings(ScriptContext.ENGINE_SCOPE));
69  	}
70  
71  	public Object eval(Reader reader, ScriptContext context) throws ScriptException {
72  		return eval(reader, context.getBindings(ScriptContext.ENGINE_SCOPE));
73  	}
74  
75  	@Override
76  	public Object eval(Reader reader, Bindings bindings) throws ScriptException {
77  		BufferedReader bfr = new BufferedReader(reader);
78  		StringBuilder script = new StringBuilder();
79  		try {
80  			String line = bfr.readLine();
81  			while (line != null) {
82  				script.append(line);
83  				script.append("\n");
84  				line = bfr.readLine();
85  			}
86  		} catch (IOException ex) {
87  			throw new ScriptException(ex);
88  		}
89  		return eval("" + script + "", bindings);
90  	}
91  
92  	@Override
93  	public Object eval(String script, Bindings bindings) throws ScriptException {
94  
95  		String code = script;
96  
97  		// check code goal to query
98  		if (code.startsWith("?-")) {
99  
100 			// replace all bindings
101 			for (Entry<String, Object> entry : bindings.entrySet()) {
102 				code = code.replace(entry.getKey(), "" + entry.getValue() + "");
103 			}
104 
105 			code = code.substring(2).trim();
106 
107 			// remove dot at the end if needed
108 			if (code.endsWith(".")) {
109 				code = code.substring(0, code.length() - 1);
110 			}
111 
112 			PrologQuery query = prolog.query(code);
113 			if (!query.hasSolution()) {
114 				return false;
115 			}
116 
117 			// set variables result in the binding map
118 			Map<String, Object> map = query.oneVariablesResult();
119 			for (Entry<String, Object> entry : map.entrySet()) {
120 				put(entry.getKey(), entry.getValue());
121 			}
122 
123 		}
124 
125 		// code is prolog program
126 		// code need ensure_loaded
127 		else {
128 			prolog.include(new StringReader(code));
129 		}
130 
131 		return true;
132 
133 	}
134 
135 	@Override
136 	public Object eval(String string) throws ScriptException {
137 		return eval(string, getContext());
138 	}
139 
140 	@Override
141 	public Object eval(Reader reader) throws ScriptException {
142 		return eval(reader, getContext());
143 	}
144 
145 	public PrologProvider getProvider() {
146 		return prolog.getProvider();
147 	}
148 
149 }