avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cutt...@apache.org
Subject svn commit: r1196233 - in /avro/trunk: CHANGES.txt lang/php/lib/avro.php lang/php/lib/avro/datum.php lang/php/lib/avro/protocol.php lang/php/lib/avro/schema.php lang/php/test/AllTests.php lang/php/test/ProtocolFileTest.php
Date Tue, 01 Nov 2011 19:32:54 GMT
Author: cutting
Date: Tue Nov  1 19:32:54 2011
New Revision: 1196233

URL: http://svn.apache.org/viewvc?rev=1196233&view=rev
Log:
AVRO-821. PHP: Add support for parsing protocols.  Contributed by Andy Wick, Saleem Shafi
and A B.

Added:
    avro/trunk/lang/php/lib/avro/protocol.php   (with props)
    avro/trunk/lang/php/test/ProtocolFileTest.php   (with props)
Modified:
    avro/trunk/CHANGES.txt
    avro/trunk/lang/php/lib/avro.php
    avro/trunk/lang/php/lib/avro/datum.php
    avro/trunk/lang/php/lib/avro/schema.php
    avro/trunk/lang/php/test/AllTests.php

Modified: avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1196233&r1=1196232&r2=1196233&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Tue Nov  1 19:32:54 2011
@@ -4,6 +4,9 @@ Avro 1.6.1 (unreleased)
 
   NEW FEATURES
 
+    AVRO-821. PHP: Add support for parsing protocols. (Andy Wick,
+    Saleem Shafi and A B via cutting)
+
   OPTIMIZATIONS
 
   IMPROVEMENTS

Modified: avro/trunk/lang/php/lib/avro.php
URL: http://svn.apache.org/viewvc/avro/trunk/lang/php/lib/avro.php?rev=1196233&r1=1196232&r2=1196233&view=diff
==============================================================================
--- avro/trunk/lang/php/lib/avro.php (original)
+++ avro/trunk/lang/php/lib/avro.php Tue Nov  1 19:32:54 2011
@@ -192,3 +192,4 @@ require_once('avro/io.php');
 require_once('avro/gmp.php');
 require_once('avro/datum.php');
 require_once('avro/data_file.php');
+require_once('avro/protocol.php');

Modified: avro/trunk/lang/php/lib/avro/datum.php
URL: http://svn.apache.org/viewvc/avro/trunk/lang/php/lib/avro/datum.php?rev=1196233&r1=1196232&r2=1196233&view=diff
==============================================================================
--- avro/trunk/lang/php/lib/avro/datum.php (original)
+++ avro/trunk/lang/php/lib/avro/datum.php Tue Nov  1 19:32:54 2011
@@ -92,7 +92,7 @@ class AvroIODatumWriter
    * @param AvroIOBinaryEncoder $encoder
    * @returns mixed
    *
-   * @throws AvrioIOTypeException if $datum is invalid for $writers_schema
+   * @throws AvroIOTypeException if $datum is invalid for $writers_schema
    */
   function write_data($writers_schema, $datum, $encoder)
   {

Added: avro/trunk/lang/php/lib/avro/protocol.php
URL: http://svn.apache.org/viewvc/avro/trunk/lang/php/lib/avro/protocol.php?rev=1196233&view=auto
==============================================================================
--- avro/trunk/lang/php/lib/avro/protocol.php (added)
+++ avro/trunk/lang/php/lib/avro/protocol.php Tue Nov  1 19:32:54 2011
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @package Avro
+ */
+
+/**
+ * Avro library for protocols
+ * @package Avro
+ */
+class AvroProtocol
+{
+  public $name;
+  public $namespace;
+  public $schemata;
+
+  public static function parse($json)
+  {
+    if (is_null($json))
+      throw new AvroProtocolParseException( "Protocol can't be null");
+
+    $protocol = new AvroProtocol();
+    $protocol->real_parse(json_decode($json, true));
+    return $protocol;
+  }
+
+  function real_parse($avro) {
+    $this->protocol = $avro["protocol"];
+    $this->namespace = $avro["namespace"];
+    $this->schemata = new AvroNamedSchemata();
+    $this->name = $avro["protocol"];
+
+    if (!is_null($avro["types"])) {
+        $types = AvroSchema::real_parse($avro["types"], $this->namespace, $this->schemata);
+    }
+
+    if (!is_null($avro["messages"])) {
+      foreach ($avro["messages"] as $messageName => $messageAvro) {
+        $message = new AvroProtocolMessage($messageName, $messageAvro, $this);
+        $this->messages{$messageName} = $message;
+      }
+    }
+  }
+}
+
+class AvroProtocolMessage
+{
+  /**
+   * @var AvroRecordSchema $request
+   */
+
+  public $request;
+
+  public $response;
+
+  public function __construct($name, $avro, $protocol)
+  {
+    $this->name = $name;
+    $this->request = new AvroRecordSchema(new AvroName($name, null, $protocol->namespace),
null, $avro{'request'}, $protocol->schemata, AvroSchema::REQUEST_SCHEMA);
+
+    if (array_key_exists('response', $avro)) {
+      $this->response = $protocol->schemata->schema_by_name(new AvroName($avro{'response'},
$protocol->namespace, $protocol->namespace));
+      if ($this->response == null)
+        $this->response = new AvroPrimitiveSchema($avro{'response'});
+    }
+  }
+}
+
+class AvroProtocolParseException extends AvroException {};

Propchange: avro/trunk/lang/php/lib/avro/protocol.php
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: avro/trunk/lang/php/lib/avro/schema.php
URL: http://svn.apache.org/viewvc/avro/trunk/lang/php/lib/avro/schema.php?rev=1196233&r1=1196232&r2=1196233&view=diff
==============================================================================
--- avro/trunk/lang/php/lib/avro/schema.php (original)
+++ avro/trunk/lang/php/lib/avro/schema.php Tue Nov  1 19:32:54 2011
@@ -443,7 +443,7 @@ class AvroSchema
         if (is_array($datum))
         {
           foreach ($expected_schema->fields() as $field)
-            if (!self::is_valid_datum($field->type(), $datum[$field->name()]))
+            if (!array_key_exists($field->name(), $datum) || !self::is_valid_datum($field->type(),
$datum[$field->name()]))
               return false;
           return true;
         }
@@ -685,7 +685,7 @@ class AvroUnionSchema extends AvroSchema
    * @var int[] list of indices of named schemas which
    *                are defined in $schemata
    */
-  private $schema_from_schemata_indices;
+  public $schema_from_schemata_indices;
 
   /**
    * @param AvroSchema[] $schemas list of schemas in the union
@@ -795,7 +795,8 @@ class AvroNamedSchema extends AvroSchema
       throw new AvroSchemaParseException('Schema doc attribute must be a string');
     $this->doc = $doc;
 
-    $schemata = $schemata->clone_with_new_schema($this);
+    if (!is_null($schemata))
+      $schemata = $schemata->clone_with_new_schema($this);
   }
 
   /**
@@ -986,6 +987,12 @@ class AvroNamedSchemata
     $this->schemata = $schemata;
   }
 
+  public function list_schemas() {
+    var_export($this->schemata);
+    foreach($this->schemata as $sch) 
+      print('Schema '.$sch->__toString()."\n");
+  }
+
   /**
    * @param string $fullname
    * @returns boolean true if there exists a schema with the given name
@@ -1179,7 +1186,7 @@ class AvroRecordSchema extends AvroNamed
    * @returns AvroField[]
    * @throws AvroSchemaParseException
    */
-  private static function parse_fields($field_data, $default_namespace, &$schemata)
+  static function parse_fields($field_data, $default_namespace, &$schemata)
   {
     $fields = array();
     $field_names = array();
@@ -1247,7 +1254,7 @@ class AvroRecordSchema extends AvroNamed
         'Record schema requires a non-empty fields attribute');
 
     if (AvroSchema::REQUEST_SCHEMA == $schema_type)
-      $this->type = $schema_type;
+      parent::__construct($schema_type, $name); 
     else
       parent::__construct($schema_type, $name, $doc, $schemata);
 

Modified: avro/trunk/lang/php/test/AllTests.php
URL: http://svn.apache.org/viewvc/avro/trunk/lang/php/test/AllTests.php?rev=1196233&r1=1196232&r2=1196233&view=diff
==============================================================================
--- avro/trunk/lang/php/test/AllTests.php (original)
+++ avro/trunk/lang/php/test/AllTests.php Tue Nov  1 19:32:54 2011
@@ -25,6 +25,7 @@ require_once('IODatumReaderTest.php');
 require_once('LongEncodingTest.php');
 require_once('FloatIntEncodingTest.php');
 require_once('DatumIOTest.php');
+require_once('ProtocolFileTest.php');
 // InterOpTest tests are run separately.
 
 class AllTests
@@ -40,6 +41,7 @@ class AllTests
     $suite->addTestSuite('LongEncodingTest');
     $suite->addTestSuite('FloatIntEncodingTest');
     $suite->addTestSuite('DatumIOTest');
+    $suite->addTestSuite('ProtocolFileTest');
     return $suite;
   }
 }

Added: avro/trunk/lang/php/test/ProtocolFileTest.php
URL: http://svn.apache.org/viewvc/avro/trunk/lang/php/test/ProtocolFileTest.php?rev=1196233&view=auto
==============================================================================
--- avro/trunk/lang/php/test/ProtocolFileTest.php (added)
+++ avro/trunk/lang/php/test/ProtocolFileTest.php Tue Nov  1 19:32:54 2011
@@ -0,0 +1,353 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+require_once('test_helper.php');
+
+// near-verbatim port of test_protocol.py
+class ProtocolFileTest extends PHPUnit_Framework_TestCase
+{
+	protected function setUp() {
+	}
+	
+	public function testParsing() {
+		$cnt=count($this->prot_parseable);
+		for ($i=0; $i<$cnt; $i++) {
+			try {
+				//print($i . " " . ($this->prot_parseable[$i]?"true":"false") . " \n");
+				$prot=AvroProtocol::parse($this->prot_data[$i]);
+			} catch (AvroSchemaParseException $x) {
+				// exception ok if we expected this protocol spec to be unparseable
+				$this->assertEquals(false, $this->prot_parseable[$i]);
+			}
+		}
+	}
+	
+	// test data
+	private $prot_parseable=array(true, true, true, true, true, true, false, true, true);
+	private $prot_data = array(
+<<<'DATUM'
+{
+  "namespace": "com.acme",
+  "protocol": "HelloWorld",
+
+  "types": [
+    {"name": "Greeting", "type": "record", "fields": [
+      {"name": "message", "type": "string"}]},
+    {"name": "Curse", "type": "error", "fields": [
+      {"name": "message", "type": "string"}]}
+  ],
+
+  "messages": {
+    "hello": {
+      "request": [{"name": "greeting", "type": "Greeting" }],
+      "response": "Greeting",
+      "errors": ["Curse"]
+    }
+  }
+}
+DATUM
+,
+<<<'DATUM'
+{"namespace": "org.apache.avro.test",
+ "protocol": "Simple",
+
+ "types": [
+     {"name": "Kind", "type": "enum", "symbols": ["FOO","BAR","BAZ"]},
+
+     {"name": "MD5", "type": "fixed", "size": 16},
+
+     {"name": "TestRecord", "type": "record",
+      "fields": [
+          {"name": "name", "type": "string", "order": "ignore"},
+          {"name": "kind", "type": "Kind", "order": "descending"},
+          {"name": "hash", "type": "MD5"}
+      ]
+     },
+
+     {"name": "TestError", "type": "error", "fields": [
+         {"name": "message", "type": "string"}
+      ]
+     }
+
+ ],
+
+ "messages": {
+
+     "hello": {
+         "request": [{"name": "greeting", "type": "string"}],
+         "response": "string"
+     },
+
+     "echo": {
+         "request": [{"name": "record", "type": "TestRecord"}],
+         "response": "TestRecord"
+     },
+
+     "add": {
+         "request": [{"name": "arg1", "type": "int"}, {"name": "arg2", "type": "int"}],
+         "response": "int"
+     },
+
+     "echoBytes": {
+         "request": [{"name": "data", "type": "bytes"}],
+         "response": "bytes"
+     },
+
+     "error": {
+         "request": [],
+         "response": "null",
+         "errors": ["TestError"]
+     }
+ }
+
+}
+DATUM
+,
+<<<'DATUM'
+{"namespace": "org.apache.avro.test.namespace",
+ "protocol": "TestNamespace",
+
+ "types": [
+     {"name": "org.apache.avro.test.util.MD5", "type": "fixed", "size": 16},
+     {"name": "TestRecord", "type": "record",
+      "fields": [ {"name": "hash", "type": "org.apache.avro.test.util.MD5"} ]
+     },
+     {"name": "TestError", "namespace": "org.apache.avro.test.errors",
+      "type": "error", "fields": [ {"name": "message", "type": "string"} ]
+     }
+ ],
+
+ "messages": {
+     "echo": {
+         "request": [{"name": "record", "type": "TestRecord"}],
+         "response": "TestRecord"
+     },
+
+     "error": {
+         "request": [],
+         "response": "null",
+         "errors": ["org.apache.avro.test.errors.TestError"]
+     }
+
+ }
+
+}
+DATUM
+,
+<<<'DATUM'
+{"namespace": "org.apache.avro.test.namespace",
+ "protocol": "TestImplicitNamespace",
+
+ "types": [
+     {"name": "org.apache.avro.test.util.MD5", "type": "fixed", "size": 16},
+     {"name": "ReferencedRecord", "type": "record", 
+       "fields": [ {"name": "foo", "type": "string"} ] },
+     {"name": "TestRecord", "type": "record",
+      "fields": [ {"name": "hash", "type": "org.apache.avro.test.util.MD5"},
+                  {"name": "unqalified", "type": "ReferencedRecord"} ]
+     },
+     {"name": "TestError",
+      "type": "error", "fields": [ {"name": "message", "type": "string"} ]
+     }
+ ],
+
+ "messages": {
+     "echo": {
+         "request": [{"name": "qualified", 
+             "type": "org.apache.avro.test.namespace.TestRecord"}],
+         "response": "TestRecord"
+     },
+
+     "error": {
+         "request": [],
+         "response": "null",
+         "errors": ["org.apache.avro.test.namespace.TestError"]
+     }
+
+ }
+
+}
+DATUM
+,
+<<<'DATUM'
+{"namespace": "org.apache.avro.test.namespace",
+ "protocol": "TestNamespaceTwo",
+
+ "types": [
+     {"name": "org.apache.avro.test.util.MD5", "type": "fixed", "size": 16},
+     {"name": "ReferencedRecord", "type": "record", 
+       "namespace": "org.apache.avro.other.namespace", 
+       "fields": [ {"name": "foo", "type": "string"} ] },
+     {"name": "TestRecord", "type": "record",
+      "fields": [ {"name": "hash", "type": "org.apache.avro.test.util.MD5"},
+                  {"name": "qualified", 
+                    "type": "org.apache.avro.other.namespace.ReferencedRecord"} 
+                ]
+     },
+     {"name": "TestError",
+      "type": "error", "fields": [ {"name": "message", "type": "string"} ]
+     }
+ ],
+
+ "messages": {
+     "echo": {
+         "request": [{"name": "qualified", 
+             "type": "org.apache.avro.test.namespace.TestRecord"}],
+         "response": "TestRecord"
+     },
+
+     "error": {
+         "request": [],
+         "response": "null",
+         "errors": ["org.apache.avro.test.namespace.TestError"]
+     }
+
+ }
+
+}
+DATUM
+,
+<<<'DATUM'
+{"namespace": "org.apache.avro.test.namespace",
+ "protocol": "TestValidRepeatedName",
+
+ "types": [
+     {"name": "org.apache.avro.test.util.MD5", "type": "fixed", "size": 16},
+     {"name": "ReferencedRecord", "type": "record", 
+       "namespace": "org.apache.avro.other.namespace", 
+       "fields": [ {"name": "foo", "type": "string"} ] },
+     {"name": "ReferencedRecord", "type": "record", 
+       "fields": [ {"name": "bar", "type": "double"} ] },
+     {"name": "TestError",
+      "type": "error", "fields": [ {"name": "message", "type": "string"} ]
+     }
+ ],
+
+ "messages": {
+     "echo": {
+         "request": [{"name": "qualified", 
+             "type": "ReferencedRecord"}],
+         "response": "org.apache.avro.other.namespace.ReferencedRecord"
+     },
+
+     "error": {
+         "request": [],
+         "response": "null",
+         "errors": ["org.apache.avro.test.namespace.TestError"]
+     }
+
+ }
+
+}
+DATUM
+,
+<<<'DATUM'
+{"namespace": "org.apache.avro.test.namespace",
+ "protocol": "TestInvalidRepeatedName",
+
+ "types": [
+     {"name": "org.apache.avro.test.util.MD5", "type": "fixed", "size": 16},
+     {"name": "ReferencedRecord", "type": "record", 
+       "fields": [ {"name": "foo", "type": "string"} ] },
+     {"name": "ReferencedRecord", "type": "record", 
+       "fields": [ {"name": "bar", "type": "double"} ] },
+     {"name": "TestError",
+      "type": "error", "fields": [ {"name": "message", "type": "string"} ]
+     }
+ ],
+
+ "messages": {
+     "echo": {
+         "request": [{"name": "qualified", 
+             "type": "ReferencedRecord"}],
+         "response": "org.apache.avro.other.namespace.ReferencedRecord"
+     },
+
+     "error": {
+         "request": [],
+         "response": "null",
+         "errors": ["org.apache.avro.test.namespace.TestError"]
+     }
+
+ }
+
+}
+DATUM
+,
+<<<'DATUM'
+{"namespace": "org.apache.avro.test",
+ "protocol": "BulkData",
+
+ "types": [],
+
+ "messages": {
+
+     "read": {
+         "request": [],
+         "response": "bytes"
+     },
+
+     "write": {
+         "request": [ {"name": "data", "type": "bytes"} ],
+         "response": "null"
+     }
+
+ }
+
+}
+DATUM
+,
+<<<'DATUM'
+{
+  "protocol" : "API",
+  "namespace" : "xyz.api",
+  "types" : [ {
+    "type" : "enum",
+    "name" : "Symbology",
+    "namespace" : "xyz.api.product",
+    "symbols" : [ "OPRA", "CUSIP", "ISIN", "SEDOL" ]
+  }, {
+    "type" : "record",
+    "name" : "Symbol",
+    "namespace" : "xyz.api.product",
+    "fields" : [ {
+      "name" : "symbology",
+      "type" : "xyz.api.product.Symbology"
+    }, {
+      "name" : "symbol",
+      "type" : "string"
+    } ]
+  }, {
+    "type" : "record",
+    "name" : "MultiSymbol",
+    "namespace" : "xyz.api.product",
+    "fields" : [ {
+      "name" : "symbols",
+      "type" : {
+        "type" : "map",
+        "values" : "xyz.api.product.Symbol"
+      }
+    } ]
+  } ],
+  "messages" : {
+  }
+}
+DATUM
+	);
+}

Propchange: avro/trunk/lang/php/test/ProtocolFileTest.php
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message