# a basic test of Bag objects, initially based on a 4suite list message
# from Martin Strohal, 2003-07-09

from cStringIO import StringIO
from Ft.Lib.Uri import OsPathToUri
from Ft.Rdf import Model, Container
from Ft.Rdf.Drivers import Memory
from Ft.Rdf.Serializers.Dom import Serializer
from Ft.Xml.Domlette import PrettyPrint
from Ft.Xml.Lib.TreeCompare import TreeCompare

SCOPE = OsPathToUri(__file__, attemptAbsolute=True) + '-INTERNAL-XML-STRING'

CONTAINER_CONTENTS_1 = ['bogus://example.org/testresource1',
                        'bogus://example.org/testresource2']

EXPECTED_MODEL_1 = """<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <rdf:Bag rdf:ID="%s">
    <rdf:li resource="bogus://example.org/testresource1"/>
    <rdf:li resource="bogus://example.org/testresource2"/>
  </rdf:Bag>
</rdf:RDF>""" % SCOPE

CONTAINER_CONTENTS_2 = ['testliteral1', 'testliteral2']

EXPECTED_MODEL_2 = """<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <rdf:Bag rdf:ID="%s">
    <rdf:li>testliteral1</rdf:li>
    <rdf:li>testliteral2</rdf:li>
  </rdf:Bag>
</rdf:RDF>""" % SCOPE

# TODO:
#
# Add a test that is a mix of literals and resources.
#
# Change the bag tests so that <rdf:li> item order in the expected
# results doesn't matter.
#
# Add tests for the other types of containers


def getModel():
    db = Memory.CreateDb('')
    return Model.Model(db)


def serializeModel(model):
    serializer = Serializer()
    stream = StringIO()
    doc = serializer.serialize(model)
    PrettyPrint(doc, stream)
    return stream.getvalue()


def Test(tester):
    tester.startGroup('RDF Bag creation and serialization')

    tester.startTest('all items are resources')
    bag = Container.Bag(SCOPE)
    for item in CONTAINER_CONTENTS_1:
        bag.append(item)
    model = getModel()

    # addContainer() turns the bag into statements.
    # The items in the bag become the objects of those statements.
    # What can we do here to ensure that these get serialized as resources?
    #
    # Currently, when converted to statements, the object type is
    # forced to be resource; we have no control over it.
    model.addContainer(bag)

    res = serializeModel(model)
    tester.compare(EXPECTED_MODEL_1, res, func=TreeCompare)
    tester.testDone()

    tester.startTest('all items are literals')
    bag = Container.Bag(SCOPE)
    for item in CONTAINER_CONTENTS_2:
        bag.append(item)
    model = getModel()

    # addContainer() turns the bag into statements.
    # The items in the bag become the objects of those statements.
    # What can we do here to ensure that these get serialized as literals?
    #
    # Currently, when converted to statements, the object type is
    # forced to be resource; we have no control over it.
    model.addContainer(bag)

    res = serializeModel(model)
    tester.compare(EXPECTED_MODEL_2, res, func=TreeCompare)
    tester.testDone()

    tester.groupDone()
    return
