########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Common/ValidationInfo.py,v 1.9 2003/12/05 06:56:31 mbrown Exp $
"""
(description needed)

Copyright 2003 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

import Schema, DocumentReference

from Ft.Server import FTSERVER_NAMESPACE
from Ft.Server.Server import FtServerServerException, Error
from Ft.Server.Server.Drivers import FtssInputSource
from Ft.Xml import XPath, Domlette

class ValidationType:
    NONE = 1
    SCHEMATRON = 2
    DTD = 3


class ValidationInfo:
    """
    Base class for validation information
    """
    def __init__(self, vType):
        self.validationType = vType


class NoValidation(ValidationInfo):
    def __init__(self):
        ValidationInfo.__init__(self, ValidationType.NONE)

    def validate(self, repo, src, path):
        return 1


class SchematronValidationInfo(ValidationInfo):
    """
    Validation information for a schematron
    """
    def __init__(self, dRef):
        ValidationInfo.__init__(self, ValidationType.SCHEMATRON)
        self.documentReference = dRef

    def validate(self, repo, src, path):
        from Ft.Xml.Xslt import Processor
        validateProc = Processor.Processor()
        sty = self.documentReference.toSchematron(repo)
        validateProc.appendStylesheetInstance(sty)
        # FIXME: path should be URI
        isrc = FtssInputSource.FtssInputSourceFactory.fromString(src, path, repo._driver)
        validationResult = validateProc.run(isrc)
        if validationResult.find('VALIDATION ERROR:') > -1:
            return 0
        return 1


class DtdValidationInfo(ValidationInfo):
    """
    Validation information from a DTD
    """
    def __init__(self, dRef):
        ValidationInfo.__init__(self, ValidationType.DTD)
        self.documentReference = dRef

    def validate(self, repo, src, path):
        raise NotImplementedError("DTD Validation")


def Serialize(v):
    """Serialize validation info"""
    doc = Domlette.Document()
    val = _Serialize(doc, v)
    doc.appendChild(val)
    return doc

def _Serialize(doc, v):
    val = doc.createElementNS(FTSERVER_NAMESPACE, 'ftss:Validator')

    ref = None

    if v.validationType == ValidationType.NONE:
        val.setAttributeNS(None, 'type', Schema.NO_VALIDATION)
    elif v.validationType == ValidationType.SCHEMATRON:
        val.setAttributeNS(None, 'type', Schema.SCHEMATRON_VALIDATION)
        dr = v.documentReference
        ref = DocumentReference._Serialize(doc, dr)
    elif v.validationType == ValidationType.DTD:
        val.setAttributeNS(None, 'type', Schema.DTD_VALIDATION)
        dr = v.documentReference
        ref = DocumentReference._Serialize(doc, dr)

    if ref:
        val.appendChild(ref)
    return val


_validationInfoTypeExpression = XPath.Compile('string(@type)')
_validationInfoDocumentReferenceExpression = XPath.Compile('ftss:DocumentReference')

def _Deserialize(con):

    val_type = _validationInfoTypeExpression.evaluate(con)
    val_type = val_type

    if val_type == Schema.NO_VALIDATION:
        return NoValidation()
    elif val_type == Schema.SCHEMATRON_VALIDATION:
        drn = _validationInfoDocumentReferenceExpression.evaluate(con)
        oNode = con.node
        con.node = drn[0]
        dr = DocumentReference._Deserialize(con)
        validationInfo = SchematronValidationInfo(dr)
        con.node = oNode
    elif val_type == Schema.DTD_VALIDATION:
        drn = _validationInfoDocumentReferenceExpression.evaluate(con)
        oNode = con.node
        con.node = drn[0]
        dr = DocumentReference._Deserialize(con)
        validationInfo = DtdValidationInfo(dr)
        con.node = oNode
    else:
        raise FtServerServerException(Error.UNKNOWN_VALIDATION_TYPE,
                                      type=val_typ)

    return validationInfo
