Commits

Rhys ! committed c8528b3 Draft

- added javadoc for more public methods
- throwing EncodingException for unsupported regex flags

Comments (0)

Files changed (5)

src/org/bert_rpc/Bert.java

  * BERT static convenience methods.
  */
 public class Bert {
+    /**
+     * Reads a single object from the provided byte array.
+     *
+     * @param bytes A byte array containing a BERT term.
+     * @return A decoded object with a type on the supported type list.
+     * @throws DecodingException Signals that the provided input cannot be
+     * decoded according to the BERT spec to an interoperable object.
+     *
+     * @see org.bert_rpc
+     */
     public static Object decode(byte[] bytes) throws DecodingException {
         try {
-            return Bert.decode(new ByteArrayInputStream(bytes));
+            return new Decoder(new ByteArrayInputStream(bytes)).decode();
         } catch (IOException e) {
             throw new RuntimeException("Reading from array failed somehow: "
                     + e.getMessage(), e);
         }
     }
 
-    public static Object decode(InputStream inputStream)
-            throws DecodingException, IOException {
-        return new Decoder(inputStream).decode();
-    }
-
-    public static byte[] encode(Object value) throws EncodingException {
+    /**
+     * Encodes an object with any type on the BERT supported types list onto
+     * a byte array.
+     *
+     * @param object The object to encode.
+     * @throws EncodingException Signals that the provided object cannot be
+     * encoded according to the BERT spec to an interoperable output.
+     */
+    public static byte[] encode(Object object) throws EncodingException {
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         try {
-            new Encoder(out).encodeUnknownType(value);
+            new Encoder(out).encodeUnknownType(object);
             out.flush();
         } catch (IOException e) {
             throw new RuntimeException("Writing to array failed somehow: "

src/org/bert_rpc/Decoder.java

 public class Decoder {
     private final DataInputStream inputStream;
 
+    /**
+     * Creates a Decoder that reads from the provided input stream.
+     *
+     * @param inputStream The input stream to read BERT terms from.
+     */
     public Decoder(InputStream inputStream) {
         this.inputStream = new DataInputStream(inputStream);
     }
 
+    /**
+     * Reads a single object from the input stream.
+     *
+     * @return A decoded object with a type on the supported type list.
+     * @throws DecodingException Signals that the provided input cannot be
+     * decoded according to the BERT spec to an interoperable object.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     *
+     * @see org.bert_rpc
+     */
     public Object decode() throws DecodingException, IOException {
         int v = this.inputStream.read();
         if (v != Constants.MAGIC) {
         }
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings("unchecked") // for List<Tuple> cast
     private Map<Object, Object> extractDict(Tuple tuple)
             throws DecodingException {
         if (tuple.size() != 3) {

src/org/bert_rpc/Encoder.java

 public class Encoder {
     private final DataOutputStream outputStream;
 
+    /**
+     * Creates an Encoder that writes to the provided output stream.
+     * @param outputStream The output stream to write BERT terms from.
+     */
     public Encoder(OutputStream outputStream) {
         this.outputStream = new DataOutputStream(outputStream);
     }
 
+    /**
+     * Encodes an object with any type on the BERT supported types list.
+     *
+     * @param object The object to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     * @throws EncodingException Signals that the provided object cannot be
+     * encoded according to the BERT spec to an interoperable output.
+     */
     public void encodeUnknownType(Object object)
             throws IOException, EncodingException {
         this.outputStream.writeByte(Constants.MAGIC);
     }
 
     @SuppressWarnings("unchecked") // for Map to Map<K, V> cast
-    public void writeUnknownType(Object value)
+    private void writeUnknownType(Object value)
             throws EncodingException, IOException {
         if (value == null) {
             this.writeNull();
         }
     }
 
+    /**
+     * Encodes a tuple containing any types on the BERT supported types list.
+     *
+     * @param tuple The tuple to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     * @throws EncodingException Signals that the provided object cannot be
+     * encoded according to the BERT spec to an interoperable output.
+     */
     public void encode(Tuple tuple) throws IOException, EncodingException {
         this.outputStream.writeByte(Constants.MAGIC);
         if (tuple == null) this.writeNull(); else this.writeTuple(tuple);
     }
 
     /**
-     * Write a tuple that is user-provided and cannot be a complex type.
+     * Writes a tuple that is user-provided and cannot be a complex type.
      *
      * @param tuple The tuple to write.
      * @throws IOException Signals that an I/O exception of some sort has
     }
 
     /**
-     * Write a tuple that may be a complex type.
+     * Writes a tuple that may be a complex type.
      *
      * @param tuple The tuple to write.
      * @throws IOException Signals that an I/O exception of some sort has
         this.outputStream.writeBytes(atom.identifier);
     }
 
+    /**
+     * Encodes a map containing any types on the BERT supported types list.
+     *
+     * @param map The map to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     * @throws EncodingException Signals that the provided object cannot be
+     * encoded according to the BERT spec to an interoperable output.
+     */
     public <K, V> void encode(Map<K, V> map)
             throws IOException, EncodingException {
         this.outputStream.writeByte(Constants.MAGIC);
                 new TwoTupleMapTransformer<K, V>(map)));
     }
 
+    /**
+     * Encodes a date.
+     *
+     * @param date The date to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encode(Date date) throws IOException {
         this.outputStream.writeByte(Constants.MAGIC);
         if (date == null) this.writeNull(); else this.writeDate(date);
         }
     }
 
+    /**
+     * Encodes an integer value that could be null.
+     *
+     * @param value The value to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encode(Integer value) throws IOException {
         if (value == null) this.encodeNull(); else this.encode((int)value);
     }
 
+    /**
+     * Encodes an integer value.
+     *
+     * @param value The value to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encode(int value) throws IOException {
         this.outputStream.writeByte(Constants.MAGIC);
         this.writeInt(value);
         }
     }
 
+    /**
+     * Encodes a double-precision floating point value that could be null.
+     *
+     * @param value The value to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encode(Double value) throws IOException {
         if (value == null) this.encodeNull(); else this.encode((double)value);
     }
 
+    /**
+     * Encodes a double-precision floating point value.
+     *
+     * @param value The value to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encode(double value) throws IOException {
         this.outputStream.writeByte(Constants.MAGIC);
         this.writeDouble(value);
         this.outputStream.write(Arrays.copyOf(bytes, Constants.FLOAT_LENGTH));
     }
 
+    /**
+     * Encodes a floating point value that could be null.
+     *
+     * @param value The value to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encode(Float value) throws IOException {
         if (value == null) this.encodeNull(); else this.encode((float)value);
     }
 
+    /**
+     * Encodes a floating point value.
+     *
+     * @param value The value to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encode(float value) throws IOException {
         this.outputStream.writeByte(Constants.MAGIC);
         this.writeFloat(value);
         this.writeDouble((double) value);
     }
 
+    /**
+     * Encodes a boolean value that could be null.
+     *
+     * @param value The value to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encode(Boolean value) throws IOException {
         if (value == null) this.encodeNull(); else this.encode((boolean)value);
     }
 
-    public void encode(boolean bool) throws IOException {
+    /**
+     * Encodes a boolean value.
+     *
+     * @param value The value to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
+    public void encode(boolean value) throws IOException {
         this.outputStream.writeByte(Constants.MAGIC);
-        this.writeBoolean(bool);
+        this.writeBoolean(value);
         this.outputStream.flush();
     }
 
         }
     }
 
+    /**
+     * Encodes a null value.
+     *
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encodeNull() throws IOException {
         this.outputStream.writeByte(Constants.MAGIC);
         this.writeNull();
         }
     }
 
+    /**
+     * Encodes a binary sequence.
+     *
+     * @param bytes The bytes to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     */
     public void encode(byte[] bytes) throws IOException {
         this.outputStream.writeByte(Constants.MAGIC);
         if (bytes == null) this.writeNull(); else this.writeBinary(bytes);
         this.outputStream.write(bytes);
     }
 
+    /**
+     * Encodes a list containing any types on the BERT supported types list.
+     *
+     * @param list The list to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     * @throws EncodingException Signals that the provided object cannot be
+     * encoded according to the BERT spec to an interoperable output.
+     */
     public void encode(List list) throws IOException, EncodingException {
         this.outputStream.writeByte(Constants.MAGIC);
         if (list == null) this.writeNull(); else this.writeList(list);
         }
     }
 
-    public void encode(Pattern regex) throws IOException {
+    /**
+     * Encodes a regular expression.
+     *
+     * @param regex The regular expression to encode.
+     * @throws IOException Signals that an I/O exception of some sort has
+     * occurred.
+     * @throws EncodingException Signals that the regular expression contains
+     * unsupported flags.
+     */
+    public void encode(Pattern regex) throws IOException, EncodingException {
         this.outputStream.writeByte(Constants.MAGIC);
         if (regex == null) this.writeNull(); else this.writeRegex(regex);
         this.outputStream.flush();
     }
 
     private void writeRegex(Pattern regex)
-            throws IOException {
+            throws IOException, EncodingException {
         List<Object> flags = new ArrayList<Object>();
         int runningMask = regex.flags();
         for (Map.Entry<Object, Integer> p : Constants.REGEX_FLAGS.entrySet()) {
             }
         }
 
+        if (runningMask != 0) {
+            throw new EncodingException("regex contains unsupported flags.");
+        }
+
         try {
             this.writeComplexTuple(new Tuple(Constants.$bert, Constants.$regex,
                     regex.pattern().getBytes("UTF8"),
                     flags));
         } catch (EncodingException e) {
-            throw new RuntimeException("somehow failed to encode regex. " +
-                    "this is a bug in jbert.", e);
+            throw new RuntimeException("somehow failed to encode valid regex. "
+                    + "this is a bug in jbert.", e);
         }
     }
 }

src/org/bert_rpc/package-info.java

+/**
+ * An implementation of the BERT binary data interchange format for Java.
+ *
+ * Supports encoding and decoding of the following types:
+ * <ul>
+ *     <li>{@link org.bert_rpc.Atom}</li>
+ *     <li>Boolean</li>
+ *     <li>byte[]</li>
+ *     <li>java.util.Date</li>
+ *     <li>Double</li>
+ *     <li>Float</li>
+ *     <li>Integer</li>
+ *     <li>java.util.List</li>
+ *     <li>java.util.Map</li>
+ *     <li>java.util.regex.Pattern</li>
+ *     <li>{@link org.bert_rpc.Tuple}</li>
+ * </ul>
+ *
+ * Note that regex Pattern encoding and decoding is a best-effort attempt at
+ * conforming to the spec. Some flags are not supported because they have no
+ * Java equivalent; thus, users must restrict themselves to some common subset
+ * of flags. In addition, the pattern component is assumed to be encoded as
+ * UTF-8, since Java does not accept binary patterns.
+ */
+
+package org.bert_rpc;

test/src/org/bert_rpc/TestEncoder.java

                 Bert.encode(Pattern.compile("(foo|spam)|(bar|eggs)")));
     }
 
+    @Test(expected = EncodingException.class)
+    public void testUnsupportedRegexFlags() throws Exception {
+        Pattern invalid = Pattern.compile("(foo|spam)|(bar|eggs)",
+                Pattern.LITERAL);
+        Bert.encode(invalid);
+    }
+
     @Test
     public void testEncodesIntegers() throws Exception {
         Assert.assertArrayEquals("encodes integers < 128",
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.