001package net.sf.cpsolver.ifs.util; 002 003import java.io.BufferedReader; 004import java.io.FileReader; 005import java.io.IOException; 006import java.io.InputStreamReader; 007import java.io.PrintWriter; 008import java.io.Reader; 009import java.util.ArrayList; 010import java.util.Iterator; 011import 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 Tomáš Müller<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 */ 035public 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}