// $Id: parsetreeschema.h,v 1.6 2018/01/03 21:33:06 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


#ifndef PARSETREESCHEMA_H
#define PARSETREESCHEMA_H

#include <map>
#include <set>
#include <string>

using std::string;

class ElementInfo
{
  private:
    ElementInfo();      // undefined

    string  m_child;
    bool    m_required;     // if true, parent requires this attribute
    bool    m_oneOnly;      // if true, parent allows only one of this attribute
    bool    m_deprecated;   // if true, ignore and issue warning
  protected:

  public:
    ElementInfo(const string child);
    ElementInfo(const string child, bool required, bool oneOnly);
    virtual ~ElementInfo() ;

    const string & GetChild()       const ;
    bool     GetRequired()    const ;
    bool     GetOneOnly()     const ;
    bool     GetDeprecated()  const ;

    string DebugDump() const;
};

class AttributeInfo
{
  private:
    AttributeInfo();      // undefined

    string  m_name;
    bool    m_required;
  protected:

  public:
    AttributeInfo(const string name, bool required);
    virtual ~AttributeInfo() ;

    const string & GetName()    const ;
    bool     GetRequired()const ;

    string DebugDump() const;
};

struct ElementInfoCompare
{
    bool operator()(const ElementInfo, const ElementInfo) const;
};

struct AttributeInfoCompare
{
    bool operator()(const AttributeInfo, const AttributeInfo) const;
};

typedef std::set<AttributeInfo,AttributeInfoCompare>    attrSet;
typedef std::set<ElementInfo,  ElementInfoCompare>      elemSet;

class VerificationInfo
{
  private:
    attrSet                     m_attributeInfo;
    elemSet                     m_elementInfo;
  protected:
    attrSet::const_iterator findAttr(const string) const;
    elemSet::const_iterator   findElem(const string) const;
  public:
    VerificationInfo() ;
    virtual ~VerificationInfo() ;

    std::set<string>  RequiredAttributes() const;
    std::set<string>  RequiredElements() const;

    bool            AllowsAttribute(const string name) const;
    bool            AllowsElement(const string name) const;
    bool            AllowsAdditionalElements(const string name) const;
    bool            DeprecatedElement(const string name) const;

    void    AddAttribute(bool required, string parentName, string name);
    void    AddElement(bool required, bool onlyOne, string parentName, string name);
    void    AddDeprecatedElement(string parentName, string name);

    string DebugDump() const;
};

class ParseTreeSchema
{
  private:
    std::map<string,VerificationInfo>   m_schema;

  protected:
    void                AddAttribute(bool required, string parent, string attr);
    void                AddSubtag   (bool required, bool onlyOne,  string parent, string child);
    void                DeprecatedSubtag(string parent, string child);
    void                AddTag      (string tagName);
    const VerificationInfo &  getInfo(const string parent, int lineNo) const;

  public:
    ParseTreeSchema();
    virtual ~ParseTreeSchema();

    std::set<string>  RequiredAttributes(const string parent, int lineNo) const;
    std::set<string>  RequiredElements(const string parent, int lineNo) const;

    bool            AllowsAttribute(const string parent, const string name, int lineNo) const;
    bool            AllowsElement(const string parent, const string child, int lineNo) const;
    bool            AllowsAdditionalElements(const string parent, const string child, int lineNo) const;
    bool            DeprecatedElement(const string parent, const string child, int lineNo) const;

    void DebugDump(const string) const;
};

class LamarcSchema  : public ParseTreeSchema
{
  private:
  protected:
  public:
    LamarcSchema();
    virtual ~LamarcSchema();
};

#endif // PARSETREESCHEMA_H

//____________________________________________________________________________________
