Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / jigsaw / src / org / w3c / jigsaw / pics / SampleLabel.java
diff --git a/JMCR-Stable/real-world application/jigsaw/src/org/w3c/jigsaw/pics/SampleLabel.java b/JMCR-Stable/real-world application/jigsaw/src/org/w3c/jigsaw/pics/SampleLabel.java
new file mode 100644 (file)
index 0000000..c73ff2f
--- /dev/null
@@ -0,0 +1,475 @@
+// SampleLabel.java\r
+// $Id: SampleLabel.java,v 1.1 2010/06/15 12:25:29 smhuang Exp $\r
+// (c) COPYRIGHT MIT and INRIA, 1996.\r
+// Please first read the full copyright statement in file COPYRIGHT.html\r
+\r
+package org.w3c.jigsaw.pics ;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.LineNumberInputStream;\r
+import java.io.PrintStream;\r
+import java.io.StringBufferInputStream;\r
+\r
+// I like writing these silly kind of parsers !\r
+// (its probably the X)\r
+\r
+class LabelParser { \r
+    File file = null ;\r
+    LineNumberInputStream in = null ;\r
+    int         ch = -1 ;\r
+    byte buffer[] = null ;\r
+    int  bufptr = 0 ;\r
+\r
+    /**\r
+     * Append the given char in the internal buffer\r
+     */\r
+\r
+    public void append (int ch) {\r
+       if ( bufptr + 1 >= buffer.length) {\r
+           // resize buffer \r
+           byte nbuf[] = new byte[buffer.length * 2] ;\r
+           System.arraycopy (buffer, 0, nbuf, 0, bufptr) ;\r
+           buffer = nbuf ;\r
+       }\r
+       buffer[bufptr++] = (byte) ch ;\r
+    }\r
+\r
+    /**\r
+     * Get the token from our internale buffer.\r
+     */\r
+\r
+    public String getToken (boolean clear) {\r
+       String tok = new String (buffer, 0, 0, bufptr) ;\r
+       if ( clear )\r
+           bufptr = 0 ;\r
+       return tok ;\r
+    }\r
+\r
+    /**\r
+     * Parser expects given character.\r
+     */\r
+\r
+    void expect (int c) \r
+       throws InvalidLabelException\r
+    {\r
+       if ( ch == c )\r
+           return ;\r
+       String msg = ("expected " \r
+                     + (new Character((char) c)).toString()\r
+                     + "[" + c + "]"\r
+                     + " got " \r
+                     + (new Character((char) ch)).toString() \r
+                     + "[" + ch + "]");\r
+       if (file == null)\r
+         throw new InvalidLabelException(in.getLineNumber(), msg) ;\r
+       else\r
+         throw new InvalidLabelFileException (file, in.getLineNumber(), msg) ;\r
+    }\r
+\r
+    String parseVariableName () \r
+       throws IOException\r
+    {\r
+       while ((ch != '=') && (ch != '\n') && (ch != -1)) {\r
+           append (Character.toLowerCase((char)ch)) ;\r
+           ch = in.read() ;\r
+       }\r
+       return getToken(true) ;\r
+    }\r
+\r
+    String parseVariableValue() \r
+       throws IOException\r
+    {\r
+       while ( (ch != -1) && (ch != '\n') ) {\r
+           append (ch) ;\r
+           ch = in.read() ;\r
+       }\r
+       return getToken(true) ;\r
+    }\r
+\r
+    SampleLabel parse (SampleLabel into)\r
+       throws InvalidLabelException, InvalidLabelFileException\r
+    {\r
+       try {\r
+           while ( true ) {\r
+               switch (ch) {\r
+                 case -1:\r
+                     // we are done.\r
+                     return into ;\r
+                 case ' ': case '\t': case '\n':\r
+                     ch = in.read() ;\r
+                     continue ;\r
+                 case '#':\r
+                     while ( ((ch = in.read()) != '\n') && (ch != -1) )\r
+                         ;\r
+                     continue ;\r
+                 default:\r
+                     String name = parseVariableName() ;\r
+                     expect ('=') ; ch = in.read() ;\r
+                     String value = parseVariableValue() ;\r
+                     if (ch != -1) { // Pb -1 instead of \n\r
+                       expect ('\n') ; \r
+                       ch = in.read() ;\r
+                     }\r
+                     into.addBinding (name, value) ;\r
+                     continue ;\r
+               }\r
+           }\r
+       } catch (IOException e) {\r
+         if (file == null)\r
+           throw new InvalidLabelException( "IO exception.") ;\r
+         else\r
+           throw new InvalidLabelFileException (file.getAbsolutePath()\r
+                                                + ": IO exception.") ;\r
+       }\r
+    }\r
+\r
+    LabelParser (File file) \r
+       throws InvalidLabelFileException\r
+    {\r
+       this.file = file ;\r
+       try {\r
+           this.in = (new LineNumberInputStream \r
+                      (new BufferedInputStream\r
+                       (new FileInputStream (file)))) ;\r
+           this.buffer = new byte[32] ;\r
+           this.ch = in.read() ;\r
+       } catch (IOException e) {\r
+           throw new InvalidLabelFileException (file.getAbsolutePath()\r
+                                                + ": IO exception.") ;\r
+       }\r
+    }\r
+\r
+    LabelParser (String string) \r
+       throws InvalidLabelException\r
+    {\r
+       try {\r
+           this.in = (new LineNumberInputStream \r
+                      (new BufferedInputStream\r
+                       (new StringBufferInputStream (string)))) ;\r
+\r
+           this.buffer = new byte[32] ;\r
+           this.ch = in.read() ;\r
+       } catch (IOException e) {\r
+           throw new InvalidLabelException( "IO exception.") ;\r
+       }\r
+    }\r
+\r
+}\r
+\r
+/**\r
+ * Label internal representation.\r
+ * The server has to know something about labels. In this implementation, I try\r
+ * to reduce this knowledge as fas as I could. Here, a label is a set of\r
+ * assignements to variables (options in PICS terms), and a rating.\r
+ * The syntax for writing label files is the following:\r
+ * <variable>=<value>\n\r
+ * <p>Comments are allowed through the '#' at beginning of line.\r
+ * With the special variable 'ratings' being mandatory.\r
+ */\r
+\r
+public class SampleLabel implements LabelInterface {\r
+    // Default variables array size\r
+    private static final int VARSIZE = 8 ;\r
+\r
+    String vars[] = null ;\r
+    String vals[] = null ;\r
+\r
+    int    varptr = 0 ;\r
+\r
+    void addBinding (String var, String val) {\r
+       if ( varptr + 1 >= vars.length ) {\r
+           // resize arrays \r
+           String nvars[] = new String[vars.length*2] ;\r
+           String nvals[] = new String[vals.length*2] ;\r
+           System.arraycopy (vars, 0, nvars, 0, vars.length) ;\r
+           System.arraycopy (vals, 0, nvals, 0, vals.length) ;\r
+           vars = nvars ;\r
+           vals = nvals ;\r
+       }\r
+       vars[varptr] = var ;\r
+       vals[varptr] = val ;\r
+       varptr++ ;\r
+    }\r
+\r
+    /**\r
+     * Debugging: print the given options of this label.\r
+     * @param out The PrintStream to print to.\r
+     */\r
+\r
+    public void print (PrintStream out) {\r
+       for (int i = 0 ; i < varptr ; i++) {\r
+           System.out.println ("\t" + vars[i] + " = " + vals[i]) ;\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Does this label defines the given option ?\r
+     * @param option The option to look for.\r
+     * @return <strong>true</strong> if the label defines the given option.\r
+     */\r
+\r
+    public boolean hasOption (String option) {\r
+       for (int i = 0 ; i < varptr ; i++) {\r
+           if ( vars[i].equals (option) )\r
+               return true ;\r
+       }\r
+       return false ;\r
+    }\r
+\r
+    /**\r
+     * Get an option index.\r
+     * This allows for fast acces to label options. There is no guarantee that\r
+     * the same option will get the same index across labels.\r
+     * @param option The option to look for.\r
+     * @return An integer, which is the option index if the option was found\r
+     *    or <strong>-1</strong> if the option isn't defined for this label.\r
+     */\r
+\r
+    public int getOptionIndex (String option) {\r
+       for (int i = 0 ; i < varptr ; i++) {\r
+           if ( vars[i].equals (option) )\r
+               return i;\r
+       }\r
+       return -1 ;\r
+    }\r
+\r
+    /**\r
+     * Get an option value, by index.\r
+     * This, along with the <strong>getOptionIndex</strong> method provides\r
+     * a fast access to option values.\r
+     * @param idx The index of the option, as gotten from \r
+     *    <strong>getOptionIndex</strong>.\r
+     * @return A String instance, providing the option value.\r
+     */\r
+\r
+    public String getOptionValue (int idx) {\r
+       if ( (idx < 0) || (idx >= varptr) ) \r
+           throw new RuntimeException (this.getClass().getName()\r
+                                       + "[getOptionValue]: "\r
+                                       + " invalid index.") ;\r
+       return vals[idx] ;\r
+    }\r
+\r
+    /**\r
+     * Get an option value, by option name.\r
+     * @param option The option that you want the value of.\r
+     * @return A String instance giving the option value, or \r
+     *    <strong>null</strong>, if the option isn't defined for this label.\r
+     */\r
+\r
+    public String getOptionValue (String option) {\r
+       for (int i = 0 ; i < varptr ; i++) {\r
+           if ( vars[i].equals (option) ) \r
+               return vals[i] ;\r
+       }\r
+       return null ;\r
+    }\r
+\r
+    /**\r
+     * Is this label generic ?\r
+     * @return <strong>true</strong> if the label if generic.\r
+     */\r
+\r
+    public boolean isGeneric () {\r
+       int idx = getOptionIndex ("generic") ;\r
+       if ( idx >= 0 )\r
+           return (new Boolean(getOptionValue (idx))).booleanValue() ;\r
+       return false ;\r
+    }\r
+\r
+    /**\r
+     * Emit the given option to the output.\r
+     * If the option is not defined for this label, skip it (don't emit). If \r
+     * possible, and according to the format, emit the short option name.\r
+     * @param space Should we emit a leading space.\r
+     * @param option The option name.\r
+     * @return <strong>true</strong> if the option was successfully emited,\r
+     *    <strong>false</strong> otherwise.\r
+     */\r
+\r
+    private boolean emit (boolean space\r
+                         , StringBuffer into\r
+                         , String option, int format) {\r
+       String value = getOptionValue (option) ;\r
+       if ( value != null ) {\r
+           switch (format) {\r
+             case LabelBureauInterface.FMT_MINIMAL:\r
+             case LabelBureauInterface.FMT_SHORT:\r
+                 // emit short option name\r
+                 if ( space )\r
+                     into.append (" ") ;\r
+                 into.append (option+" "+value) ;\r
+                 break ;\r
+             default:\r
+                 // emit full option name\r
+                 if ( space )\r
+                     into.append (" ") ;\r
+                 into.append (option+" "+value) ;\r
+                 break ;\r
+           }\r
+           return true ;\r
+       }\r
+       return false ;\r
+    }\r
+\r
+    /**\r
+     * Emit the given option to the output.\r
+     * If possible, and according to the format, emit the short option name.\r
+     * @param space Should we emit a leading space.\r
+     * @param into The StringBuffer to dump this label to.\r
+     * @param option The option name.\r
+     */\r
+\r
+    private void emit (boolean space, StringBuffer into, int idx, int format) {\r
+       switch (format) {\r
+         case LabelBureauInterface.FMT_MINIMAL:\r
+         case LabelBureauInterface.FMT_SHORT:\r
+             // emit short option name\r
+             if ( space )\r
+                 into.append (" ") ;\r
+             into.append (vars[idx]+" "+vals[idx]) ;\r
+             break ;\r
+         default:\r
+             if ( space )\r
+                 into.append (" ") ;\r
+             into.append (vars[idx]+" "+vals[idx]) ;\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Dump this label according to the given format.\r
+     * The dump should take place <em>after</em> the service has dump itself.\r
+     * @param into A StringBuffer to dump the labels to.\r
+     * @param format The format in which the dump should be done. This can\r
+     *    be one of the four format described in the PICS specification.\r
+     */\r
+\r
+    public void dump (StringBuffer into, int format) {\r
+       boolean space = false ; ;\r
+       switch (format) {\r
+         case LabelBureauInterface.FMT_MINIMAL:\r
+             // emit just the ratings, except if generic\r
+             if ( isGeneric() ) {\r
+                 // emit the generic and for options (FIXME errors ?)\r
+                 emit (space,into,"generic",LabelBureauInterface.FMT_MINIMAL);\r
+                 space = true ;\r
+                 emit (space,into,"for",LabelBureauInterface.FMT_MINIMAL) ;\r
+                 emit (space,into,"ratings",LabelBureauInterface.FMT_MINIMAL);\r
+             } else {\r
+                 emit (space,into,"ratings",LabelBureauInterface.FMT_MINIMAL);\r
+             }\r
+             break ;\r
+         case LabelBureauInterface.FMT_SHORT:\r
+             // emit ratings, and full, which I deem appropriate\r
+             if ( isGeneric() ) {\r
+                 // emit the generic and for options:\r
+                 emit (space,into, "generic", LabelBureauInterface.FMT_SHORT);\r
+                 space = true ;\r
+                 emit (space,into, "for", LabelBureauInterface.FMT_SHORT) ;\r
+                 emit (space,into, "full", LabelBureauInterface.FMT_SHORT) ;\r
+                 emit (space,into, "ratings", LabelBureauInterface.FMT_SHORT);\r
+             } else {\r
+                 emit (space, into, "full", LabelBureauInterface.FMT_SHORT) ;\r
+                 space = true ;\r
+                 emit (space,into,"ratings",LabelBureauInterface.FMT_SHORT) ;\r
+             }\r
+             break ;\r
+         case LabelBureauInterface.FMT_FULL:\r
+             // Emit all options, rating at the end\r
+             for (int i = 0 ; i < varptr ; i++) {\r
+                 if ( vars[i].equals("ratings") )\r
+                     continue ;\r
+                 emit (space, into, i, LabelBureauInterface.FMT_FULL) ;\r
+                 space = true ;\r
+             }\r
+             emit (space, into, "ratings", LabelBureauInterface.FMT_FULL) ;\r
+             break ;\r
+         case LabelBureauInterface.FMT_SIGNED:\r
+             throw new RuntimeException (this.getClass().getName()\r
+                                         + "[dump]: "\r
+                                         + "SIGNED format unsupported.") ;\r
+             \r
+             // not reached\r
+         default:\r
+             throw new RuntimeException (this.getClass().getName()\r
+                                         + "[dump]: "\r
+                                         + " invalid format "\r
+                                         + "\"" + format + "\"") ;\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Create a new label from the given stream.\r
+     * @param file The file inwhich the label options are described.\r
+     */\r
+\r
+    SampleLabel (File file) \r
+       throws InvalidLabelException\r
+    {\r
+      try {\r
+       this.vars   = new String[VARSIZE] ;\r
+       this.vals   = new String[VARSIZE] ;\r
+       this.varptr = 0 ;\r
+       LabelParser p = new LabelParser (file) ;\r
+       p.parse (this) ;\r
+      } catch (InvalidLabelException e) {\r
+       throw new InvalidLabelFileException(e.getMessage());\r
+      }\r
+    }\r
+\r
+    SampleLabel (String string) \r
+       throws InvalidLabelException\r
+    {\r
+       this.vars   = new String[VARSIZE] ;\r
+       this.vals   = new String[VARSIZE] ;\r
+       this.varptr = 0 ;\r
+       LabelParser p = new LabelParser (string) ;\r
+       p.parse (this) ;\r
+    }\r
+    /**\r
+     * Create a new label from a set of options.\r
+     * This constructor takes two arrays, one of option names, and one\r
+     * of option values. It builds out of them the internal\r
+     * representation for this label.\r
+     * <p>The given arrays are used as is (no copy), and might side-effected\r
+     * by the new instance.\r
+     * @param optnames Names of option for this label.\r
+     * @param optvalues Values of option for this label.  \r
+     */\r
+\r
+    public SampleLabel (String optnames[], String optvals[]) {\r
+       if ( optnames.length != optvals.length )\r
+           throw new RuntimeException (this.getClass().getName()\r
+                                       + " invalid constructor params:"\r
+                                       + " bad length.") ;\r
+       this.vars   = optnames ;\r
+       this.vals   = optvals ;\r
+       this.varptr = optnames.length ;\r
+    }\r
+\r
+    // Testing only\r
+\r
+    public static void main (String args[]) {\r
+       if ( args.length != 1 ) {\r
+           System.out.println ("Label <file>") ;\r
+           System.exit (1) ;\r
+       }\r
+       try {\r
+           SampleLabel label = new SampleLabel (new File (args[0])) ;\r
+           StringBuffer sb = new StringBuffer() ;\r
+           label.dump (sb, LabelBureauInterface.FMT_MINIMAL) ;\r
+           System.out.println (sb.toString()) ;\r
+       } catch (InvalidLabelException e) {\r
+           System.out.println (e.getMessage()) ;\r
+           System.exit (1) ;\r
+       }\r
+       System.exit (0) ;\r
+    }\r
+\r
+}\r
+\r
+\r