# coding=utf-8
# Licensed Materials - Property of IBM
# Copyright IBM Corp. 2016
import enum

def _stream_schema(schema):
    if isinstance(schema, StreamSchema):
        return schema
    if isinstance(schema, CommonSchema):
        return schema
    return StreamSchema(str(schema))

class StreamSchema(object) :
    """SPL stream schema."""

    def __init__(self, schema):
        schema = schema.strip()
        self.__spl_type = not schema.startswith("tuple<")
        self.__schema=schema

    def schema(self):
        return self.__schema

    def spl_json(self):
        _splj = {}
        _splj["type"] = 'spltype'
        _splj["value"] = self.schema()
        return _splj

    def extend(self, schema):
        """
        Extend a schema by another
        """
        if self.__spl_type:
           raise TypeError("Not supported for declared SPL types")
        base = self.schema()
        extends = schema.schema()
        new_schema = base[:-1] + ',' + extends[6:]
        return StreamSchema(new_schema)

# XML = StreamSchema("tuple<xml document>")

@enum.unique
class CommonSchema(enum.Enum):
    """
    Common stream schemas for interoperability within Streams applications.
    
    Python - Stream constains Python objects
    Json - Stream contains JSON objects. Streams with schema Json can be published and subscribed between Streams applications implemented in different languages.
    String - Stream contains strings. Streams with schema String can be published and subscribed between Streams applications implemented in different languages.
    Binary - Stream contains binary tuples. NOT YET SUPPORTED IN Python.
    """
    Python = StreamSchema("tuple<blob __spl_po>")
    Json = StreamSchema("tuple<rstring jsonString>")
    String = StreamSchema("tuple<rstring string>")
    Binary = StreamSchema("tuple<blob binary>")

    def schema(self):
        return self.value.schema();

    def spl_json(self):
        return self.value.spl_json()

    def extend(self, schema):
        return self.value.extend(schema)

@@ -534,32 +534,81 @@
  self.__schema%0A%0A
+    def str(self):%0A        return self.__schema%0A%0A
     def spl_json
@@ -1245,23 +1245,398 @@
 ns.%0A
+%0A
     
-%0A    Python
+Streams application can publish streams that are subscribed to by other applications.%0A    Use of common schemas allow streams connections regardless of the implementation%0A%0A    Python applications publish streams using :py:meth:%60~streamsx.topology.topology.Stream.publish%60%0A    and subscribe using :py:meth:%60~streamsx.topology.topology.Topology.subscribe%60.%0A    %0A     * :py:const:%60Python%60
  - S
@@ -1670,20 +1670,35 @@
 cts%0A    
+ * :py:const:%60
 Json
+%60
  - Strea
@@ -1725,65 +1725,466 @@
 cts.
- Streams with schema Json can be published and subscribed
+%0A     * :py:const:%60String%60 - Stream contains strings.%0A     * :py:const:%60Binary%60 - Stream contains binary tuples.%0A    %22%22%22%0A    Python = StreamSchema(%22tuple%3Cblob __spl_po%3E%22)%0A    %22%22%22%0A    Stream where each tuple is a Python object.%0A%0A    Python streams can only be used by Python applications.%0A    %22%22%22%0A    Json = StreamSchema(%22tuple%3Crstring jsonString%3E%22)%0A    %22%22%22%0A    Stream where each tuple is a JSON object.%0A%0A    %60Json%60 can be used as a natural interchange format
  bet
@@ -2200,32 +2200,36 @@
 ams applications
+%0A   
  implemented in 
@@ -2242,91 +2242,326 @@
 ent 
-languages.%0A    String - Stream contains s
+programming languages. All languages supported by%0A    Streams support publishing and subscribing to JSON streams.%0A%0A    Python objects are converted to JSON objects using %60json.dumps(obj)%60.%0A    %22%22%22%0A    S
 tring
-s.
+ =
  Stream
-s with schema 
+Schema(%22tuple%3Crstring string%3E%22)%0A    %22%22%22%0A    Stream where each tuple is a string.%0A%0A    %60
 String
+%60
  can be 
 publ
@@ -2560,32 +2560,44 @@
  be 
-published and subscribed
+used as a natural interchange format
  bet
@@ -2621,16 +2621,20 @@
 ications
+%0A   
  impleme
@@ -2655,90 +2655,185 @@
 ent 
-languages.%0A    Binary - Stream contains binary tuples. NOT YET SUPPORTED IN Python
+programming languages. All languages supported by%0A    Streams support publishing and subscribing to string streams.%0A%0A    Python objects are converted to strings using %60str(obj)%60
 .%0A  
@@ -2834,38 +2834,38 @@
 )%60.%0A    %22%22%22%0A    
-Python
+Binary
  = StreamSchema(
@@ -2880,171 +2880,174 @@
 lob 
-__spl_po%3E%22)%0A    Json = StreamSchema(%22tuple%3Crstring jsonString%3E%22)%0A    String = StreamSchema(%22tuple%3Crstring string%3E%22)%0A    Binary = StreamSchema(%22tuple%3Cblob binary%3E%22)
+binary%3E%22)%0A    %22%22%22%0A    Stream where each tuple is a binary object (sequence of bytes).%0A%0A    .. warning:: %60Binary%60 is not yet supported for Python applications.%0A    %22%22%22
 %0A%0A  
@@ -3104,9 +3104,8 @@
 ma()
-;
 %0A%0A  
@@ -3227,16 +3227,70 @@
 .extend(schema)%0A
+%0A    def str(self):%0A        return str(self.schema())%0A

Improve doc