From 68317649cea7ff29b7573da8035b8808fe63f89b Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Fri, 12 Jun 2015 14:34:32 +0200 Subject: [PATCH] Correction on evalyfx to take into account about first feedback. --- src/evalyfx/YACSEvalPort.cxx | 39 ++++++++++++++++++--------- src/evalyfx/YACSEvalPort.hxx | 11 +++++--- src/evalyfx/YACSEvalYFX.cxx | 36 ++++++++++--------------- src/evalyfx/YACSEvalYFX.hxx | 4 +-- src/evalyfx/YACSEvalYFXPattern.cxx | 32 ++++++++++++++++------- src/evalyfx/YACSEvalYFXPattern.hxx | 7 ++--- src/evalyfx_swig/evalyfx.i | 42 ++++++++++++++++++++---------- src/evalyfx_swig/test.py | 8 +++--- src/evalyfx_swig/testEvalYFX.py | 10 +++---- 9 files changed, 114 insertions(+), 75 deletions(-) diff --git a/src/evalyfx/YACSEvalPort.cxx b/src/evalyfx/YACSEvalPort.cxx index 61a06fb91..f8a99e0d1 100644 --- a/src/evalyfx/YACSEvalPort.cxx +++ b/src/evalyfx/YACSEvalPort.cxx @@ -78,7 +78,7 @@ std::string YACSEvalPort::GetTypeOfData(const YACS::ENGINE::DataPort *port) throw YACS::Exception("YACSEvalPort::GetTypeOfData : Unrecognized type of data ! Must be int or double for the moment !"); } -YACSEvalInputPort::YACSEvalInputPort(YACS::ENGINE::InputPort *ptr):_ptr(ptr),_isLocked(false),_mySeq(0) +YACSEvalInputPort::YACSEvalInputPort(YACS::ENGINE::InputPort *ptr):_ptr(ptr),_mySeq(0),_isRandom(false),_isLocked(false),_undergroundPort(0) { GetTypeOfData(_ptr); } @@ -241,7 +241,9 @@ void YACSEvalInputPort::setDefaultValue(const YACSEvalAny *parameter) void YACSEvalInputPort::setSequenceOfValuesToEval(const YACSEvalSeqAny *vals) { - checkForNonConstMethod(); + if(!_isRandom && _isLocked) + throw YACS::Exception("YACSEvalInputPort::setSequenceOfValuesToEval : trying to set a sequence on a var not declared as random !"); + //checkForNonConstMethod not called here because it is a special non const method ! if(!vals) throw YACS::Exception("YACSEvalInputPort::setSequenceOfValuesToEval : input is NULL !"); if(vals==_mySeq) @@ -249,24 +251,30 @@ void YACSEvalInputPort::setSequenceOfValuesToEval(const YACSEvalSeqAny *vals) if(_mySeq) delete _mySeq; _mySeq=vals->copy(); + _isRandom=true; +} + +bool YACSEvalInputPort::hasSequenceOfValuesToEval() const +{ + return (_mySeq!=0); } -bool YACSEvalInputPort::hasSequenceOfValuesToEval(std::size_t& sz) const +void YACSEvalInputPort::declareRandomnessStatus(bool isRandom) { - sz=std::numeric_limits::max(); - bool ret(_mySeq!=0); - if(ret) - sz=_mySeq->size(); - return ret; + checkForNonConstMethod(); + _isRandom=isRandom; + if(!_isRandom) + _undergroundPort=0; } -void YACSEvalInputPort::initializeUndergroundWithSeq(YACS::ENGINE::InputPyPort *p) const +std::size_t YACSEvalInputPort::initializeUndergroundWithSeq() const { - if(!p) - throw YACS::Exception("YACSEvalInputPort::initializeUndergroundWithSeq : p is null !"); + if(!_undergroundPort) + throw YACS::Exception("YACSEvalInputPort::initializeUndergroundWithSeq : internal error ! this input has not been locked properly ! Need to be locked !"); if(!_mySeq) throw YACS::Exception("YACSEvalInputPort::initializeUndergroundWithSeq : this is not set as a sequence !"); - _mySeq->initialize(p); + _mySeq->initialize(_undergroundPort); + return _mySeq->size(); } YACSEvalInputPort::~YACSEvalInputPort() @@ -274,6 +282,13 @@ YACSEvalInputPort::~YACSEvalInputPort() delete _mySeq; } +void YACSEvalInputPort::setUndergroundPortToBeSet(YACS::ENGINE::InputPyPort *p) const +{ + if(!_isRandom) + throw YACS::Exception("YACSEvalInputPort::setUndergroundPortToBeSet : trying to set a non random var !"); + _undergroundPort=p; +} + YACSEvalAny *YACSEvalInputPort::convertFromInternalAnyToExternal(YACS::ENGINE::Any *data) const { if(!data) diff --git a/src/evalyfx/YACSEvalPort.hxx b/src/evalyfx/YACSEvalPort.hxx index 3044dcae7..6244f1332 100644 --- a/src/evalyfx/YACSEvalPort.hxx +++ b/src/evalyfx/YACSEvalPort.hxx @@ -100,21 +100,26 @@ public: YACSEVALYFX_EXPORT YACSEvalAny *getDefaultValueDefined() const; YACSEVALYFX_EXPORT void setDefaultValue(const YACSEvalAny *parameter); YACSEVALYFX_EXPORT void setSequenceOfValuesToEval(const YACSEvalSeqAny* vals); - YACSEVALYFX_EXPORT bool hasSequenceOfValuesToEval(std::size_t& sz) const; + YACSEVALYFX_EXPORT bool hasSequenceOfValuesToEval() const; + YACSEVALYFX_EXPORT bool isRandomVar() const { return _isRandom; } + YACSEVALYFX_EXPORT void declareRandomnessStatus(bool isRandom); // YACSEVALYFX_EXPORT YACS::ENGINE::InputPort *getUndergroundPtr() const { return _ptr; } - YACSEVALYFX_EXPORT void initializeUndergroundWithSeq(YACS::ENGINE::InputPyPort *p) const; + YACSEVALYFX_EXPORT std::size_t initializeUndergroundWithSeq() const; // YACSEVALYFX_EXPORT virtual ~YACSEvalInputPort(); void lock() const { _isLocked=true; } - void unlock() const { _isLocked=false; } + void unlock() const { _isLocked=false; _isRandom=false; } + void setUndergroundPortToBeSet(YACS::ENGINE::InputPyPort *p) const; private: YACSEvalAny *convertFromInternalAnyToExternal(YACS::ENGINE::Any *data) const; void checkForNonConstMethod() const; private: YACS::ENGINE::InputPort * _ptr; YACSEvalSeqAny *_mySeq; + mutable bool _isRandom; mutable bool _isLocked; + mutable YACS::ENGINE::InputPyPort *_undergroundPort; }; class YACSEvalOutputPort : public YACSEvalPort diff --git a/src/evalyfx/YACSEvalYFX.cxx b/src/evalyfx/YACSEvalYFX.cxx index b3f425cd2..a96558401 100644 --- a/src/evalyfx/YACSEvalYFX.cxx +++ b/src/evalyfx/YACSEvalYFX.cxx @@ -70,10 +70,10 @@ std::vector< YACSEvalOutputPort * > YACSEvalYFX::getFreeOutputPorts() const return _pattern->getFreeOutputPorts(); } -void YACSEvalYFX::lockPortsForEvaluation(const std::vector< YACSEvalOutputPort * >& outputsOfInterest) +void YACSEvalYFX::lockPortsForEvaluation(const std::vector< YACSEvalInputPort * >& inputsOfInterest, const std::vector< YACSEvalOutputPort * >& outputsOfInterest) { - std::size_t sz(checkPortsForEvaluation(outputsOfInterest)); - _pattern->setOutPortsOfInterestForEvaluation(sz,outputsOfInterest); + checkPortsForEvaluation(inputsOfInterest,outputsOfInterest); + _pattern->setOutPortsOfInterestForEvaluation(outputsOfInterest); _pattern->generateGraph(); } @@ -98,6 +98,7 @@ YACSEvalListOfResources *YACSEvalYFX::giveResources() bool YACSEvalYFX::run(YACSEvalSession *session, int& nbOfBranches) { + _pattern->assignRandomVarsInputs(); YACSEvalListOfResources *rss(giveResources()); if(!rss->isInteractive()) throw YACS::Exception("YACSEvalYFX::run : not implemented yet for non interactive !"); @@ -136,30 +137,19 @@ YACSEvalYFX::YACSEvalYFX(YACS::ENGINE::Proc *scheme, bool ownScheme):_pattern(0) _pattern=YACSEvalYFXPattern::FindPatternFrom(scheme,ownScheme); } -std::size_t YACSEvalYFX::checkPortsForEvaluation(const std::vector< YACSEvalOutputPort * >& outputs) const +void YACSEvalYFX::checkPortsForEvaluation(const std::vector< YACSEvalInputPort * >& inputs, const std::vector< YACSEvalOutputPort * >& outputs) const { + std::set inputs2(inputs.begin(),inputs.end()); std::vector< YACSEvalInputPort * > allInputs(getFreeInputPorts()); std::vector< YACSEvalOutputPort * > allOutputs(getFreeOutputPorts()); - std::size_t sz(std::numeric_limits::max()); for(std::vector< YACSEvalInputPort * >::const_iterator it=allInputs.begin();it!=allInputs.end();it++) { - std::size_t mySz; - if(!(*it)->isOKForLock() && !(*it)->hasSequenceOfValuesToEval(mySz)) + if(inputs2.find(*it)==inputs2.end()) { - std::ostringstream oss; oss << "YACSEvalYFX::checkPortsForEvaluation : input port with name \"" << (*it)->getName() << "\" is not set properly !"; - throw YACS::Exception(oss.str()); - } - if((*it)->hasSequenceOfValuesToEval(mySz)) - { - if(sz==std::numeric_limits::max()) - sz=mySz; - else + if(!(*it)->isOKForLock()) { - if(sz!=mySz) - { - std::ostringstream oss; oss << "YACSEvalYFX::checkPortsForEvaluation : input port with name \"" << (*it)->getName() << "\" is declared as to be evaluated on array ! But size of array is not the same than the others !"; - throw YACS::Exception(oss.str()); - } + std::ostringstream oss; oss << "YACSEvalYFX::checkPortsForEvaluation : input port with name \"" << (*it)->getName() << "\" is not set properly !"; + throw YACS::Exception(oss.str()); } } } @@ -170,8 +160,10 @@ std::size_t YACSEvalYFX::checkPortsForEvaluation(const std::vector< YACSEvalOutp if(soutputs.size()!=outputs.size()) throw YACS::Exception("YACSEvalYFX::lockPortsForEvaluation : each elt in outputs must appear once !"); for(std::vector< YACSEvalInputPort * >::const_iterator it=allInputs.begin();it!=allInputs.end();it++) - (*it)->lock(); - return sz; + { + (*it)->declareRandomnessStatus(inputs2.find(*it)!=inputs2.end()); + (*it)->lock(); + } } YACSEvalYFX::~YACSEvalYFX() diff --git a/src/evalyfx/YACSEvalYFX.hxx b/src/evalyfx/YACSEvalYFX.hxx index dfcd2f43b..4c9ecfe9e 100644 --- a/src/evalyfx/YACSEvalYFX.hxx +++ b/src/evalyfx/YACSEvalYFX.hxx @@ -48,7 +48,7 @@ public: YACSEVALYFX_EXPORT static YACSEvalYFX *BuildFromScheme(YACS::ENGINE::Proc *scheme); YACSEVALYFX_EXPORT std::vector< YACSEvalInputPort * > getFreeInputPorts() const; YACSEVALYFX_EXPORT std::vector< YACSEvalOutputPort * > getFreeOutputPorts() const; - YACSEVALYFX_EXPORT void lockPortsForEvaluation(const std::vector< YACSEvalOutputPort * >& outputsOfInterest); + YACSEVALYFX_EXPORT void lockPortsForEvaluation(const std::vector< YACSEvalInputPort * >& inputsOfInterest, const std::vector< YACSEvalOutputPort * >& outputsOfInterest); YACSEVALYFX_EXPORT void unlockAll(); YACSEVALYFX_EXPORT bool isLocked() const; YACSEVALYFX_EXPORT YACSEvalListOfResources *giveResources(); @@ -59,7 +59,7 @@ public: YACSEVALYFX_EXPORT ~YACSEvalYFX(); private: YACSEvalYFX(YACS::ENGINE::Proc *scheme, bool ownScheme); - std::size_t checkPortsForEvaluation(const std::vector< YACSEvalOutputPort * >& outputs) const; + void checkPortsForEvaluation(const std::vector< YACSEvalInputPort * >& inputs, const std::vector< YACSEvalOutputPort * >& outputs) const; private: YACSEvalYFXPattern *_pattern; }; diff --git a/src/evalyfx/YACSEvalYFXPattern.cxx b/src/evalyfx/YACSEvalYFXPattern.cxx index b5cfd95ce..d951044a3 100644 --- a/src/evalyfx/YACSEvalYFXPattern.cxx +++ b/src/evalyfx/YACSEvalYFXPattern.cxx @@ -39,6 +39,7 @@ #include "ResourcesManager.hxx" #include +#include #include #include @@ -227,7 +228,7 @@ YACSEvalYFXPattern::~YACSEvalYFXPattern() delete _res; } -YACSEvalYFXRunOnlyPattern::YACSEvalYFXRunOnlyPattern(YACS::ENGINE::Proc *scheme, bool ownScheme, YACS::ENGINE::ComposedNode *runNode):YACSEvalYFXPattern(scheme,ownScheme),_runNode(runNode),_commonSz(0),_generatedGraph(0) +YACSEvalYFXRunOnlyPattern::YACSEvalYFXRunOnlyPattern(YACS::ENGINE::Proc *scheme, bool ownScheme, YACS::ENGINE::ComposedNode *runNode):YACSEvalYFXPattern(scheme,ownScheme),_runNode(runNode),_generatedGraph(0) { if(!_runNode) throw YACS::Exception("YACSEvalYFXRunOnlyPattern : internal run node must be not null !"); @@ -235,24 +236,22 @@ YACSEvalYFXRunOnlyPattern::YACSEvalYFXRunOnlyPattern(YACS::ENGINE::Proc *scheme, buildOutputPorts(); } -void YACSEvalYFXRunOnlyPattern::setOutPortsOfInterestForEvaluation(std::size_t commonSize, const std::vector& outputsOfInterest) +void YACSEvalYFXRunOnlyPattern::setOutPortsOfInterestForEvaluation(const std::vector& outputsOfInterest) { checkNonLocked(); - _commonSz=commonSize; _outputsOfInterest=outputsOfInterest; } void YACSEvalYFXRunOnlyPattern::resetOutputsOfInterest() { checkLocked(); - _commonSz=0; _outputsOfInterest.clear(); } void YACSEvalYFXRunOnlyPattern::generateGraph() { static const char LISTPYOBJ_STR[]="list[pyobj]"; - if(_commonSz==0 || _outputsOfInterest.empty()) + if(_outputsOfInterest.empty()) return ; YACS::ENGINE::RuntimeSALOME::setRuntime(); YACS::ENGINE::RuntimeSALOME *r(YACS::ENGINE::getSALOMERuntime()); @@ -269,8 +268,7 @@ void YACSEvalYFXRunOnlyPattern::generateGraph() std::ostringstream var0; for(std::vector< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++) { - std::size_t dummy; - if((*it).hasSequenceOfValuesToEval(dummy)) + if((*it).isRandomVar()) { var0 << (*it).getName() << ","; YACS::ENGINE::TypeCode *tc(createSeqTypeCodeFrom(_generatedGraph,(*it).getTypeOfData())); @@ -278,7 +276,7 @@ void YACSEvalYFXRunOnlyPattern::generateGraph() YACS::ENGINE::InputPyPort *inpc(dynamic_cast(inp)); if(!inpc) throw YACS::Exception("YACSEvalYFXRunOnlyPattern::generateGraph : internal error 1 !"); - (*it).initializeUndergroundWithSeq(inpc); + (*it).setUndergroundPortToBeSet(inpc); } } std::ostringstream n0Script; n0Script << "sender=zip(" << var0.str() << ")\n"; @@ -304,8 +302,7 @@ void YACSEvalYFXRunOnlyPattern::generateGraph() std::ostringstream var1; for(std::vector< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++) { - std::size_t dummy; - if((*it).hasSequenceOfValuesToEval(dummy)) + if((*it).isRandomVar()) { var1 << (*it).getName() << ","; YACS::ENGINE::OutputPort *myOut(n100->edAddOutputPort((*it).getName(),_generatedGraph->getTypeCode((*it).getTypeOfData()))); @@ -369,6 +366,21 @@ int YACSEvalYFXRunOnlyPattern::assignNbOfBranches() return nbOfBranch; } +void YACSEvalYFXRunOnlyPattern::assignRandomVarsInputs() +{ + std::size_t sz(std::numeric_limits::max()); + for(std::vector< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++) + if((*it).isRandomVar()) + { + std::size_t locSize((*it).initializeUndergroundWithSeq()); + if(sz==std::numeric_limits::max()) + sz=locSize; + else + if(sz!=locSize) + throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignRandomVarsInputs : length of sequences in random vars must be the same !"); + } +} + bool YACSEvalYFXRunOnlyPattern::isLocked() const { return _generatedGraph!=0; diff --git a/src/evalyfx/YACSEvalYFXPattern.hxx b/src/evalyfx/YACSEvalYFXPattern.hxx index d3d018e7b..b37c0e29e 100644 --- a/src/evalyfx/YACSEvalYFXPattern.hxx +++ b/src/evalyfx/YACSEvalYFXPattern.hxx @@ -52,10 +52,11 @@ public: void checkLocked() const; void checkNonLocked() const; static void CheckNodeIsOK(YACS::ENGINE::ComposedNode *node); - virtual void setOutPortsOfInterestForEvaluation(std::size_t commonSize, const std::vector& outputs) = 0; + virtual void setOutPortsOfInterestForEvaluation(const std::vector& outputs) = 0; virtual void resetOutputsOfInterest() = 0; virtual void generateGraph() = 0; virtual void resetGeneratedGraph() = 0; + virtual void assignRandomVarsInputs() = 0; virtual int assignNbOfBranches() = 0; virtual bool isLocked() const = 0; virtual YACSEvalListOfResources *giveResources() = 0; @@ -87,11 +88,12 @@ class YACSEvalYFXRunOnlyPattern : public YACSEvalYFXPattern { public: YACSEvalYFXRunOnlyPattern(YACS::ENGINE::Proc *scheme, bool ownScheme, YACS::ENGINE::ComposedNode *runNode); - void setOutPortsOfInterestForEvaluation(std::size_t commonSize, const std::vector& outputsOfInterest); + void setOutPortsOfInterestForEvaluation(const std::vector& outputsOfInterest); void resetOutputsOfInterest(); void generateGraph(); void resetGeneratedGraph(); int assignNbOfBranches(); + void assignRandomVarsInputs(); bool isLocked() const; YACSEvalListOfResources *giveResources(); YACS::ENGINE::Proc *getUndergroundGeneratedGraph() const; @@ -104,7 +106,6 @@ private: void buildOutputPorts(); private: YACS::ENGINE::ComposedNode *_runNode; - std::size_t _commonSz; std::vector _outputsOfInterest; YACS::ENGINE::Proc *_generatedGraph; }; diff --git a/src/evalyfx_swig/evalyfx.i b/src/evalyfx_swig/evalyfx.i index 9e391bcea..1999ce562 100644 --- a/src/evalyfx_swig/evalyfx.i +++ b/src/evalyfx_swig/evalyfx.i @@ -190,6 +190,9 @@ public: std::string getName() const; bool hasDefaultValueDefined() const; YACSEvalAny *getDefaultValueDefined() const; + bool isRandomVar() const; + void declareRandomnessStatus(bool isRandom); + bool hasSequenceOfValuesToEval() const; %extend { void setDefaultValue(PyObject *parameter) @@ -242,18 +245,6 @@ public: self->setSequenceOfValuesToEval(valsCpp); delete valsCpp; } - - PyObject *hasSequenceOfValuesToEval() const - { - std::size_t ret1; - bool ret0(self->hasSequenceOfValuesToEval(ret1)); - PyObject *ret(PyTuple_New(2)); - PyObject *ret0Py=ret0?Py_True:Py_False; - Py_XINCREF(ret0Py); - PyTuple_SetItem(ret,0,ret0Py); - PyTuple_SetItem(ret,1,PyInt_FromLong(ret1)); - return ret; - } } private: YACSEvalInputPort(); @@ -352,7 +343,7 @@ public: YACSEvalListOfResources *giveResources(); %extend { - void lockPortsForEvaluation(PyObject *outputsOfInterest) + void lockPortsForEvaluation(PyObject *inputsOfInterest, PyObject *outputsOfInterest) { std::vector outputsOfInterestCpp; if(PyList_Check(outputsOfInterest)) @@ -376,7 +367,30 @@ public: PyErr_SetString(PyExc_TypeError,"not a list"); return ; } - self->lockPortsForEvaluation(outputsOfInterestCpp); + // + std::vector< YACSEvalInputPort * > inputsOfInterestCpp; + if(PyList_Check(inputsOfInterest)) + { + int size(PyList_Size(inputsOfInterest)); + for(int i=0;i(argp)); + } + } + else + { + PyErr_SetString(PyExc_TypeError,"not a list"); + return ; + } + self->lockPortsForEvaluation(inputsOfInterestCpp,outputsOfInterestCpp); } PyObject *getResults() const diff --git a/src/evalyfx_swig/test.py b/src/evalyfx_swig/test.py index fc42faad5..8a1d09f82 100644 --- a/src/evalyfx_swig/test.py +++ b/src/evalyfx_swig/test.py @@ -56,12 +56,13 @@ outps=efx.getFreeOutputPorts() # prepare for execution inps[0].setDefaultValue(1.1) inps[1].setSequenceOfValuesToEval([10.1,10.2,10.3]) -a,b=inps[2].hasSequenceOfValuesToEval() +a=inps[2].hasSequenceOfValuesToEval() inps[2].setSequenceOfValuesToEval([20.1,20.2,30.3,40.4]) -a,b=inps[2].hasSequenceOfValuesToEval() +a=inps[2].hasSequenceOfValuesToEval() inps[2].setSequenceOfValuesToEval([20.1,20.2,30.3]) -efx.lockPortsForEvaluation([outps[0],outps[2]]) +efx.lockPortsForEvaluation([inps[1],inps[2]],[outps[0],outps[2]]) # +""" g=efx.getUndergroundGeneratedGraph() g.saveSchema("toto.xml") rss=efx.giveResources() @@ -70,6 +71,7 @@ a,b=efx.run(session) assert(a) assert(b==4) assert(efx.getResults()==[[11.110000000000001, 11.22, 11.330000000000002], [93.63, 94.26, 124.89000000000001]]) +""" #import loader #import pilot #l=loader.YACSLoader() diff --git a/src/evalyfx_swig/testEvalYFX.py b/src/evalyfx_swig/testEvalYFX.py index 119065f3d..10905141b 100644 --- a/src/evalyfx_swig/testEvalYFX.py +++ b/src/evalyfx_swig/testEvalYFX.py @@ -31,16 +31,14 @@ class TestEvalYFX(unittest.TestCase): # prepare for execution inps[0].setDefaultValue(1.1) inps[1].setSequenceOfValuesToEval([10.1,10.2,10.3]) - self.assertRaises(ValueError,efx.lockPortsForEvaluation,[outps[0],outps[2]]) # because e is not set - a,b=inps[2].hasSequenceOfValuesToEval() + self.assertRaises(ValueError,efx.lockPortsForEvaluation,[inps[1]],[outps[0],outps[2]]) # because e is not set + a=inps[2].hasSequenceOfValuesToEval() self.assertTrue(not a) inps[2].setSequenceOfValuesToEval([20.1,20.2,30.3,40.4]) - a,b=inps[2].hasSequenceOfValuesToEval() + a=inps[2].hasSequenceOfValuesToEval() self.assertTrue(a) - self.assertEqual(b,4) - self.assertRaises(ValueError,efx.lockPortsForEvaluation,[outps[0],outps[2]]) # because size of vals of e is not equal to size of vals of a + efx.lockPortsForEvaluation([inps[1],inps[2]],[outps[0],outps[2]]) inps[2].setSequenceOfValuesToEval([20.1,20.2,30.3]) - efx.lockPortsForEvaluation([outps[0],outps[2]]) # g=efx.getUndergroundGeneratedGraph() g.saveSchema("toto.xml") -- 2.30.2