from Xslt import test_harness
from xml.xslt import XsltException,Error
import basic_test

sheet_str_1 = """<?xml version="1.0" ?>
<!-- Preprocessor for the Schematron XML Schema Language.
    http://www.ascc.net/xml/resource/schematron/schematron.html
    Copyright (C) 1999 Rick Jelliffe and Academia Sinica Computing Centre
    Permission to use granted under GPL or MPL.

    History: 
    1999-10-18 Created RJ
    1999-10-25 In report and assert should use apply-template not value-of
               Thanks to James Clark for this fix
    1999-11-2  Add key element
    1999-12-21 Add ns element: thanks Dave Carlisle for the code
-->
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">

<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

<!-- Category: top-level-element -->
<xsl:output
  method="xml" 
  omit-xml-declaration="no"
  standalone="yes" 
  indent="yes" />


<xsl:template match="schema">
    <axsl:stylesheet>
        <xsl:for-each select="ns">
            <xsl:attribute name="{concat(@prefix,':dummy-for-xmlns')}"
                namespace="{@uri}"/>
        </xsl:for-each>
        <xsl:attribute name="version">1.0</xsl:attribute>
        <xsl:apply-templates mode="do-keys" />
        <xsl:element name='xsl:output' namespace='http://www.w3.org/1999/XSL/Transform'>
            <xsl:attribute name="method">text</xsl:attribute>
        </xsl:element>
        <axsl:template match='/'>
            <xsl:value-of select="title" />
            <xsl:apply-templates mode="do-all-patterns" />
        </axsl:template>

        <xsl:apply-templates />

        <axsl:template match="text()" priority="-1">
            <!-- strip characters -->
        </axsl:template>
    </axsl:stylesheet>
</xsl:template>

<xsl:template match="pattern" mode="do-all-patterns" >
    <axsl:apply-templates mode='M{count(preceding-sibling::*)}' />
</xsl:template>

<xsl:template match="pattern">
    <xsl:apply-templates />

    <axsl:template match="text()" priority="-1" mode="M{count(preceding-sibling::*)}">
        <!-- strip characters -->
    </axsl:template>
</xsl:template>

<xsl:template match="rule">
    <axsl:template match='{@context}' priority='{4000 - count(preceding-sibling::*)}' mode='M{count(../preceding-sibling::*)}'>
        <xsl:apply-templates />
        <axsl:apply-templates mode='M{count(../preceding-sibling::*)}'/>
    </axsl:template>

</xsl:template>

<xsl:template match="name" mode="text">
    <xsl:choose>
        <xsl:when test='@path' >
        <axsl:value-of select="name({@path})" />
        </xsl:when>
        <xsl:otherwise>
        <axsl:value-of select="name(.)" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="assert">
    <axsl:choose> 
        <axsl:when test='{@test}'/>
        <axsl:otherwise>
            <xsl:if test="@role">(<xsl:value-of select="@role"/>) </xsl:if>
In pattern <xsl:value-of select="ancestor::pattern/@name"/>:
            <xsl:apply-templates mode="text" />
        </axsl:otherwise>
    </axsl:choose> 

</xsl:template>

<xsl:template match="report">
    <axsl:if test='{@test}'>
        <xsl:if test="@role">(<xsl:value-of select="@role"/>) </xsl:if>
In pattern <xsl:value-of select="ancestor::pattern/@name"/>:
        <xsl:apply-templates mode="text"/>
    </axsl:if> 
</xsl:template>

<xsl:template match="rule/key" mode="do-keys">
    <axsl:key match="{../@context}" name="@name" path="@use" />
</xsl:template>

<xsl:template match="text()" priority="-1" mode="do-keys" >
    <!-- strip characters -->
</xsl:template>

<xsl:template match="text()" priority="-1" mode="do-all-patterns">
    <!-- strip characters -->
</xsl:template>

<xsl:template match="text()" priority="-1">
    <!-- strip characters -->
</xsl:template>

</xsl:stylesheet>"""

xml_source_1 = """<schema>
  <ns prefix='pp' uri='http://medwired.com/namespaces/practiceportal/1.0'/>
  <ns prefix='html' uri='http://www.w3.org/1999/xhtml'/>
  <ns prefix='xlink' uri='http://www.w3.org/XML/XLink/0.9'/>
  <pattern name='Open Check For Element Structure'>
    <rule context='pp:physician'>
      <assert test='@pp:rid'><name/> missing required rid attribute</assert>
      <report test='../pp:atom_list'>Atom is part of an atom list</report>
      <assert test='pp:metadata'><name/> element is missing a metadata child</assert>
      <assert test='pp:data'><name/> element is missing a data child</assert>
      <assert test='count(*) = 2'>There is an extra element in <name/>.</assert>
    </rule>

    <rule context='pp:physician/pp:metadata'>
      <assert test='pp:editor'><name/> metadata is missing required editor</assert>
      <report test='pp:description'><name/> contains an optional description</report>
    </rule>

    <rule context='pp:physician/pp:data'>
      <assert test='pp:forename'><name/> is missing required forename element</assert>
      <assert test='pp:surname'><name/> is missing required surname element</assert>
      <assert test='pp:degree_suffix'><name/> is missing required degree_suffix element</assert>
      <assert test='pp:education'><name/> is missing required education element</assert>
      <assert test='pp:experience'><name/> is missing required experience element</assert>
      <assert test='pp:licensure'><name/> is missing required licensure element</assert>
      <assert test='pp:board_certified'><name/> is missing required board_certified element</assert>
      <assert test='pp:practices_at'><name/> is missing required practices_at element</assert>
      <report test='pp:middle_initial'><name/> includes optional middle_initial element</report>
      <report test='pp:dea_id'><name/> includes optional dea_id element</report>
      <report test='pp:tax_id'><name/> includes optional tax_id element</report>
      <report test='pp:name_suffix'><name/> includes optional name_suffix element</report>
      <report test='pp:interesting_fact'><name/> includes optional interesting_fact element</report>
      <report test='pp:quote'><name/> includes optional quote element</report>
      <report test='pp:nickname'><name/> includes optional nickname element</report>
      <report test='pp:philosophy'><name/> includes optional philosophy element</report>
      <report test='pp:bio_summary'><name/> includes optional bio_summary element</report>
      <report test='pp:military_service'><name/> includes optional military_service element</report>
      <report test='pp:experience'><name/> includes optional experience element</report>
      <report test='pp:professional_interests'><name/> includes optional professional_interests element</report>
      <report test='pp:honors'><name/> includes optional honors element</report>
      <report test='pp:awards'><name/> includes optional awards element</report>
      <report test='pp:professional_memberships'><name/> includes optional professional_memberships element</report>
      <report test='pp:presentations'><name/> includes optional presentations element</report>
      <report test='pp:personal_background'><name/> includes optional personal_background element</report>
    </rule>

    <rule context='pp:education'>
      <assert test='pp:undergrad|pp:postgrad|pp:medical_school|pp:internship|pp:residency'><name/> missing required elements</assert>
    </rule>

    <rule context='pp:experience|pp:affiliations'>
      <assert test='pp:organization'><name/>  missing required elements</assert>
    </rule>

    <rule context='pp:practices_at'>
      <assert test='pp:practice'><name/> missing required elements</assert>
    </rule>

  </pattern>
</schema>"""


xml_source_2 = """<schema>
  <ns prefix='pp' uri='http://medwired.com/namespaces/practiceportal/1.0'/>
  <ns prefix='html' uri='http://www.w3.org/1999/xhtml'/>
  <ns prefix='xlink' uri='http://www.w3.org/XML/XLink/0.9'/>
  <pattern name='Closed Check For Element Structure'>
    <rule context='pp:page'>
      <assert test='@pp:rid'><name/> atom missing required rid attribute</assert>
      <report test='../pp:atom_list'>Atom is part of an atom list</report>
      <assert test='pp:metadata'><name/> is missing a metadata child</assert>
      <assert test='pp:data'><name/> is missing a data child</assert>
      <assert test='count(*) = 2'>There is an extra element in <name/>.</assert>
    </rule>

    <rule context='pp:page/pp:metadata'>
      <assert test='pp:editor'><name/> is missing required editor</assert>
      <assert test='pp:links'><name/> is missing required links</assert>
      <assert test='pp:parent'><name/> is missing required parent</assert>
      <assert test='pp:children'><name/> is missing required children</assert>
      <report test='pp:see_also'><name/> includes optional see_also</report>
      <report test='pp:mime_type'><name/> includes optional mime_type</report>
      <report test='pp:editor'><name/> includes optional editor</report>
      <assert test='count(pp:editor|pp:links|pp:parent|pp:children|pp:see_also|pp:mime_type) = count(*)'>There is an extra element in <name/>.</assert>
    </rule>

    <rule context='pp:page/pp:data'>
      <assert test='descendant::*[(namespace-uri() != "http://www.w3.org/1999/xhtml")][namespace-uri() != "http://www.w3.org/XML/XLink/0.9"][namespace-uri() != "http://medwired.com/namespaces/practiceportal/1.0"]'>Content element <name/> is neither xhtml or practice-portal instruction.</assert>
    </rule>

  </pattern>
</schema>"""

expected_1="""<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<xsl:stylesheet html:dummy-for-xmlns='' xlink:dummy-for-xmlns='' pp:dummy-for-xmlns='' version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:xlink='http://www.w3.org/XML/XLink/0.9' xmlns:html='http://www.w3.org/1999/xhtml' xmlns:pp='http://medwired.com/namespaces/practiceportal/1.0'>
  <xsl:output method='text'/>
  <xsl:template match='/'><xsl:apply-templates mode='M3'/>
  </xsl:template>
  <xsl:template match='pp:physician' mode='M3' priority='4000'>
    <xsl:choose>
      <xsl:when test='@pp:rid'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> missing required rid attribute</xsl:otherwise>
    </xsl:choose>
    <xsl:if test='../pp:atom_list'>
In pattern Open Check For Element Structure:
        Atom is part of an atom list</xsl:if>
    <xsl:choose>
      <xsl:when test='pp:metadata'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> element is missing a metadata child</xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test='pp:data'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> element is missing a data child</xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test='count(*) = 2'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            There is an extra element in <xsl:value-of select='name(.)'/>.</xsl:otherwise>
    </xsl:choose>
    <xsl:apply-templates mode='M3'/>
  </xsl:template>
  <xsl:template match='pp:physician/pp:metadata' mode='M3' priority='3999'>
    <xsl:choose>
      <xsl:when test='pp:editor'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> metadata is missing required editor</xsl:otherwise>
    </xsl:choose>
    <xsl:if test='pp:description'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> contains an optional description</xsl:if>
    <xsl:apply-templates mode='M3'/>
  </xsl:template>
  <xsl:template match='pp:physician/pp:data' mode='M3' priority='3998'>
    <xsl:choose>
      <xsl:when test='pp:forename'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> is missing required forename element</xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test='pp:surname'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> is missing required surname element</xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test='pp:degree_suffix'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> is missing required degree_suffix element</xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test='pp:education'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> is missing required education element</xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test='pp:experience'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> is missing required experience element</xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test='pp:licensure'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> is missing required licensure element</xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test='pp:board_certified'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> is missing required board_certified element</xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test='pp:practices_at'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> is missing required practices_at element</xsl:otherwise>
    </xsl:choose>
    <xsl:if test='pp:middle_initial'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional middle_initial element</xsl:if>
    <xsl:if test='pp:dea_id'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional dea_id element</xsl:if>
    <xsl:if test='pp:tax_id'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional tax_id element</xsl:if>
    <xsl:if test='pp:name_suffix'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional name_suffix element</xsl:if>
    <xsl:if test='pp:interesting_fact'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional interesting_fact element</xsl:if>
    <xsl:if test='pp:quote'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional quote element</xsl:if>
    <xsl:if test='pp:nickname'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional nickname element</xsl:if>
    <xsl:if test='pp:philosophy'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional philosophy element</xsl:if>
    <xsl:if test='pp:bio_summary'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional bio_summary element</xsl:if>
    <xsl:if test='pp:military_service'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional military_service element</xsl:if>
    <xsl:if test='pp:experience'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional experience element</xsl:if>
    <xsl:if test='pp:professional_interests'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional professional_interests element</xsl:if>
    <xsl:if test='pp:honors'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional honors element</xsl:if>
    <xsl:if test='pp:awards'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional awards element</xsl:if>
    <xsl:if test='pp:professional_memberships'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional professional_memberships element</xsl:if>
    <xsl:if test='pp:presentations'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional presentations element</xsl:if>
    <xsl:if test='pp:personal_background'>
In pattern Open Check For Element Structure:
        <xsl:value-of select='name(.)'/> includes optional personal_background element</xsl:if>
    <xsl:apply-templates mode='M3'/>
  </xsl:template>
  <xsl:template match='pp:education' mode='M3' priority='3997'>
    <xsl:choose>
      <xsl:when test='pp:undergrad|pp:postgrad|pp:medical_school|pp:internship|pp:residency'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> missing required elements</xsl:otherwise>
    </xsl:choose>
    <xsl:apply-templates mode='M3'/>
  </xsl:template>
  <xsl:template match='pp:experience|pp:affiliations' mode='M3' priority='3996'>
    <xsl:choose>
      <xsl:when test='pp:organization'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/>  missing required elements</xsl:otherwise>
    </xsl:choose>
    <xsl:apply-templates mode='M3'/>
  </xsl:template>
  <xsl:template match='pp:practices_at' mode='M3' priority='3995'>
    <xsl:choose>
      <xsl:when test='pp:practice'/>
      <xsl:otherwise>
In pattern Open Check For Element Structure:
            <xsl:value-of select='name(.)'/> missing required elements</xsl:otherwise>
    </xsl:choose>
    <xsl:apply-templates mode='M3'/>
  </xsl:template>
  <xsl:template match='text()' mode='M3' priority='-1'/>
  <xsl:template match='text()' priority='-1'/>
</xsl:stylesheet>"""


expected_2 = basic_test.expected_1

sheet_3 = """<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:template match="/">
    <xsl:apply-templates>
      <foo/>
    </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>
"""
source_3 = """<foo>dummy</foo>"""
expected_3=""""""

def PrintResourceUsage():
    """
    Note: tried

    rusage = resource.getrusage(resource.RUSAGE_SELF )
    print rusage[3:5]

    but it just kept returning '(0,0)'
    """

    os.system('ps uww -p '+str(os.getpid())+'\n')


import sys, types
if sys.hexversion > 0x2000000:
    def filterFunc(cycles):
        if type(cycles[0][0]) is types.ClassType:
            return not issubclass(cycles[0][0], Exception)
        return 0
else:
    filterFunc = lambda cycles: 1


def _DoTest1(tester):
    source = test_harness.FileInfo(uri='Xslt/Core/addr_book1.xml', nsAware=0)
    sty = test_harness.FileInfo(uri='Xslt/Core/addr_book1.xsl')
    xtest = test_harness.XsltTester(source,
                                    [sty],
                                    expected_2,
                                    )
    xtest.test(tester)
    return

def _DoTest2(tester):
    source = test_harness.FileInfo(string=xml_source_1)
    sty = test_harness.FileInfo(string=sheet_str_1)
    xtest = test_harness.XsltTester(source,
                                    [sty],
                                    expected_1,
                                    )
    xtest.test(tester)
    return

    #source = test_harness.FileInfo(string=xml_source_2)
    #sty = test_harness.FileInfo(string=sheet_str_1)
    #xtest = test_harness.XsltTester(source,
    #                                [sty],
    #                                expected_1,
    #                                )

    #res = xtest.test(tester)
    #return res

def _DoTest3(tester):
    source = test_harness.FileInfo(string=source_3)
    sty = test_harness.FileInfo(string=sheet_3)
    xtest = test_harness.XsltTester(source,
                                    [sty],
                                    expected_3,
                                    expectedException = XsltException,
                                    exceptionValues = {'errorCode':Error.ILLEGAL_APPLYTEMPLATE_CHILD},
                                    )
    xtest.test(tester)
    return

tests =[('HTML output',_DoTest1),
        ('XML Ouput ',_DoTest2),
        ('Errors ',_DoTest3),
        ]

def Test(tester):
    from Ft.Lib import Cyclops

    for name, func in tests:
        tester.startGroup(name)
        z = Cyclops.CycleFinder()
        z.install_cycle_filter(filterFunc)
        z.run(func,(tester,))
    
        tester.startTest("Check for Leaks")
        z.find_cycles(1)
        tester.compare(0, len(z.cycles))
        if len(z.cycles):
            z.show_cycles()
        tester.testDone()
        tester.groupDone()

    return
