001 package net.sf.cpsolver.ifs.util;
002
003 import java.io.BufferedReader;
004 import java.io.FileReader;
005 import java.io.IOException;
006 import java.io.InputStreamReader;
007 import java.io.PrintWriter;
008 import java.io.Reader;
009 import java.util.ArrayList;
010 import java.util.Iterator;
011 import java.util.List;
012
013 /**
014 * A class for reading prolog files.
015 *
016 * @version IFS 1.2 (Iterative Forward Search)<br>
017 * Copyright (C) 2006 - 2010 Tomas Muller<br>
018 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
019 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
020 * <br>
021 * This library is free software; you can redistribute it and/or modify
022 * it under the terms of the GNU Lesser General Public License as
023 * published by the Free Software Foundation; either version 3 of the
024 * License, or (at your option) any later version. <br>
025 * <br>
026 * This library is distributed in the hope that it will be useful, but
027 * WITHOUT ANY WARRANTY; without even the implied warranty of
028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
029 * Lesser General Public License for more details. <br>
030 * <br>
031 * You should have received a copy of the GNU Lesser General Public
032 * License along with this library; if not see
033 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
034 */
035 public class PrologFile implements Iterator<PrologFile.Term> {
036 private BufferedReader iBufferedReader = null;
037 private Term iNextTerm = null;
038
039 public PrologFile(String file) throws java.io.IOException {
040 iBufferedReader = new BufferedReader(new FileReader(file));
041 iNextTerm = (iBufferedReader.ready() ? readTerm(new SpecialReader(iBufferedReader)) : null);
042 if (iNextTerm == null)
043 iBufferedReader.close();
044 else
045 iBufferedReader.readLine();
046 }
047
048 /** Reads a prolog file. It returns a set of terms */
049 public static List<Term> readTermsFromStream(java.io.InputStream is, String term) throws java.io.IOException {
050 BufferedReader br = new BufferedReader(new InputStreamReader(is));
051 List<Term> ret = new ArrayList<Term>();
052 // int x=0;
053 while (br.ready()) {
054 Term t = readTerm(new SpecialReader(br));
055 // System.out.println(t);
056 // x++;
057 // if (x>10) break;
058 if (t != null && t.getText() != null && t.getText().startsWith(term)) {
059 ret.add(t);
060 }
061 br.readLine();
062 }
063 br.close();
064 return ret;
065 }
066
067 /** Writes a set of terms. */
068 public static void writeTerms(PrintWriter pw, List<Term> terms) throws java.io.IOException {
069 for (Term t : terms) {
070 writeTerm(pw, t);
071 }
072 }
073
074 /** reads a term */
075 private static Term readTerm(SpecialReader is) throws IOException {
076 StringBuffer text = new StringBuffer();
077 List<Term> content = null;
078 int i;
079 if ((i = is.read()) >= 0) {
080 while ((char) i == '%' || (char) i == ':') {
081 do {
082 i = is.read();
083 } while (i >= 0 && !(i == 0x0d || i == 0x0a));
084 i = is.read();
085 if (i >= 0 && (i == 0x0d || i == 0x0a))
086 i = is.read();
087 }
088 if (i >= 0)
089 is.flush((char) i);
090 }
091 char prev = (char) i;
092 if (i >= 0)
093 while ((i = is.read()) >= 0) {
094 char ch = (char) i;
095 if (ch == '\n' || ch == '\r')
096 if (prev == '.')
097 break;
098 else
099 continue;
100 if (ch == '(' || ch == '[') {
101 content = new ArrayList<Term>();
102 content.add(readTerm(is));
103 } else if (content == null && (ch == ',' || ch == ')' || ch == ']')) {
104 is.flush(ch);
105 break;
106 } else if (ch == ',')
107 content.add(readTerm(is));
108 else if (ch == ')' || ch == ']')
109 break;
110 else
111 text.append(ch);
112 prev = ch;
113 }
114 else
115 return null;
116 Term ret = new Term(text.toString().trim(), content);
117 return ret;
118 }
119
120 /** writes a term */
121 private static void writeTerm(PrintWriter pw, Term t) {
122 pw.println(t.toString() + ".");
123 }
124
125 @Override
126 public boolean hasNext() {
127 return iNextTerm != null;
128 }
129
130 @Override
131 public Term next() {
132 Term ret = iNextTerm;
133 try {
134 iNextTerm = (iBufferedReader.ready() ? readTerm(new SpecialReader(iBufferedReader)) : null);
135 } catch (java.io.IOException x) {
136 iNextTerm = null;
137 }
138 try {
139 if (iNextTerm == null)
140 iBufferedReader.close();
141 else
142 iBufferedReader.readLine();
143 } catch (java.io.IOException x) {
144 }
145 return ret;
146 }
147
148 @Override
149 public void remove() {
150 }
151
152 /** Flushable reader -- extension of java.io.Reader */
153 private static class SpecialReader {
154 /** reader */
155 private Reader iReader = null;
156 /** flushed characters */
157 private StringBuffer iFlushedChars = new StringBuffer();
158
159 /** constructor */
160 public SpecialReader(Reader r) {
161 iReader = r;
162 }
163
164 /** reads a byte */
165 public int read() throws java.io.IOException {
166 if (iFlushedChars.length() == 0)
167 return iReader.read();
168 char ret = iFlushedChars.charAt(0);
169 iFlushedChars.deleteCharAt(0);
170 return ret;
171 }
172
173 /** flush (return to stream) a character */
174 public void flush(char ch) {
175 iFlushedChars.insert(0, ch);
176 }
177 }
178
179 /** Term -- it can contain a text and a content (set of terms) */
180 public static class Term {
181 /** text */
182 private String iText = null;
183 /** content */
184 private List<Term> iContent = null;
185
186 @Override
187 public boolean equals(Object o) {
188 if (o == null || !(o instanceof Term))
189 return false;
190 Term t = (Term) o;
191 if (iText == null && t.iText != null)
192 return false;
193 if (iText != null && t.iText == null)
194 return false;
195 if (iText != null && !iText.equals(t.iText))
196 return false;
197 if (iContent == null && t.iContent != null)
198 return false;
199 if (iContent != null && t.iContent == null)
200 return false;
201 if (iContent != null && !iContent.equals(t.iContent))
202 return false;
203 return true;
204 }
205
206 /** constructor */
207 public Term(String text) {
208 iText = text;
209 iContent = null;
210 }
211
212 /** constructor */
213 public Term(List<Term> content) {
214 iText = null;
215 iContent = content;
216 }
217
218 /** constructor */
219 public Term(String text, List<Term> content) {
220 iText = text;
221 iContent = content;
222 }
223
224 /** constructor */
225 public Term(String text, Term[] content) {
226 iText = text;
227 if (content == null) {
228 iContent = null;
229 } else {
230 iContent = new ArrayList<Term>();
231 for (int i = 0; i < content.length; i++)
232 iContent.add(content[i]);
233 }
234 }
235
236 /** constructor */
237 public Term(Term[] content) {
238 this(null, content);
239 }
240
241 /** return text */
242 public String getText() {
243 return iText;
244 }
245
246 /** return content */
247 public List<Term> getContent() {
248 return iContent;
249 }
250
251 /** content size */
252 public int size() {
253 return (iContent == null ? -1 : iContent.size());
254 }
255
256 /** return text as int */
257 public int toInt() {
258 return Integer.parseInt(iText);
259 }
260
261 /** return text as long */
262 public long toLong() {
263 return Long.parseLong(iText);
264 }
265
266 /** return text as fouble */
267 public double toDouble() {
268 return Double.parseDouble(iText);
269 }
270
271 /** return text as boolean */
272 public boolean toBoolean() {
273 return (toInt() != 0);
274 }
275
276 /** return content as boolean array */
277 public boolean[] toBooleanArray() {
278 if (iContent.size() == 1 && iContent.get(0).toString().length() == 0)
279 return new boolean[] {};
280 boolean[] ret = new boolean[iContent.size()];
281 for (int i = 0; i < ret.length; i++) {
282 ret[i] = elementAt(i).toBoolean();
283 }
284 return ret;
285 }
286
287 /** return content as string array */
288 public String[] toStringArray() {
289 if (iContent.size() == 1 && iContent.get(0).toString().length() == 0)
290 return new String[] {};
291 String[] ret = new String[iContent.size()];
292 for (int i = 0; i < ret.length; i++) {
293 Term t = elementAt(i);
294 ret[i] = (t.getText().length() > 0 ? t.toString() : t.elementAt(0).toString());
295 }
296 return ret;
297 }
298
299 /** return content as int array */
300 public int[] toIntArray() {
301 // System.err.println("ToIntArray: "+this);
302 if (iContent.size() == 1 && iContent.get(0).toString().length() == 0)
303 return new int[] {};
304 int[] ret = new int[iContent.size()];
305 for (int i = 0; i < ret.length; i++) {
306 Term t = elementAt(i);
307 ret[i] = (t.getText().length() > 0 ? Integer.parseInt(t.getText()) : t.elementAt(0).toInt());
308 // System.err.println(" "+i+" .. "+ret[i]);
309 }
310 return ret;
311 }
312
313 /** idx-th element of content */
314 public Term elementAt(int idx) {
315 try {
316 return iContent.get(idx);
317 } catch (Exception e) {
318 return null;
319 }
320 }
321
322 /** element of content named name */
323 public Term element(String name) {
324 try {
325 for (Term t : iContent) {
326 if (t.getText() != null && t.getText().equals(name))
327 return t;
328 }
329 return null;
330 } catch (Exception e) {
331 return null;
332 }
333 }
334
335 /** index of element of content named name */
336 public int indexOf(String name) {
337 try {
338 int idx = 0;
339 for (Term t : iContent) {
340 if (t.getText() != null && t.getText().equals(name))
341 return idx;
342 idx++;
343 }
344 return -1;
345 } catch (Exception e) {
346 return -1;
347 }
348 }
349
350 /** string representation of term */
351 @Override
352 public String toString() {
353 boolean isArray = (iText == null || iText.length() == 0);
354 StringBuffer sb = new StringBuffer(isArray ? "" : iText);
355 if (iContent != null) {
356 sb.append(isArray ? "[" : "(");
357 for (Iterator<Term> e = iContent.iterator(); e.hasNext();) {
358 sb.append(e.next().toString());
359 sb.append(e.hasNext() ? "," : "");
360 }
361 sb.append(isArray ? "]" : ")");
362 }
363 return sb.toString();
364 }
365
366 @Override
367 public int hashCode() {
368 return toString().hashCode();
369 }
370
371 @Override
372 public Object clone() {
373 return new Term(iText == null ? null : new String(iText), iContent == null ? iContent
374 : new ArrayList<Term>(iContent));
375 }
376 }
377 }