<commit_before>// Copyright (C) 2010 - 2012 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include "copasi.h"
#include "CEvaluationNode.h"
#include "CEvaluationTree.h"

#include "sbml/math/ASTNode.h"

CEvaluationNodeLogical::CEvaluationNodeLogical():
  CEvaluationNode(CEvaluationNode::INVALID, ""),
  mpLeft(NULL),
  mpRight(NULL)
{}

CEvaluationNodeLogical::CEvaluationNodeLogical(const SubType & subType,
    const Data & data):
  CEvaluationNode((Type)(CEvaluationNode::LOGICAL | subType), data),
  mpLeft(NULL),
  mpRight(NULL)
{
  switch (mType & 0x00FFFFFF)
    {
      case OR:
        mPrecedence = PRECEDENCE_LOGIG_OR;
        break;

      case XOR:
        mPrecedence = PRECEDENCE_LOGIG_XOR;
        break;

      case AND:
        mPrecedence = PRECEDENCE_LOGIG_AND;
        break;

      case EQ:
        mPrecedence = PRECEDENCE_LOGIG_EQ;
        break;

      case NE:
        mPrecedence = PRECEDENCE_LOGIG_NE;
        break;

      case GT:
        mPrecedence = PRECEDENCE_LOGIG_GT;
        break;

      case GE:
        mPrecedence = PRECEDENCE_LOGIG_GE;
        break;

      case LT:
        mPrecedence = PRECEDENCE_LOGIG_LT;
        break;

      case LE:
        mPrecedence = PRECEDENCE_LOGIG_LE;
        break;
    }
}

CEvaluationNodeLogical::CEvaluationNodeLogical(const CEvaluationNodeLogical & src):
  CEvaluationNode(src),
  mpLeft(NULL),
  mpRight(NULL)
{}

CEvaluationNodeLogical::~CEvaluationNodeLogical() {}

bool CEvaluationNodeLogical::compile(const CEvaluationTree * /* pTree */)
{
  mpLeft = static_cast<CEvaluationNode *>(getChild());

  if (mpLeft == NULL) return false;

  mpRight = static_cast<CEvaluationNode *>(mpLeft->getSibling());

  if (mpRight == NULL) return false;

  return (mpRight->getSibling() == NULL); // We must have exactly two children
}

// virtual
std::string CEvaluationNodeLogical::getInfix(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data Infix;

      if (*mpLeft < * (CEvaluationNode *)this)
        Infix = "(" + children[0] + ")";
      else
        Infix = children[0];

      Infix += " " + mData + " ";

      if (!(*(CEvaluationNode *)this < *mpRight))
        Infix += "(" + children[1] + ")";
      else
        Infix += children[1];

      return Infix;
    }
  else
    return "@";
}

// virtual
std::string CEvaluationNodeLogical::getDisplayString(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data DisplayString;

      if (*mpLeft < * (CEvaluationNode *)this)
        DisplayString = "(" + children[0] + ")";
      else
        DisplayString = children[0] + " ";

      DisplayString += mData;

      if (!(*(CEvaluationNode *)this < *mpRight))
        DisplayString += "(" + children[1] + ")";
      else
        DisplayString += " " + children[1];

      return DisplayString;
    }
  else
    return "@";
}

// virtual
std::string CEvaluationNodeLogical::getCCodeString(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data DisplayString;
      Data data;

      switch ((SubType)CEvaluationNode::subType(this->getType()))
        {
          case AND:
            data = "&&";
            break;

          case OR:
            data = "||";
            break;

          case EQ:
            data = "==";
            break;

          case GE:
            data = ">=";
            break;

          case GT:
            data = ">";
            break;

          case LE:
            data = "<=";
            break;

          case LT:
            data = "<";
            break;

          case NE:
            data = "!=";
            break;

          default:
            /*
             * case XOR:
             */
            data = "@";
            break;
        }

      if (*mpLeft < * (CEvaluationNode *)this)
        DisplayString = "(" + children[0] + ")";
      else
        DisplayString = children[0] + " ";

      DisplayString += data;

      if (!(*(CEvaluationNode *)this < *mpRight))
        DisplayString += "(" + children[1] + ")";
      else
        DisplayString += " " + children[1];

      return DisplayString;
    }
  else
    return "@";
}

// virtual
std::string CEvaluationNodeLogical::getBerkeleyMadonnaString(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data DisplayString;
      Data data;

      switch ((SubType)CEvaluationNode::subType(this->getType()))
        {
          case AND:
            data = "AND";
            break;

          case OR:
            data = "OR";
            break;

            /* case XOR:
               break; */
          case EQ:
            data = "=";
            break;

          case GE:
            data = ">=";
            break;

          case GT:
            data = ">";
            break;

          case LE:
            data = "<=";
            break;

          case LT:
            data = "<";
            break;

          case NE:
            data = "<>";
            break;

          default:
            data = "@";
            break;
        }

      if (*mpLeft < * (CEvaluationNode *)this)
        DisplayString = "(" + children[0] + ")";
      else
        DisplayString = children[0] + " ";

      DisplayString += data;

      if (!(*(CEvaluationNode *)this < *mpRight))
        DisplayString += "(" + children[1] + ")";
      else
        DisplayString += " " + children[1];

      return DisplayString;
    }
  else
    return "@";
}

// virtual
std::string CEvaluationNodeLogical::getXPPString(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data DisplayString;
      Data data;

      switch ((SubType)CEvaluationNode::subType(this->getType()))
        {
          case AND:
            data = "&";
            break;

          case OR:
            data = "|";
            break;

          case EQ:
            data = "==";
            break;

          case GE:
            data = ">=";
            break;

          case GT:
            data = ">";
            break;

          case LE:
            data = "<=";
            break;

          case LT:
            data = "<";
            break;

          case NE:
            data = "!=";
            break;

          default:
            /* case XOR: */
            CCopasiMessage(CCopasiMessage::WARNING, " TODO   ");
            data = "@"; //TODO
            break;
        }

      if (*mpLeft < * (CEvaluationNode *)this)
        DisplayString = "(" + children[0] + ")";
      else
        DisplayString = children[0] + " ";

      DisplayString += data;

      if (!(*(CEvaluationNode *)this < *mpRight))
        DisplayString += "(" + children[1] + ")";
      else
        DisplayString += " " + children[1];

      return DisplayString;
    }
  else
    return "@"; //TODO
}

// static
CEvaluationNode * CEvaluationNodeLogical::fromAST(const ASTNode * pASTNode, const std::vector< CEvaluationNode * > & children)
{
  assert(pASTNode->getNumChildren() == children.size());

  size_t i = 0;
  size_t iMax = children.size();

  SubType subType;
  std::string data = "";

  switch (pASTNode->getType())
    {
      case AST_LOGICAL_AND:
        subType = AND;
        data = "and";
        break;

      case AST_LOGICAL_OR:
        subType = OR;
        data = "or";
        break;

      case AST_LOGICAL_XOR:
        subType = XOR;
        data = "xor";
        break;

      case AST_RELATIONAL_EQ:
        subType = EQ;
        data = "eq";
        break;

      case AST_RELATIONAL_GEQ:
        subType = GE;
        data = "ge";
        break;

      case AST_RELATIONAL_GT:
        subType = GT;
        data = "gt";
        break;

      case AST_RELATIONAL_LEQ:
        subType = LE;
        data = "le";
        break;

      case AST_RELATIONAL_LT:
        subType = LT;
        data = "lt";
        break;

      case AST_RELATIONAL_NEQ:
        subType = NE;
        data = "ne";
        break;

      default:
        subType = INVALID;
        break;
    }

  CEvaluationNode* pNode = NULL;
  // convert the two children

  switch (subType)
    {
      case AND:
      case OR:
      case XOR:

        // The number of chidren may vary
        switch (iMax)
          {
            case 0:

              if (subType == AND)
                pNode = new CEvaluationNodeConstant(CEvaluationNodeConstant::TRUE, "TRUE");
              else
                pNode = new CEvaluationNodeConstant(CEvaluationNodeConstant::FALSE, "FALSE");

              break;

            case 1:
              pNode = children[0];
              break;

            default:
            {
              pNode = new CEvaluationNodeLogical(subType, data);
              CEvaluationNode * pCurrent = pNode;

              // We have at least 2 children
              while (i < iMax - 1)
                {
                  // add the first value
                  pCurrent->addChild(children[i++]);

                  switch (iMax - i)
                    {
                      case 1:
                        // We have only 1 more child
                        pCurrent->addChild(children[i++]);
                        break;

                      default:
                        // We have at least 2 more children
                      {
                        // create a new node with the same operator
                        CEvaluationNode * pTmp = new CEvaluationNodeLogical(subType, data);
                        pCurrent->addChild(pTmp);
                        pCurrent = pTmp;
                      }
                      break;
                    }
                }
            }
            break;
          }

        break;

      case EQ:
      case NE:
      case GE:
      case GT:
      case LE:
      case LT:
        // all these are binary
        assert(iMax == 2);
        pNode = new CEvaluationNodeLogical(subType, data);
        pNode->addChild(children[0]);
        pNode->addChild(children[1]);
        break;

      case INVALID:
        // do nothing
        break;
    }

  return pNode;
}

// virtual
bool CEvaluationNodeLogical::isBoolean() const
{return true;}

ASTNode* CEvaluationNodeLogical::toAST(const CCopasiDataModel* pDataModel) const
{
  SubType subType = (SubType)CEvaluationNode::subType(this->getType());
  ASTNode* node = new ASTNode();

  switch (subType)
    {
      case AND:
        node->setType(AST_LOGICAL_AND);
        break;

      case OR:
        node->setType(AST_LOGICAL_OR);
        break;

      case XOR:
        node->setType(AST_LOGICAL_XOR);
        break;

      case EQ:
        node->setType(AST_RELATIONAL_EQ);
        break;

      case NE:
        node->setType(AST_RELATIONAL_NEQ);
        break;

      case GT:
        node->setType(AST_RELATIONAL_GT);
        break;

      case GE:
        node->setType(AST_RELATIONAL_GEQ);
        break;

      case LT:
        node->setType(AST_RELATIONAL_LT);
        break;

      case LE:
        node->setType(AST_RELATIONAL_LEQ);
        break;

      case INVALID:
        break;

      default:
        subType = INVALID;
        break;
    }

  if (subType != INVALID)
    {
      const CEvaluationNode* child1 = dynamic_cast<const CEvaluationNode*>(this->getChild());
      const CEvaluationNode* child2 = dynamic_cast<const CEvaluationNode*>(child1->getSibling());
      node->addChild(child1->toAST(pDataModel));
      node->addChild(child2->toAST(pDataModel));
    }

  return node;
}

#include "utilities/copasimathml.h"

// virtual
std::string CEvaluationNodeLogical::getMMLString(const std::vector< std::string > & children,
    bool /* expand */,
    const std::vector< std::vector< std::string > > & /* variables */) const
{
  std::ostringstream out;

  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      std::string data = "";
      bool flag = false;

      switch ((SubType)CEvaluationNode::subType(this->getType()))
        {
          case AND:
            data = " and ";
            break;

          case OR:
            data = " or ";
            break;

          case XOR:
            data = " xor ";
            break;

          case EQ:
            data = "=";
            break;

          case GE:
            data = ">=";
            break;

          case GT:
            data = ">";
            break;

          case LE:
            data = "<=";
            break;

          case LT:
            data = "<";
            break;

          case NE:
            data = "≠";
            break;

          default:
            /*
             *
             */
            data = "@";
            break;
        }

      out << "<mrow>" << std::endl;

      flag = ((*mpLeft < * (CEvaluationNode *)this));

      if (flag) out << "<mfenced>" << std::endl;

      out << children[0];

      if (flag) out << "</mfenced>" << std::endl;

      out << "<mo>" << data << "</mo>" << std::endl;

      flag = ((*(CEvaluationNode *)this < *mpRight));

      if (!flag) out << "<mfenced>" << std::endl;

      out << children[1];

      if (!flag) out << "</mfenced>" << std::endl;

      out << "</mrow>" << std::endl;
    }

  return out.str();
}
<commit_msg>- fix for bug 1965: missing xor export, now instead of (a @ b) it exports (!a != !b)<commit_after>// Copyright (C) 2010 - 2012 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

// Copyright (C) 2005 - 2007 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc. and EML Research, gGmbH.
// All rights reserved.

#include "copasi.h"
#include "CEvaluationNode.h"
#include "CEvaluationTree.h"

#include "sbml/math/ASTNode.h"

CEvaluationNodeLogical::CEvaluationNodeLogical():
  CEvaluationNode(CEvaluationNode::INVALID, ""),
  mpLeft(NULL),
  mpRight(NULL)
{}

CEvaluationNodeLogical::CEvaluationNodeLogical(const SubType & subType,
    const Data & data):
  CEvaluationNode((Type)(CEvaluationNode::LOGICAL | subType), data),
  mpLeft(NULL),
  mpRight(NULL)
{
  switch (mType & 0x00FFFFFF)
    {
      case OR:
        mPrecedence = PRECEDENCE_LOGIG_OR;
        break;

      case XOR:
        mPrecedence = PRECEDENCE_LOGIG_XOR;
        break;

      case AND:
        mPrecedence = PRECEDENCE_LOGIG_AND;
        break;

      case EQ:
        mPrecedence = PRECEDENCE_LOGIG_EQ;
        break;

      case NE:
        mPrecedence = PRECEDENCE_LOGIG_NE;
        break;

      case GT:
        mPrecedence = PRECEDENCE_LOGIG_GT;
        break;

      case GE:
        mPrecedence = PRECEDENCE_LOGIG_GE;
        break;

      case LT:
        mPrecedence = PRECEDENCE_LOGIG_LT;
        break;

      case LE:
        mPrecedence = PRECEDENCE_LOGIG_LE;
        break;
    }
}

CEvaluationNodeLogical::CEvaluationNodeLogical(const CEvaluationNodeLogical & src):
  CEvaluationNode(src),
  mpLeft(NULL),
  mpRight(NULL)
{}

CEvaluationNodeLogical::~CEvaluationNodeLogical() {}

bool CEvaluationNodeLogical::compile(const CEvaluationTree * /* pTree */)
{
  mpLeft = static_cast<CEvaluationNode *>(getChild());

  if (mpLeft == NULL) return false;

  mpRight = static_cast<CEvaluationNode *>(mpLeft->getSibling());

  if (mpRight == NULL) return false;

  return (mpRight->getSibling() == NULL); // We must have exactly two children
}

// virtual
std::string CEvaluationNodeLogical::getInfix(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data Infix;

      if (*mpLeft < * (CEvaluationNode *)this)
        Infix = "(" + children[0] + ")";
      else
        Infix = children[0];

      Infix += " " + mData + " ";

      if (!(*(CEvaluationNode *)this < *mpRight))
        Infix += "(" + children[1] + ")";
      else
        Infix += children[1];

      return Infix;
    }
  else
    return "@";
}

// virtual
std::string CEvaluationNodeLogical::getDisplayString(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data DisplayString;

      if (*mpLeft < * (CEvaluationNode *)this)
        DisplayString = "(" + children[0] + ")";
      else
        DisplayString = children[0] + " ";

      DisplayString += mData;

      if (!(*(CEvaluationNode *)this < *mpRight))
        DisplayString += "(" + children[1] + ")";
      else
        DisplayString += " " + children[1];

      return DisplayString;
    }
  else
    return "@";
}

// virtual
std::string CEvaluationNodeLogical::getCCodeString(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data DisplayString;
      Data data;
      bool isXor = false;

      switch ((SubType)CEvaluationNode::subType(this->getType()))
        {
          case AND:
            data = "&&";
            break;

          case OR:
            data = "||";
            break;

          case EQ:
            data = "==";
            break;

          case GE:
            data = ">=";
            break;

          case GT:
            data = ">";
            break;

          case LE:
            data = "<=";
            break;

          case LT:
            data = "<";
            break;

          case NE:
            data = "!=";
            break;

          default:
            /*
             * case XOR:
             */
            data = "!=";
            isXor = true;
            break;
        }

      if (isXor)
        DisplayString = " !";
      else
        DisplayString = "";

      if (*mpLeft < * (CEvaluationNode *)this)
        DisplayString += "(" + children[0] + ")";
      else
        DisplayString += children[0] + " ";

      DisplayString += data;

      if (isXor)
        DisplayString += " !";

      if (!(*(CEvaluationNode *)this < *mpRight))
        DisplayString += "(" + children[1] + ")";
      else
        DisplayString += " " + children[1];

      return DisplayString;
    }
  else
    return "@";
}

// virtual
std::string CEvaluationNodeLogical::getBerkeleyMadonnaString(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data DisplayString;
      Data data;

      switch ((SubType)CEvaluationNode::subType(this->getType()))
        {
          case AND:
            data = "AND";
            break;

          case OR:
            data = "OR";
            break;

            /* case XOR:
               break; */
          case EQ:
            data = "=";
            break;

          case GE:
            data = ">=";
            break;

          case GT:
            data = ">";
            break;

          case LE:
            data = "<=";
            break;

          case LT:
            data = "<";
            break;

          case NE:
            data = "<>";
            break;

          default:
            data = "@";
            break;
        }

      if (*mpLeft < * (CEvaluationNode *)this)
        DisplayString = "(" + children[0] + ")";
      else
        DisplayString = children[0] + " ";

      DisplayString += data;

      if (!(*(CEvaluationNode *)this < *mpRight))
        DisplayString += "(" + children[1] + ")";
      else
        DisplayString += " " + children[1];

      return DisplayString;
    }
  else
    return "@";
}

// virtual
std::string CEvaluationNodeLogical::getXPPString(const std::vector< std::string > & children) const
{
  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      Data DisplayString;
      Data data;

      switch ((SubType)CEvaluationNode::subType(this->getType()))
        {
          case AND:
            data = "&";
            break;

          case OR:
            data = "|";
            break;

          case EQ:
            data = "==";
            break;

          case GE:
            data = ">=";
            break;

          case GT:
            data = ">";
            break;

          case LE:
            data = "<=";
            break;

          case LT:
            data = "<";
            break;

          case NE:
            data = "!=";
            break;

          default:
            /* case XOR: */
            CCopasiMessage(CCopasiMessage::WARNING, " TODO   ");
            data = "@"; //TODO
            break;
        }

      if (*mpLeft < * (CEvaluationNode *)this)
        DisplayString = "(" + children[0] + ")";
      else
        DisplayString = children[0] + " ";

      DisplayString += data;

      if (!(*(CEvaluationNode *)this < *mpRight))
        DisplayString += "(" + children[1] + ")";
      else
        DisplayString += " " + children[1];

      return DisplayString;
    }
  else
    return "@"; //TODO
}

// static
CEvaluationNode * CEvaluationNodeLogical::fromAST(const ASTNode * pASTNode, const std::vector< CEvaluationNode * > & children)
{
  assert(pASTNode->getNumChildren() == children.size());

  size_t i = 0;
  size_t iMax = children.size();

  SubType subType;
  std::string data = "";

  switch (pASTNode->getType())
    {
      case AST_LOGICAL_AND:
        subType = AND;
        data = "and";
        break;

      case AST_LOGICAL_OR:
        subType = OR;
        data = "or";
        break;

      case AST_LOGICAL_XOR:
        subType = XOR;
        data = "xor";
        break;

      case AST_RELATIONAL_EQ:
        subType = EQ;
        data = "eq";
        break;

      case AST_RELATIONAL_GEQ:
        subType = GE;
        data = "ge";
        break;

      case AST_RELATIONAL_GT:
        subType = GT;
        data = "gt";
        break;

      case AST_RELATIONAL_LEQ:
        subType = LE;
        data = "le";
        break;

      case AST_RELATIONAL_LT:
        subType = LT;
        data = "lt";
        break;

      case AST_RELATIONAL_NEQ:
        subType = NE;
        data = "ne";
        break;

      default:
        subType = INVALID;
        break;
    }

  CEvaluationNode* pNode = NULL;
  // convert the two children

  switch (subType)
    {
      case AND:
      case OR:
      case XOR:

        // The number of chidren may vary
        switch (iMax)
          {
            case 0:

              if (subType == AND)
                pNode = new CEvaluationNodeConstant(CEvaluationNodeConstant::TRUE, "TRUE");
              else
                pNode = new CEvaluationNodeConstant(CEvaluationNodeConstant::FALSE, "FALSE");

              break;

            case 1:
              pNode = children[0];
              break;

            default:
            {
              pNode = new CEvaluationNodeLogical(subType, data);
              CEvaluationNode * pCurrent = pNode;

              // We have at least 2 children
              while (i < iMax - 1)
                {
                  // add the first value
                  pCurrent->addChild(children[i++]);

                  switch (iMax - i)
                    {
                      case 1:
                        // We have only 1 more child
                        pCurrent->addChild(children[i++]);
                        break;

                      default:
                        // We have at least 2 more children
                      {
                        // create a new node with the same operator
                        CEvaluationNode * pTmp = new CEvaluationNodeLogical(subType, data);
                        pCurrent->addChild(pTmp);
                        pCurrent = pTmp;
                      }
                      break;
                    }
                }
            }
            break;
          }

        break;

      case EQ:
      case NE:
      case GE:
      case GT:
      case LE:
      case LT:
        // all these are binary
        assert(iMax == 2);
        pNode = new CEvaluationNodeLogical(subType, data);
        pNode->addChild(children[0]);
        pNode->addChild(children[1]);
        break;

      case INVALID:
        // do nothing
        break;
    }

  return pNode;
}

// virtual
bool CEvaluationNodeLogical::isBoolean() const
{return true;}

ASTNode* CEvaluationNodeLogical::toAST(const CCopasiDataModel* pDataModel) const
{
  SubType subType = (SubType)CEvaluationNode::subType(this->getType());
  ASTNode* node = new ASTNode();

  switch (subType)
    {
      case AND:
        node->setType(AST_LOGICAL_AND);
        break;

      case OR:
        node->setType(AST_LOGICAL_OR);
        break;

      case XOR:
        node->setType(AST_LOGICAL_XOR);
        break;

      case EQ:
        node->setType(AST_RELATIONAL_EQ);
        break;

      case NE:
        node->setType(AST_RELATIONAL_NEQ);
        break;

      case GT:
        node->setType(AST_RELATIONAL_GT);
        break;

      case GE:
        node->setType(AST_RELATIONAL_GEQ);
        break;

      case LT:
        node->setType(AST_RELATIONAL_LT);
        break;

      case LE:
        node->setType(AST_RELATIONAL_LEQ);
        break;

      case INVALID:
        break;

      default:
        subType = INVALID;
        break;
    }

  if (subType != INVALID)
    {
      const CEvaluationNode* child1 = dynamic_cast<const CEvaluationNode*>(this->getChild());
      const CEvaluationNode* child2 = dynamic_cast<const CEvaluationNode*>(child1->getSibling());
      node->addChild(child1->toAST(pDataModel));
      node->addChild(child2->toAST(pDataModel));
    }

  return node;
}

#include "utilities/copasimathml.h"

// virtual
std::string CEvaluationNodeLogical::getMMLString(const std::vector< std::string > & children,
    bool /* expand */,
    const std::vector< std::vector< std::string > > & /* variables */) const
{
  std::ostringstream out;

  if (const_cast<CEvaluationNodeLogical *>(this)->compile(NULL))
    {
      std::string data = "";
      bool flag = false;

      switch ((SubType)CEvaluationNode::subType(this->getType()))
        {
          case AND:
            data = " and ";
            break;

          case OR:
            data = " or ";
            break;

          case XOR:
            data = " xor ";
            break;

          case EQ:
            data = "=";
            break;

          case GE:
            data = ">=";
            break;

          case GT:
            data = ">";
            break;

          case LE:
            data = "<=";
            break;

          case LT:
            data = "<";
            break;

          case NE:
            data = "≠";
            break;

          default:
            /*
             *
             */
            data = "@";
            break;
        }

      out << "<mrow>" << std::endl;

      flag = ((*mpLeft < * (CEvaluationNode *)this));

      if (flag) out << "<mfenced>" << std::endl;

      out << children[0];

      if (flag) out << "</mfenced>" << std::endl;

      out << "<mo>" << data << "</mo>" << std::endl;

      flag = ((*(CEvaluationNode *)this < *mpRight));

      if (!flag) out << "<mfenced>" << std::endl;

      out << children[1];

      if (!flag) out << "</mfenced>" << std::endl;

      out << "</mrow>" << std::endl;
    }

  return out.str();
}
<|endoftext|>


<commit_before>#pragma once

#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Sparse>

#include "boundary.hpp"
#include "mass_matrix_assembly.hpp"
#include "neumann_boundary_assemble.hpp"
#include "stiffness_matrix_assembly.hpp"

//! Evolves the solution in time using the explicit Forward Euler scheme
//!
//! @param vertices the list of vertices that build the triangular mesh
//! @param triangles the list of indices that represent the triangular mesh
//! @param u0 the initial data
//! @param gamma the parameter gamma (has to do with the boundary conditions)
//! @param m number of timesteps to perform
//! @returns a pair which contains as first parameter the solution at time = 1,
//!          and second parameter the energy evolving over time.
std::pair<Eigen::VectorXd, std::vector<double>> radiativeTimeEvolutionExplicit(const Eigen::MatrixXd &vertices,
                                                                               const Eigen::MatrixXi &triangles,
                                                                               const Eigen::VectorXd &u0,
                                                                               const double           gamma,
                                                                               const int              m) {
	std::vector<double> energy;
	Eigen::VectorXd     u(u0.size());
	u = u0;

	double dt = 1.0 / m;

	// Get the edges, this is used to compute the neumann boundary matrix
	Eigen::MatrixXi edges = getBoundaryEdges(vertices, triangles);

	// Define the needed matrices and solvers

	// (write your solution here)
	for (int timestep = 0; timestep < m; ++timestep) {
		// Step the solution forward in time
		// (write your solution here)

		energy.push_back(u.sum() / u.rows());
	}

	return std::make_pair(u, energy);
}
<commit_msg>Solved series 4 problem 1i<commit_after>#pragma once

#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Sparse>

#include "boundary.hpp"
#include "mass_matrix_assembly.hpp"
#include "neumann_boundary_assemble.hpp"
#include "stiffness_matrix_assembly.hpp"

//! Evolves the solution in time using the explicit Forward Euler scheme
//!
//! @param vertices the list of vertices that build the triangular mesh
//! @param triangles the list of indices that represent the triangular mesh
//! @param u0 the initial data
//! @param gamma the parameter gamma (has to do with the boundary conditions)
//! @param m number of timesteps to perform
//! @returns a pair which contains as first parameter the solution at time = 1,
//!          and second parameter the energy evolving over time.
std::pair<Eigen::VectorXd, std::vector<double>> radiativeTimeEvolutionExplicit(const Eigen::MatrixXd &vertices,
                                                                               const Eigen::MatrixXi &triangles,
                                                                               const Eigen::VectorXd &u0,
                                                                               const double           gamma,
                                                                               const int              m) {
	std::vector<double> energy;
	Eigen::VectorXd     u(u0.size());
	u = u0;

	double dt = 1.0 / m;

	// Get the edges, this is used to compute the neumann boundary matrix
	Eigen::MatrixXi edges = getBoundaryEdges(vertices, triangles);

	// Define the needed matrices and solvers
	SparseMatrix M = assembleMassMatrix(vertices, triangles);
	SparseMatrix A = assembleStiffnessMatrix(vertices, triangles);
	SparseMatrix B = assembleBoundaryMatrix(vertices, edges, gamma);
	A += B;

	Eigen::SimplicialLDLT<SparseMatrix> SolverM;
	SolverM.compute(M);

	if (SolverM.info() != Eigen::Success) {
		throw std::runtime_error("Could not decompose matrix M");
	}

	// (write your solution here)
	for (int timestep = 0; timestep < m; ++timestep) {
		// Step the solution forward in time
		// (write your solution here)
		u += SolverM.solve(-1.0 * dt * A * u).eval();

		energy.push_back(u.sum() / u.rows());
	}

	return std::make_pair(u, energy);
}
<|endoftext|>


<commit_before>/** \file    patch_up_ppns_for_k10plus.cc
 *  \brief   Swaps out all persistent old PPN's with new PPN's.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2019, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <memory>
#include <unordered_map>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <kchashdb.h>
#include "Compiler.h"
#include "DbConnection.h"
#include "DbResultSet.h"
#include "DbRow.h"
#include "MapUtil.h"
#include "MARC.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "UBTools.h"
#include "util.h"
#include "VuFind.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--store-only] marc_input1 [marc_input2 .. marc_inputN]"
            "If --store-only has been specified, no swapping will be performed and only the persistent map file will be overwritten.");
}

struct PPNsAndSigil {
    std::string old_ppn_, old_sigil_, new_ppn_;
public:
    PPNsAndSigil(const std::string &old_ppn, const std::string &old_sigil, const std::string &new_ppn)
        : old_ppn_(old_ppn), old_sigil_(old_sigil), new_ppn_(new_ppn) { }
    PPNsAndSigil() = default;
    PPNsAndSigil(const PPNsAndSigil &other) = default;
};

void LoadMapping(MARC::Reader * const marc_reader,
                 const std::unordered_multimap<std::string, std::string> &already_processed_ppns_and_sigils,
                 std::vector<PPNsAndSigil> * const old_ppns_sigils_and_new_ppns)
{
    // We need to consider the sigil of the old BSZ as well as the K10+ sigil because in future there may also be merges of
    // K10+ entities which will lead to old PPN's being K10+ PPN's.
    auto matcher(RegexMatcher::RegexMatcherFactoryOrDie("^\\((DE-576|DE-627)\\)(.+)"));
    while (const auto record = marc_reader->read()) {
        for (const auto &field : record.getTagRange("035")) {
            const auto subfield_a(field.getFirstSubfieldWithCode('a'));
            if (matcher->matched(subfield_a)) {
                const std::string old_sigil((*matcher)[1]);
                const std::string old_ppn((*matcher)[2]);
                if (not MapUtil::Contains(already_processed_ppns_and_sigils, old_ppn, old_sigil))
                    old_ppns_sigils_and_new_ppns->emplace_back(old_ppn, old_sigil, record.getControlNumber());
            }
        }
    }

    LOG_INFO("Found " + std::to_string(old_ppns_sigils_and_new_ppns->size()) + " new mappings of old PPN's to new PPN's in \""
             + marc_reader->getPath() + "\".\n");
}

void PatchTable(DbConnection * const db_connection, const std::string &table, const std::string &column,
                const std::vector<PPNsAndSigil> &old_ppns_sigils_and_new_ppns)
{
    const unsigned MAX_BATCH_SIZE(100);

    db_connection->queryOrDie("BEGIN");

    unsigned replacement_count(0), batch_size(0);
    for (const auto &old_ppn_sigil_and_new_ppn : old_ppns_sigils_and_new_ppns) {
        ++batch_size;
        db_connection->queryOrDie("UPDATE IGNORE " + table + " SET " + column + "='" + old_ppn_sigil_and_new_ppn.new_ppn_
                                  + "' WHERE " + column + "='" + old_ppn_sigil_and_new_ppn.old_ppn_ + "'");
        replacement_count += db_connection->getNoOfAffectedRows();
        if (batch_size >= MAX_BATCH_SIZE) {
            db_connection->queryOrDie("COMMIT");
            db_connection->queryOrDie("BEGIN");
        }
    }

    db_connection->queryOrDie("COMMIT");

    LOG_INFO("Replaced " + std::to_string(replacement_count) + " rows in " + table + ".");
}

void PatchNotifiedDB(const std::string &user_type, const std::vector<PPNsAndSigil> &old_ppns_sigils_and_new_ppns) {
    const std::string DB_FILENAME(UBTools::GetTuelibPath() + user_type + "_notified.db");
    std::unique_ptr<kyotocabinet::HashDB> db(new kyotocabinet::HashDB());
    if (not (db->open(DB_FILENAME, kyotocabinet::HashDB::OWRITER | kyotocabinet::HashDB::OREADER))) {
        LOG_INFO("\"" + DB_FILENAME + "\" not found!");
        return;
    }

    unsigned updated_count(0);
    for (const auto &ppns_and_sigil : old_ppns_sigils_and_new_ppns) {
        std::string value;
        if (db->get(ppns_and_sigil.old_ppn_, &value)) {
            if (unlikely(not db->remove(ppns_and_sigil.old_ppn_)))
                LOG_ERROR("failed to remove key \"" + ppns_and_sigil.old_ppn_ + "\" from \"" + DB_FILENAME + "\"!");
            if (unlikely(not db->add(ppns_and_sigil.old_ppn_, value)))
                LOG_ERROR("failed to add key \"" + ppns_and_sigil.old_ppn_ + "\" from \"" + DB_FILENAME + "\"!");
            ++updated_count;
        }
    }

    LOG_INFO("Updated " + std::to_string(updated_count) + " entries in \"" + DB_FILENAME + "\".");
}

bool HaveAllPermissions(DbConnection * const db_connection, const std::string &database) {
    const std::string QUERY("SHOW GRANTS FOR '" + db_connection->getUser() + "'@'" + db_connection->getHost() + "'");
    if (not db_connection->query(QUERY)) {
        if (db_connection->getLastErrorCode() == 1141)
            return false;
        LOG_ERROR(QUERY + " failed: " + db_connection->getLastErrorMessage());
    }

    DbResultSet result_set(db_connection->getLastResultSet());
    while (const auto row = result_set.getNextRow()) {
        if (row[0]
            == "GRANT ALL PRIVILEGES ON `" + database + "`.* TO '" + db_connection->getUser() + "'@'" + db_connection->getHost() + "'")
            return true;
    }
    return false;
}

void CheckMySQLPermissions(DbConnection * const db_connection) {
    if (not HaveAllPermissions(db_connection, "vufind"))
        LOG_ERROR("'" + db_connection->getUser() + "'@'" + db_connection->getHost() + "' needs all permissions on the vufind database!");
    if (VuFind::GetTueFindFlavour() == "ixtheo") {
        if (not HaveAllPermissions(db_connection, "ixtheo"))
            LOG_ERROR("'" + db_connection->getUser() + "'@' " + db_connection->getHost()
                      + "' needs all permissions on the ixtheo database!");
    }
}

void AddPPNsAndSigilsToMultiMap(const std::vector<PPNsAndSigil> &old_ppns_sigils_and_new_ppns,
                                std::unordered_multimap<std::string, std::string> * const already_processed_ppns_and_sigils)
{
    for (const auto &old_ppn_sigil_and_new_ppn : old_ppns_sigils_and_new_ppns)
        already_processed_ppns_and_sigils->emplace(std::make_pair(old_ppn_sigil_and_new_ppn.old_ppn_, old_ppn_sigil_and_new_ppn.old_sigil_));
}

} // unnamed namespace

static const std::string ALREADY_SWAPPED_PPNS_MAP_FILE(UBTools::GetTuelibPath() + "k10+_ppn_map.map");

int Main(int argc, char **argv) {
    if (argc < 2)
        Usage();

    bool store_only(false);
    if (std::strcmp(argv[1], "--store-only") == 0) {
        store_only = true;
        --argc, ++argv;
        if (argc < 2)
            Usage();
    }

    DbConnection db_connection; // ub_tools user

    CheckMySQLPermissions(&db_connection);

    std::unordered_multimap<std::string, std::string> already_processed_ppns_and_sigils;
    if (not store_only)
        MapUtil::DeserialiseMap(ALREADY_SWAPPED_PPNS_MAP_FILE, &already_processed_ppns_and_sigils);

    std::vector<PPNsAndSigil> old_ppns_sigils_and_new_ppns;
    for (int arg_no(1); arg_no < argc; ++arg_no) {
        const auto marc_reader(MARC::Reader::Factory(argv[arg_no]));
        LoadMapping(marc_reader.get(), already_processed_ppns_and_sigils, &old_ppns_sigils_and_new_ppns);
    }
    if (old_ppns_sigils_and_new_ppns.empty()) {
        LOG_INFO("nothing to do!");
        return EXIT_SUCCESS;
    }

    if (store_only) {
        AddPPNsAndSigilsToMultiMap(old_ppns_sigils_and_new_ppns, &already_processed_ppns_and_sigils);
        MapUtil::SerialiseMap(ALREADY_SWAPPED_PPNS_MAP_FILE, already_processed_ppns_and_sigils);
        return EXIT_SUCCESS;
    }

    PatchNotifiedDB("ixtheo", old_ppns_sigils_and_new_ppns);
    PatchNotifiedDB("relbib", old_ppns_sigils_and_new_ppns);

    PatchTable(&db_connection, "vufind.resource", "record_id", old_ppns_sigils_and_new_ppns);
    PatchTable(&db_connection, "vufind.record", "record_id", old_ppns_sigils_and_new_ppns);
    PatchTable(&db_connection, "vufind.change_tracker", "id", old_ppns_sigils_and_new_ppns);
    if (VuFind::GetTueFindFlavour() == "ixtheo") {
        PatchTable(&db_connection, "ixtheo.keyword_translations", "ppn", old_ppns_sigils_and_new_ppns);
        PatchTable(&db_connection, "vufind.ixtheo_journal_subscriptions", "journal_control_number_or_bundle_name",
                   old_ppns_sigils_and_new_ppns);
        PatchTable(&db_connection, "vufind.ixtheo_pda_subscriptions", "book_ppn", old_ppns_sigils_and_new_ppns);
        PatchTable(&db_connection, "vufind.relbib_ids", "record_id", old_ppns_sigils_and_new_ppns);
        PatchTable(&db_connection, "vufind.bibstudies_ids", "record_id", old_ppns_sigils_and_new_ppns);
    }

    AddPPNsAndSigilsToMultiMap(old_ppns_sigils_and_new_ppns, &already_processed_ppns_and_sigils);
    MapUtil::SerialiseMap(ALREADY_SWAPPED_PPNS_MAP_FILE, already_processed_ppns_and_sigils);

    return EXIT_SUCCESS;
}
<commit_msg>patch_up_ppns_for_k10plus: create ALREADY_SWAPPED_PPNS_MAP_FILE if not exists<commit_after>/** \file    patch_up_ppns_for_k10plus.cc
 *  \brief   Swaps out all persistent old PPN's with new PPN's.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2019, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <memory>
#include <unordered_map>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <kchashdb.h>
#include "Compiler.h"
#include "DbConnection.h"
#include "DbResultSet.h"
#include "DbRow.h"
#include "FileUtil.h"
#include "MapUtil.h"
#include "MARC.h"
#include "RegexMatcher.h"
#include "StringUtil.h"
#include "UBTools.h"
#include "util.h"
#include "VuFind.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--store-only] marc_input1 [marc_input2 .. marc_inputN]"
            "If --store-only has been specified, no swapping will be performed and only the persistent map file will be overwritten.");
}

struct PPNsAndSigil {
    std::string old_ppn_, old_sigil_, new_ppn_;
public:
    PPNsAndSigil(const std::string &old_ppn, const std::string &old_sigil, const std::string &new_ppn)
        : old_ppn_(old_ppn), old_sigil_(old_sigil), new_ppn_(new_ppn) { }
    PPNsAndSigil() = default;
    PPNsAndSigil(const PPNsAndSigil &other) = default;
};

void LoadMapping(MARC::Reader * const marc_reader,
                 const std::unordered_multimap<std::string, std::string> &already_processed_ppns_and_sigils,
                 std::vector<PPNsAndSigil> * const old_ppns_sigils_and_new_ppns)
{
    // We need to consider the sigil of the old BSZ as well as the K10+ sigil because in future there may also be merges of
    // K10+ entities which will lead to old PPN's being K10+ PPN's.
    auto matcher(RegexMatcher::RegexMatcherFactoryOrDie("^\\((DE-576|DE-627)\\)(.+)"));
    while (const auto record = marc_reader->read()) {
        for (const auto &field : record.getTagRange("035")) {
            const auto subfield_a(field.getFirstSubfieldWithCode('a'));
            if (matcher->matched(subfield_a)) {
                const std::string old_sigil((*matcher)[1]);
                const std::string old_ppn((*matcher)[2]);
                if (not MapUtil::Contains(already_processed_ppns_and_sigils, old_ppn, old_sigil))
                    old_ppns_sigils_and_new_ppns->emplace_back(old_ppn, old_sigil, record.getControlNumber());
            }
        }
    }

    LOG_INFO("Found " + std::to_string(old_ppns_sigils_and_new_ppns->size()) + " new mappings of old PPN's to new PPN's in \""
             + marc_reader->getPath() + "\".\n");
}

void PatchTable(DbConnection * const db_connection, const std::string &table, const std::string &column,
                const std::vector<PPNsAndSigil> &old_ppns_sigils_and_new_ppns)
{
    const unsigned MAX_BATCH_SIZE(100);

    db_connection->queryOrDie("BEGIN");

    unsigned replacement_count(0), batch_size(0);
    for (const auto &old_ppn_sigil_and_new_ppn : old_ppns_sigils_and_new_ppns) {
        ++batch_size;
        db_connection->queryOrDie("UPDATE IGNORE " + table + " SET " + column + "='" + old_ppn_sigil_and_new_ppn.new_ppn_
                                  + "' WHERE " + column + "='" + old_ppn_sigil_and_new_ppn.old_ppn_ + "'");
        replacement_count += db_connection->getNoOfAffectedRows();
        if (batch_size >= MAX_BATCH_SIZE) {
            db_connection->queryOrDie("COMMIT");
            db_connection->queryOrDie("BEGIN");
        }
    }

    db_connection->queryOrDie("COMMIT");

    LOG_INFO("Replaced " + std::to_string(replacement_count) + " rows in " + table + ".");
}

void PatchNotifiedDB(const std::string &user_type, const std::vector<PPNsAndSigil> &old_ppns_sigils_and_new_ppns) {
    const std::string DB_FILENAME(UBTools::GetTuelibPath() + user_type + "_notified.db");
    std::unique_ptr<kyotocabinet::HashDB> db(new kyotocabinet::HashDB());
    if (not (db->open(DB_FILENAME, kyotocabinet::HashDB::OWRITER | kyotocabinet::HashDB::OREADER))) {
        LOG_INFO("\"" + DB_FILENAME + "\" not found!");
        return;
    }

    unsigned updated_count(0);
    for (const auto &ppns_and_sigil : old_ppns_sigils_and_new_ppns) {
        std::string value;
        if (db->get(ppns_and_sigil.old_ppn_, &value)) {
            if (unlikely(not db->remove(ppns_and_sigil.old_ppn_)))
                LOG_ERROR("failed to remove key \"" + ppns_and_sigil.old_ppn_ + "\" from \"" + DB_FILENAME + "\"!");
            if (unlikely(not db->add(ppns_and_sigil.old_ppn_, value)))
                LOG_ERROR("failed to add key \"" + ppns_and_sigil.old_ppn_ + "\" from \"" + DB_FILENAME + "\"!");
            ++updated_count;
        }
    }

    LOG_INFO("Updated " + std::to_string(updated_count) + " entries in \"" + DB_FILENAME + "\".");
}

bool HaveAllPermissions(DbConnection * const db_connection, const std::string &database) {
    const std::string QUERY("SHOW GRANTS FOR '" + db_connection->getUser() + "'@'" + db_connection->getHost() + "'");
    if (not db_connection->query(QUERY)) {
        if (db_connection->getLastErrorCode() == 1141)
            return false;
        LOG_ERROR(QUERY + " failed: " + db_connection->getLastErrorMessage());
    }

    DbResultSet result_set(db_connection->getLastResultSet());
    while (const auto row = result_set.getNextRow()) {
        if (row[0]
            == "GRANT ALL PRIVILEGES ON `" + database + "`.* TO '" + db_connection->getUser() + "'@'" + db_connection->getHost() + "'")
            return true;
    }
    return false;
}

void CheckMySQLPermissions(DbConnection * const db_connection) {
    if (not HaveAllPermissions(db_connection, "vufind"))
        LOG_ERROR("'" + db_connection->getUser() + "'@'" + db_connection->getHost() + "' needs all permissions on the vufind database!");
    if (VuFind::GetTueFindFlavour() == "ixtheo") {
        if (not HaveAllPermissions(db_connection, "ixtheo"))
            LOG_ERROR("'" + db_connection->getUser() + "'@' " + db_connection->getHost()
                      + "' needs all permissions on the ixtheo database!");
    }
}

void AddPPNsAndSigilsToMultiMap(const std::vector<PPNsAndSigil> &old_ppns_sigils_and_new_ppns,
                                std::unordered_multimap<std::string, std::string> * const already_processed_ppns_and_sigils)
{
    for (const auto &old_ppn_sigil_and_new_ppn : old_ppns_sigils_and_new_ppns)
        already_processed_ppns_and_sigils->emplace(std::make_pair(old_ppn_sigil_and_new_ppn.old_ppn_, old_ppn_sigil_and_new_ppn.old_sigil_));
}

} // unnamed namespace

static const std::string ALREADY_SWAPPED_PPNS_MAP_FILE(UBTools::GetTuelibPath() + "k10+_ppn_map.map");

int Main(int argc, char **argv) {
    if (argc < 2)
        Usage();

    bool store_only(false);
    if (std::strcmp(argv[1], "--store-only") == 0) {
        store_only = true;
        --argc, ++argv;
        if (argc < 2)
            Usage();
    }

    DbConnection db_connection; // ub_tools user

    CheckMySQLPermissions(&db_connection);

    std::unordered_multimap<std::string, std::string> already_processed_ppns_and_sigils;
    if (not FileUtil::Exists(ALREADY_SWAPPED_PPNS_MAP_FILE))
        FileUtil::WriteStringOrDie(ALREADY_SWAPPED_PPNS_MAP_FILE, "");
    if (not store_only)
        MapUtil::DeserialiseMap(ALREADY_SWAPPED_PPNS_MAP_FILE, &already_processed_ppns_and_sigils);

    std::vector<PPNsAndSigil> old_ppns_sigils_and_new_ppns;
    for (int arg_no(1); arg_no < argc; ++arg_no) {
        const auto marc_reader(MARC::Reader::Factory(argv[arg_no]));
        LoadMapping(marc_reader.get(), already_processed_ppns_and_sigils, &old_ppns_sigils_and_new_ppns);
    }
    if (old_ppns_sigils_and_new_ppns.empty()) {
        LOG_INFO("nothing to do!");
        return EXIT_SUCCESS;
    }

    if (store_only) {
        AddPPNsAndSigilsToMultiMap(old_ppns_sigils_and_new_ppns, &already_processed_ppns_and_sigils);
        MapUtil::SerialiseMap(ALREADY_SWAPPED_PPNS_MAP_FILE, already_processed_ppns_and_sigils);
        return EXIT_SUCCESS;
    }

    PatchNotifiedDB("ixtheo", old_ppns_sigils_and_new_ppns);
    PatchNotifiedDB("relbib", old_ppns_sigils_and_new_ppns);

    PatchTable(&db_connection, "vufind.resource", "record_id", old_ppns_sigils_and_new_ppns);
    PatchTable(&db_connection, "vufind.record", "record_id", old_ppns_sigils_and_new_ppns);
    PatchTable(&db_connection, "vufind.change_tracker", "id", old_ppns_sigils_and_new_ppns);
    if (VuFind::GetTueFindFlavour() == "ixtheo") {
        PatchTable(&db_connection, "ixtheo.keyword_translations", "ppn", old_ppns_sigils_and_new_ppns);
        PatchTable(&db_connection, "vufind.ixtheo_journal_subscriptions", "journal_control_number_or_bundle_name",
                   old_ppns_sigils_and_new_ppns);
        PatchTable(&db_connection, "vufind.ixtheo_pda_subscriptions", "book_ppn", old_ppns_sigils_and_new_ppns);
        PatchTable(&db_connection, "vufind.relbib_ids", "record_id", old_ppns_sigils_and_new_ppns);
        PatchTable(&db_connection, "vufind.bibstudies_ids", "record_id", old_ppns_sigils_and_new_ppns);
    }

    AddPPNsAndSigilsToMultiMap(old_ppns_sigils_and_new_ppns, &already_processed_ppns_and_sigils);
    MapUtil::SerialiseMap(ALREADY_SWAPPED_PPNS_MAP_FILE, already_processed_ppns_and_sigils);

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#pragma once

#include <graphene/app/plugin.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/operation_history_object.hpp>

namespace graphene { namespace elasticsearch {
   using namespace chain;

//
// Plugins should #define their SPACE_ID's so plugins with
// conflicting SPACE_ID assignments can be compiled into the
// same binary (by simply re-assigning some of the conflicting #defined
// SPACE_ID's in a build script).
//
// Assignment of SPACE_ID's cannot be done at run-time because
// various template automagic depends on them being known at compile
// time.
//
#ifndef ELASTICSEARCH_SPACE_ID
#define ELASTICSEARCH_SPACE_ID 6
#endif

namespace detail
{
    class elasticsearch_plugin_impl;
}

class elasticsearch_plugin : public graphene::app::plugin
{
   public:
      elasticsearch_plugin();
      virtual ~elasticsearch_plugin();

      std::string plugin_name()const override;
      std::string plugin_description()const override;
      virtual void plugin_set_program_options(
         boost::program_options::options_description& cli,
         boost::program_options::options_description& cfg) override;
      virtual void plugin_initialize(const boost::program_options::variables_map& options) override;
      virtual void plugin_startup() override;

      friend class detail::elasticsearch_plugin_impl;
      std::unique_ptr<detail::elasticsearch_plugin_impl> my;
};

struct operation_visitor
{
   typedef void result_type;

   share_type fee_amount;
   asset_id_type fee_asset;

   asset_id_type transfer_asset_id;
   share_type transfer_amount;
   account_id_type transfer_from;
   account_id_type transfer_to;

   void operator()( const graphene::chain::transfer_operation& o )
   {
      fee_asset = o.fee.asset_id;
      fee_amount = o.fee.amount;

      transfer_asset_id = o.amount.asset_id;
      transfer_amount = o.amount.amount;
      transfer_from = o.from;
      transfer_to = o.to;
   }

   object_id_type      fill_order_id;
   account_id_type     fill_account_id;
   asset_id_type       fill_pays_asset_id;
   share_type          fill_pays_amount;
   asset_id_type       fill_receives_asset_id;
   share_type          fill_receives_amount;
   double              fill_fill_price;
   bool                fill_is_maker;

   void operator()( const graphene::chain::fill_order_operation& o )
   {
      fee_asset = o.fee.asset_id;
      fee_amount = o.fee.amount;

      fill_order_id = o.order_id;
      fill_account_id = o.account_id;
      fill_pays_asset_id = o.pays.asset_id;
      fill_pays_amount = o.pays.amount;
      fill_receives_asset_id = o.receives.asset_id;
      fill_receives_amount = o.receives.amount;
      fill_fill_price = o.fill_price.to_real();
      fill_is_maker = o.is_maker;
   }

   template<typename T>
   void operator()( const T& o )
   {
      fee_asset = o.fee.asset_id;
      fee_amount = o.fee.amount;
   }
};

struct operation_history_struct {
   int trx_in_block;
   int op_in_trx;
   std::string operation_result;
   int virtual_op;
   std::string op;
   variant op_object;
};

struct block_struct {
   int block_num;
   fc::time_point_sec block_time;
   std::string trx_id;
};

struct fee_struct {
   asset_id_type asset;
   std::string asset_name;
   share_type amount;
   double amount_units;
};

struct transfer_struct {
   asset_id_type asset;
   std::string asset_name;
   share_type amount;
   double amount_units;
   account_id_type from;
   account_id_type to;
};

struct fill_struct {
   object_id_type order_id;
   account_id_type account_id;
   asset_id_type pays_asset_id;
   std::string pays_asset_name;
   share_type pays_amount;
   double pays_amount_units;
   asset_id_type receives_asset_id;
   std::string receives_asset_name;
   share_type receives_amount;
   double receives_amount_units;
   double fill_price;
   double fill_price_units;
   bool is_maker;
};

struct visitor_struct {
   fee_struct fee_data;
   transfer_struct transfer_data;
   fill_struct fill_data;
};

struct bulk_struct {
   account_transaction_history_object account_history;
   operation_history_struct operation_history;
   int operation_type;
   int operation_id_num;
   block_struct block_data;
   optional<visitor_struct> additional_data;
};

struct adaptor_struct {
   variant adapt(const variant_object& op)
   {
      fc::mutable_variant_object o(op);
      vector<string> keys_to_rename;
      for (auto i = o.begin(); i != o.end(); ++i)
      {
         auto& element = (*i).value();
         if (element.is_object())
         {
            const string& name = (*i).key();
            auto& vo = element.get_object();
            if (vo.contains(name.c_str()))
               keys_to_rename.emplace_back(name);
            element = adapt(vo);
         }
         else if (element.is_array())
            adapt(element.get_array());
      }
      for (const auto& i : keys_to_rename)
      {
         string new_name = i + "_";
         o[new_name] = variant(o[i]);
         o.erase(i);
      }

      if (o.find("memo") != o.end())
      {
         auto& memo = o["memo"];
         if (memo.is_string())
         {
            o["memo_"] = o["memo"];
            o.erase("memo");
         }
         else if (memo.is_object())
         {
            fc::mutable_variant_object tmp(memo.get_object());
            if (tmp.find("nonce") != tmp.end())
            {
               tmp["nonce"] = tmp["nonce"].as_string();
               o["memo"] = tmp;
            }
         }
      }
      if (o.find("new_parameters") != o.end())
      {
         auto& tmp = o["new_parameters"];
         if (tmp.is_object())
         {
            fc::mutable_variant_object tmp2(tmp.get_object());
            if (tmp2.find("current_fees") != tmp2.end())
            {
               tmp2.erase("current_fees");
               o["new_parameters"] = tmp2;
            }
         }
      }
      if (o.find("owner") != o.end() && o["owner"].is_string())
      {
         o["owner_"] = o["owner"].as_string();
         o.erase("owner");
      }
      if (o.find("proposed_ops") != o.end())
      {
         o["proposed_ops"] = fc::json::to_string(o["proposed_ops"]);
      }
      if (o.find("initializer") != o.end())
      {
         o["initializer"] = fc::json::to_string(o["initializer"]);
      }
      if (o.find("policy") != o.end())
      {
         o["policy"] = fc::json::to_string(o["policy"]);
      }
      if (o.find("predicates") != o.end())
      {
         o["predicates"] = fc::json::to_string(o["predicates"]);
      }

      variant v;
      fc::to_variant(o, v, FC_PACK_MAX_DEPTH);
      return v;
   }

   void adapt(fc::variants& v)
   {
      for (auto& array_element : v)
      {
         if (array_element.is_object())
            array_element = adapt(array_element.get_object());
         else if (array_element.is_array())
            adapt(array_element.get_array());
         else
            array_element = array_element.as_string();
      }
   }
};

} } //graphene::elasticsearch

FC_REFLECT( graphene::elasticsearch::operation_history_struct, (trx_in_block)(op_in_trx)(operation_result)(virtual_op)(op)(op_object) )
FC_REFLECT( graphene::elasticsearch::block_struct, (block_num)(block_time)(trx_id) )
FC_REFLECT( graphene::elasticsearch::fee_struct, (asset)(asset_name)(amount)(amount_units) )
FC_REFLECT( graphene::elasticsearch::transfer_struct, (asset)(asset_name)(amount)(amount_units)(from)(to) )
FC_REFLECT( graphene::elasticsearch::fill_struct, (order_id)(account_id)(pays_asset_id)(pays_asset_name)(pays_amount)(pays_amount_units)
                                                  (receives_asset_id)(receives_asset_name)(receives_amount)(receives_amount_units)(fill_price)
                                                  (fill_price_units)(is_maker))
FC_REFLECT( graphene::elasticsearch::visitor_struct, (fee_data)(transfer_data)(fill_data) )
FC_REFLECT( graphene::elasticsearch::bulk_struct, (account_history)(operation_history)(operation_type)(operation_id_num)(block_data)(additional_data) )
<commit_msg>add active_special_authority to adaptor<commit_after>/*
 * Copyright (c) 2017 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#pragma once

#include <graphene/app/plugin.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/operation_history_object.hpp>

namespace graphene { namespace elasticsearch {
   using namespace chain;

//
// Plugins should #define their SPACE_ID's so plugins with
// conflicting SPACE_ID assignments can be compiled into the
// same binary (by simply re-assigning some of the conflicting #defined
// SPACE_ID's in a build script).
//
// Assignment of SPACE_ID's cannot be done at run-time because
// various template automagic depends on them being known at compile
// time.
//
#ifndef ELASTICSEARCH_SPACE_ID
#define ELASTICSEARCH_SPACE_ID 6
#endif

namespace detail
{
    class elasticsearch_plugin_impl;
}

class elasticsearch_plugin : public graphene::app::plugin
{
   public:
      elasticsearch_plugin();
      virtual ~elasticsearch_plugin();

      std::string plugin_name()const override;
      std::string plugin_description()const override;
      virtual void plugin_set_program_options(
         boost::program_options::options_description& cli,
         boost::program_options::options_description& cfg) override;
      virtual void plugin_initialize(const boost::program_options::variables_map& options) override;
      virtual void plugin_startup() override;

      friend class detail::elasticsearch_plugin_impl;
      std::unique_ptr<detail::elasticsearch_plugin_impl> my;
};

struct operation_visitor
{
   typedef void result_type;

   share_type fee_amount;
   asset_id_type fee_asset;

   asset_id_type transfer_asset_id;
   share_type transfer_amount;
   account_id_type transfer_from;
   account_id_type transfer_to;

   void operator()( const graphene::chain::transfer_operation& o )
   {
      fee_asset = o.fee.asset_id;
      fee_amount = o.fee.amount;

      transfer_asset_id = o.amount.asset_id;
      transfer_amount = o.amount.amount;
      transfer_from = o.from;
      transfer_to = o.to;
   }

   object_id_type      fill_order_id;
   account_id_type     fill_account_id;
   asset_id_type       fill_pays_asset_id;
   share_type          fill_pays_amount;
   asset_id_type       fill_receives_asset_id;
   share_type          fill_receives_amount;
   double              fill_fill_price;
   bool                fill_is_maker;

   void operator()( const graphene::chain::fill_order_operation& o )
   {
      fee_asset = o.fee.asset_id;
      fee_amount = o.fee.amount;

      fill_order_id = o.order_id;
      fill_account_id = o.account_id;
      fill_pays_asset_id = o.pays.asset_id;
      fill_pays_amount = o.pays.amount;
      fill_receives_asset_id = o.receives.asset_id;
      fill_receives_amount = o.receives.amount;
      fill_fill_price = o.fill_price.to_real();
      fill_is_maker = o.is_maker;
   }

   template<typename T>
   void operator()( const T& o )
   {
      fee_asset = o.fee.asset_id;
      fee_amount = o.fee.amount;
   }
};

struct operation_history_struct {
   int trx_in_block;
   int op_in_trx;
   std::string operation_result;
   int virtual_op;
   std::string op;
   variant op_object;
};

struct block_struct {
   int block_num;
   fc::time_point_sec block_time;
   std::string trx_id;
};

struct fee_struct {
   asset_id_type asset;
   std::string asset_name;
   share_type amount;
   double amount_units;
};

struct transfer_struct {
   asset_id_type asset;
   std::string asset_name;
   share_type amount;
   double amount_units;
   account_id_type from;
   account_id_type to;
};

struct fill_struct {
   object_id_type order_id;
   account_id_type account_id;
   asset_id_type pays_asset_id;
   std::string pays_asset_name;
   share_type pays_amount;
   double pays_amount_units;
   asset_id_type receives_asset_id;
   std::string receives_asset_name;
   share_type receives_amount;
   double receives_amount_units;
   double fill_price;
   double fill_price_units;
   bool is_maker;
};

struct visitor_struct {
   fee_struct fee_data;
   transfer_struct transfer_data;
   fill_struct fill_data;
};

struct bulk_struct {
   account_transaction_history_object account_history;
   operation_history_struct operation_history;
   int operation_type;
   int operation_id_num;
   block_struct block_data;
   optional<visitor_struct> additional_data;
};

struct adaptor_struct {
   variant adapt(const variant_object& op)
   {
      fc::mutable_variant_object o(op);
      vector<string> keys_to_rename;
      for (auto i = o.begin(); i != o.end(); ++i)
      {
         auto& element = (*i).value();
         if (element.is_object())
         {
            const string& name = (*i).key();
            auto& vo = element.get_object();
            if (vo.contains(name.c_str()))
               keys_to_rename.emplace_back(name);
            element = adapt(vo);
         }
         else if (element.is_array())
            adapt(element.get_array());
      }
      for (const auto& i : keys_to_rename)
      {
         string new_name = i + "_";
         o[new_name] = variant(o[i]);
         o.erase(i);
      }

      if (o.find("memo") != o.end())
      {
         auto& memo = o["memo"];
         if (memo.is_string())
         {
            o["memo_"] = o["memo"];
            o.erase("memo");
         }
         else if (memo.is_object())
         {
            fc::mutable_variant_object tmp(memo.get_object());
            if (tmp.find("nonce") != tmp.end())
            {
               tmp["nonce"] = tmp["nonce"].as_string();
               o["memo"] = tmp;
            }
         }
      }
      if (o.find("new_parameters") != o.end())
      {
         auto& tmp = o["new_parameters"];
         if (tmp.is_object())
         {
            fc::mutable_variant_object tmp2(tmp.get_object());
            if (tmp2.find("current_fees") != tmp2.end())
            {
               tmp2.erase("current_fees");
               o["new_parameters"] = tmp2;
            }
         }
      }
      if (o.find("owner") != o.end() && o["owner"].is_string())
      {
         o["owner_"] = o["owner"].as_string();
         o.erase("owner");
      }
      if (o.find("proposed_ops") != o.end())
      {
         o["proposed_ops"] = fc::json::to_string(o["proposed_ops"]);
      }
      if (o.find("initializer") != o.end())
      {
         o["initializer"] = fc::json::to_string(o["initializer"]);
      }
      if (o.find("policy") != o.end())
      {
         o["policy"] = fc::json::to_string(o["policy"]);
      }
      if (o.find("predicates") != o.end())
      {
         o["predicates"] = fc::json::to_string(o["predicates"]);
      }
      if (o.find("active_special_authority") != o.end())
      {
         o["active_special_authority"] = fc::json::to_string(o["active_special_authority"]);
      }

      variant v;
      fc::to_variant(o, v, FC_PACK_MAX_DEPTH);
      return v;
   }

   void adapt(fc::variants& v)
   {
      for (auto& array_element : v)
      {
         if (array_element.is_object())
            array_element = adapt(array_element.get_object());
         else if (array_element.is_array())
            adapt(array_element.get_array());
         else
            array_element = array_element.as_string();
      }
   }
};

} } //graphene::elasticsearch

FC_REFLECT( graphene::elasticsearch::operation_history_struct, (trx_in_block)(op_in_trx)(operation_result)(virtual_op)(op)(op_object) )
FC_REFLECT( graphene::elasticsearch::block_struct, (block_num)(block_time)(trx_id) )
FC_REFLECT( graphene::elasticsearch::fee_struct, (asset)(asset_name)(amount)(amount_units) )
FC_REFLECT( graphene::elasticsearch::transfer_struct, (asset)(asset_name)(amount)(amount_units)(from)(to) )
FC_REFLECT( graphene::elasticsearch::fill_struct, (order_id)(account_id)(pays_asset_id)(pays_asset_name)(pays_amount)(pays_amount_units)
                                                  (receives_asset_id)(receives_asset_name)(receives_amount)(receives_amount_units)(fill_price)
                                                  (fill_price_units)(is_maker))
FC_REFLECT( graphene::elasticsearch::visitor_struct, (fee_data)(transfer_data)(fill_data) )
FC_REFLECT( graphene::elasticsearch::bulk_struct, (account_history)(operation_history)(operation_type)(operation_id_num)(block_data)(additional_data) )
<|endoftext|>


<commit_before>#include "vlcplugin_win.h"

#include "../common/win32_fullscreen.h"

static HMODULE hDllModule= 0;

HMODULE DllGetModule()
{
    return hDllModule;
};

extern "C"
BOOL WINAPI DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
{
    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH:
            hDllModule = (HMODULE)hModule;
            break;
        default:
            break;
    }
    return TRUE;
};

static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar )
{
    VlcPluginWin *p_plugin = reinterpret_cast<VlcPluginWin *>(GetWindowLongPtr(p_hwnd, GWLP_USERDATA));

    switch( i_msg )
    {
        case WM_ERASEBKGND:
            return 1L;

        case WM_PAINT:
        {
            PAINTSTRUCT paintstruct;
            HDC hdc;
            RECT rect;

            hdc = BeginPaint( p_hwnd, &paintstruct );

            GetClientRect( p_hwnd, &rect );

            FillRect( hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH) );
            SetTextColor(hdc, RGB(255, 255, 255));
            SetBkColor(hdc, RGB(0, 0, 0));
            if( p_plugin->psz_text )
                DrawText( hdc, p_plugin->psz_text, strlen(p_plugin->psz_text), &rect,
                          DT_CENTER|DT_VCENTER|DT_SINGLELINE);

            EndPaint( p_hwnd, &paintstruct );
            return 0L;
        }
        case WM_SIZE:{
            int new_client_width = LOWORD(lpar);
            int new_client_height = HIWORD(lpar);
            //first child will be resized to client area
            HWND hChildWnd = GetWindow(p_hwnd, GW_CHILD);
            if(hChildWnd){
                MoveWindow(hChildWnd, 0, 0, new_client_width, new_client_height, FALSE);
            }
            return 0L;
        }
        case WM_LBUTTONDBLCLK:{
            p_plugin->toggle_fullscreen();
            return 0L;
        }
        default:
            /* delegate to default handler */
            return CallWindowProc( p_plugin->getWindowProc(), p_hwnd,
                                   i_msg, wpar, lpar );
    }
}

VlcPluginWin::VlcPluginWin(NPP instance, NPuint16_t mode) :
    VlcPluginBase(instance, mode),
    pf_wndproc(NULL),
    _WindowsManager(DllGetModule())
{
}

VlcPluginWin::~VlcPluginWin()
{
    destroy_windows();
}

void VlcPluginWin::toggle_fullscreen()
{
    _WindowsManager.ToggleFullScreen();
}

void VlcPluginWin::set_fullscreen(int yes)
{
    if(yes){
        _WindowsManager.StartFullScreen();
    }
    else{
        _WindowsManager.EndFullScreen();
    }
}

int  VlcPluginWin::get_fullscreen()
{
    return _WindowsManager.IsFullScreen();
}

void VlcPluginWin::show_toolbar()
{
    /* TODO */
}

void VlcPluginWin::hide_toolbar()
{
    /* TODO */
}

void VlcPluginWin::update_controls()
{
    /* TODO */
}

bool VlcPluginWin::create_windows()
{
    HWND drawable = (HWND) (getWindow().window);

    /* attach our plugin object */
    SetWindowLongPtr(drawable, GWLP_USERDATA,
                     (LONG_PTR)this);

    /* install our WNDPROC */
    setWindowProc( (WNDPROC)SetWindowLongPtr( drawable,
                                     GWLP_WNDPROC, (LONG_PTR)Manage ) );

    /* change window style to our liking */
    LONG style = GetWindowLong(drawable, GWL_STYLE);
    style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
    SetWindowLong(drawable, GWL_STYLE, style);

    _WindowsManager.CreateWindows(drawable);

    return true;
}

bool VlcPluginWin::resize_windows()
{
    /* TODO */
    HWND drawable = (HWND) (getWindow().window);
    /* Redraw window */
    InvalidateRect( drawable, NULL, TRUE );
    UpdateWindow( drawable );
    return true;
}

bool VlcPluginWin::destroy_windows()
{
    _WindowsManager.DestroyWindows();

    HWND oldwin = (HWND)npwindow.window;
    if( oldwin )
    {
        WNDPROC winproc = getWindowProc();
        if( winproc )
        {
            /* reset WNDPROC */
            SetWindowLongPtr( oldwin, GWLP_WNDPROC, (LONG_PTR)winproc );
            setWindowProc(NULL);
        }
        npwindow.window = NULL;
    }

    return true;
}

void VlcPluginWin::on_media_player_new()
{
    _WindowsManager.LibVlcAttach(libvlc_media_player);
}

void VlcPluginWin::on_media_player_release()
{
    _WindowsManager.LibVlcDetach();
}
<commit_msg>npapi win32: move holder window resizing to resize_window();<commit_after>#include "vlcplugin_win.h"

#include "../common/win32_fullscreen.h"

static HMODULE hDllModule= 0;

HMODULE DllGetModule()
{
    return hDllModule;
};

extern "C"
BOOL WINAPI DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
{
    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH:
            hDllModule = (HMODULE)hModule;
            break;
        default:
            break;
    }
    return TRUE;
};

static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar )
{
    VlcPluginWin *p_plugin = reinterpret_cast<VlcPluginWin *>(GetWindowLongPtr(p_hwnd, GWLP_USERDATA));

    switch( i_msg )
    {
        case WM_ERASEBKGND:
            return 1L;

        case WM_PAINT:
        {
            PAINTSTRUCT paintstruct;
            HDC hdc;
            RECT rect;

            hdc = BeginPaint( p_hwnd, &paintstruct );

            GetClientRect( p_hwnd, &rect );

            FillRect( hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH) );
            SetTextColor(hdc, RGB(255, 255, 255));
            SetBkColor(hdc, RGB(0, 0, 0));
            if( p_plugin->psz_text )
                DrawText( hdc, p_plugin->psz_text, strlen(p_plugin->psz_text), &rect,
                          DT_CENTER|DT_VCENTER|DT_SINGLELINE);

            EndPaint( p_hwnd, &paintstruct );
            return 0L;
        }
        case WM_LBUTTONDBLCLK:{
            p_plugin->toggle_fullscreen();
            return 0L;
        }
        default:
            /* delegate to default handler */
            return CallWindowProc( p_plugin->getWindowProc(), p_hwnd,
                                   i_msg, wpar, lpar );
    }
}

VlcPluginWin::VlcPluginWin(NPP instance, NPuint16_t mode) :
    VlcPluginBase(instance, mode),
    pf_wndproc(NULL),
    _WindowsManager(DllGetModule())
{
}

VlcPluginWin::~VlcPluginWin()
{
    destroy_windows();
}

void VlcPluginWin::toggle_fullscreen()
{
    _WindowsManager.ToggleFullScreen();
}

void VlcPluginWin::set_fullscreen(int yes)
{
    if(yes){
        _WindowsManager.StartFullScreen();
    }
    else{
        _WindowsManager.EndFullScreen();
    }
}

int  VlcPluginWin::get_fullscreen()
{
    return _WindowsManager.IsFullScreen();
}

void VlcPluginWin::show_toolbar()
{
    /* TODO */
}

void VlcPluginWin::hide_toolbar()
{
    /* TODO */
}

void VlcPluginWin::update_controls()
{
    /* TODO */
}

bool VlcPluginWin::create_windows()
{
    HWND drawable = (HWND) (getWindow().window);

    /* attach our plugin object */
    SetWindowLongPtr(drawable, GWLP_USERDATA,
                     (LONG_PTR)this);

    /* install our WNDPROC */
    setWindowProc( (WNDPROC)SetWindowLongPtr( drawable,
                                     GWLP_WNDPROC, (LONG_PTR)Manage ) );

    /* change window style to our liking */
    LONG style = GetWindowLong(drawable, GWL_STYLE);
    style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
    SetWindowLong(drawable, GWL_STYLE, style);

    _WindowsManager.CreateWindows(drawable);

    return true;
}

bool VlcPluginWin::resize_windows()
{
    HWND drawable = (HWND) (getWindow().window);
    RECT rect;
    GetClientRect(drawable, &rect);
    if(!_WindowsManager.IsFullScreen() && _WindowsManager.getHolderWnd()){
        HWND hHolderWnd = _WindowsManager.getHolderWnd()->getHWND();
        MoveWindow(hHolderWnd, 0, 0, rect.right - rect.left, rect.bottom - rect.top, TRUE);
    }
    return true;
}

bool VlcPluginWin::destroy_windows()
{
    _WindowsManager.DestroyWindows();

    HWND oldwin = (HWND)npwindow.window;
    if( oldwin )
    {
        WNDPROC winproc = getWindowProc();
        if( winproc )
        {
            /* reset WNDPROC */
            SetWindowLongPtr( oldwin, GWLP_WNDPROC, (LONG_PTR)winproc );
            setWindowProc(NULL);
        }
        npwindow.window = NULL;
    }

    return true;
}

void VlcPluginWin::on_media_player_new()
{
    _WindowsManager.LibVlcAttach(libvlc_media_player);
}

void VlcPluginWin::on_media_player_release()
{
    _WindowsManager.LibVlcDetach();
}
<|endoftext|>


<commit_before>#include "interpreter.h"

#include <QtCore/QCoreApplication>
#include <QtWidgets/QAction>
#include <QtCore/QDebug>

#include <qrtext/languageToolboxInterface.h>

#include <utils/timelineInterface.h>
#include <utils/tracer.h>
#include <interpreterBase/robotModel/robotModelInterface.h>

using namespace qReal;
using namespace interpreterCore::interpreter;
using namespace interpreterBase::robotModel;

int const maxThreadsCount = 100;

Interpreter::Interpreter(GraphicalModelAssistInterface const &graphicalModelApi
		, LogicalModelAssistInterface &logicalModelApi
		, qReal::gui::MainWindowInterpretersInterface &interpretersInterface
		, qReal::ProjectManagementInterface const &projectManager
		, BlocksFactoryManagerInterface &blocksFactoryManager
		, interpreterBase::robotModel::RobotModelManagerInterface const &robotModelManager
		, qrtext::LanguageToolboxInterface &languageToolbox
		, QAction &connectToRobotAction
		)
	: mGraphicalModelApi(graphicalModelApi)
	, mLogicalModelApi(logicalModelApi)
	, mInterpretersInterface(interpretersInterface)
	, mState(idle)
	, mRobotModelManager(robotModelManager)
	, mBlocksTable(new details::BlocksTable(blocksFactoryManager, robotModelManager))
	, mActionConnectToRobot(connectToRobotAction)
	, mSensorVariablesUpdater(robotModelManager, languageToolbox)
	, mAutoconfigurer(mGraphicalModelApi, *mBlocksTable, *mInterpretersInterface.errorReporter())
	, mLanguageToolbox(languageToolbox)
{
	connect(
			&mRobotModelManager
			, &interpreterBase::robotModel::RobotModelManagerInterface::allDevicesConfigured
			, this
			, &Interpreter::devicesConfiguredSlot
			);

	connect(
			&mRobotModelManager
			, &interpreterBase::robotModel::RobotModelManagerInterface::connected
			, this
			, &Interpreter::connectedSlot
			);

	connect(&projectManager, &qReal::ProjectManagementInterface::beforeOpen, this, &Interpreter::stopRobot);

	connectDevicesConfigurationProvider(&mAutoconfigurer);
}

Interpreter::~Interpreter()
{
	qDeleteAll(mThreads);
	delete mBlocksTable;
}

void Interpreter::interpret()
{
	mInterpretersInterface.errorReporter()->clear();

	if (mRobotModelManager.model().connectionState() != RobotModelInterface::connectedState) {
		mInterpretersInterface.errorReporter()->addInformation(tr("No connection to robot"));
		return;
	}

	if (mState != idle) {
		mInterpretersInterface.errorReporter()->addInformation(tr("Interpreter is already running"));
		return;
	}

	mBlocksTable->clear();
	mState = waitingForDevicesConfiguredToLaunch;

	if (!mAutoconfigurer.configure(mGraphicalModelApi.children(Id::rootId()), mRobotModelManager.model().name())) {
		return;
	}

	mLanguageToolbox.clear();

	/// @todo Temporarily loading initial configuration from a network of SensorConfigurationProviders.
	///       To be done more adequately.
	for (PortInfo const &port : mRobotModelManager.model().configurablePorts()) {
		QString const modelName = mRobotModelManager.model().name();
		DeviceInfo const deviceInfo = currentConfiguration(modelName, port);
		mRobotModelManager.model().configureDevice(port, deviceInfo);
	}

	mRobotModelManager.model().applyConfiguration();
}

void Interpreter::stopRobot()
{
	mSensorVariablesUpdater.suspend();
	mRobotModelManager.model().stopRobot();
	mState = idle;
	qDeleteAll(mThreads);
	mThreads.clear();
	mBlocksTable->setFailure();
	emit stopped();
}

int Interpreter::timeElapsed() const
{
	return mState == interpreting
			? mRobotModelManager.model().timeline().timestamp() - mInterpretationStartedTimestamp
			: 0;
}

void Interpreter::connectedSlot(bool success)
{
	qDebug() << "Interpreter::connectedSlot";

	if (success) {
		if (mRobotModelManager.model().needsConnection()) {
			mInterpretersInterface.errorReporter()->addInformation(tr("Connected successfully"));
		}
	} else {
		utils::Tracer::debug(utils::Tracer::initialization, "Interpreter::connectedSlot"
				, "Robot connection status: " + QString::number(success));
		mInterpretersInterface.errorReporter()->addError(tr("Can't connect to a robot."));
	}

	mActionConnectToRobot.setChecked(success);
}

void Interpreter::devicesConfiguredSlot()
{
	utils::Tracer::debug(utils::Tracer::initialization
			, "Interpreter::devicesConfiguredSlot", "Sensors are configured");

	if (mRobotModelManager.model().connectionState() != RobotModelInterface::connectedState) {
		mInterpretersInterface.errorReporter()->addInformation(tr("No connection to robot"));
		mState = idle;
		return;
	}

	if (mState == waitingForDevicesConfiguredToLaunch) {
		mState = interpreting;
		mInterpretationStartedTimestamp = mRobotModelManager.model().timeline().timestamp();

		mSensorVariablesUpdater.run();

		utils::Tracer::debug(utils::Tracer::initialization
				, "Interpreter::devicesConfiguredSlot", "Starting interpretation");

		Id const &currentDiagramId = mInterpretersInterface.activeDiagram();

		details::Thread * const initialThread = new details::Thread(&mGraphicalModelApi
				, mInterpretersInterface, currentDiagramId, *mBlocksTable);

		emit started();

		addThread(initialThread);
	}
}

void Interpreter::threadStopped()
{
	details::Thread * const thread = static_cast<details::Thread *>(sender());

	mThreads.removeAll(thread);
	delete thread;

	if (mThreads.isEmpty()) {
		stopRobot();
	}
}

void Interpreter::newThread(Id const &startBlockId)
{
	details::Thread * const thread = new details::Thread(&mGraphicalModelApi
			, mInterpretersInterface, *mBlocksTable, startBlockId);

	addThread(thread);
}

void Interpreter::addThread(details::Thread * const thread)
{
	if (mThreads.count() >= maxThreadsCount) {
		reportError(tr("Threads limit exceeded. Maximum threads count is %1").arg(maxThreadsCount));
		stopRobot();
	}

	mThreads.append(thread);
	connect(thread, SIGNAL(stopped()), this, SLOT(threadStopped()));

	connect(thread, &details::Thread::newThread, this, &Interpreter::newThread);

	QCoreApplication::processEvents();
	if (mState != idle) {
		thread->interpret();
	}
}

void Interpreter::connectToRobot()
{
	if (mState == interpreting) {
		return;
	}

	if (mRobotModelManager.model().connectionState() == RobotModelInterface::connectedState) {
		mRobotModelManager.model().stopRobot();
		mRobotModelManager.model().disconnectFromRobot();
	} else {
		mRobotModelManager.model().connectToRobot();
	}

	mActionConnectToRobot.setChecked(
			mRobotModelManager.model().connectionState() == RobotModelInterface::connectedState);
}

void Interpreter::disconnectSlot()
{
	mActionConnectToRobot.setChecked(false);
	stopRobot();
}

void Interpreter::reportError(QString const &message)
{
	mInterpretersInterface.errorReporter()->addError(message);
}
<commit_msg>stop robot before interpretation<commit_after>#include "interpreter.h"

#include <QtCore/QCoreApplication>
#include <QtWidgets/QAction>
#include <QtCore/QDebug>

#include <qrtext/languageToolboxInterface.h>

#include <utils/timelineInterface.h>
#include <utils/tracer.h>
#include <interpreterBase/robotModel/robotModelInterface.h>

using namespace qReal;
using namespace interpreterCore::interpreter;
using namespace interpreterBase::robotModel;

int const maxThreadsCount = 100;

Interpreter::Interpreter(GraphicalModelAssistInterface const &graphicalModelApi
		, LogicalModelAssistInterface &logicalModelApi
		, qReal::gui::MainWindowInterpretersInterface &interpretersInterface
		, qReal::ProjectManagementInterface const &projectManager
		, BlocksFactoryManagerInterface &blocksFactoryManager
		, interpreterBase::robotModel::RobotModelManagerInterface const &robotModelManager
		, qrtext::LanguageToolboxInterface &languageToolbox
		, QAction &connectToRobotAction
		)
	: mGraphicalModelApi(graphicalModelApi)
	, mLogicalModelApi(logicalModelApi)
	, mInterpretersInterface(interpretersInterface)
	, mState(idle)
	, mRobotModelManager(robotModelManager)
	, mBlocksTable(new details::BlocksTable(blocksFactoryManager, robotModelManager))
	, mActionConnectToRobot(connectToRobotAction)
	, mSensorVariablesUpdater(robotModelManager, languageToolbox)
	, mAutoconfigurer(mGraphicalModelApi, *mBlocksTable, *mInterpretersInterface.errorReporter())
	, mLanguageToolbox(languageToolbox)
{
	connect(
			&mRobotModelManager
			, &interpreterBase::robotModel::RobotModelManagerInterface::allDevicesConfigured
			, this
			, &Interpreter::devicesConfiguredSlot
			);

	connect(
			&mRobotModelManager
			, &interpreterBase::robotModel::RobotModelManagerInterface::connected
			, this
			, &Interpreter::connectedSlot
			);

	connect(&projectManager, &qReal::ProjectManagementInterface::beforeOpen, this, &Interpreter::stopRobot);

	connectDevicesConfigurationProvider(&mAutoconfigurer);
}

Interpreter::~Interpreter()
{
	qDeleteAll(mThreads);
	delete mBlocksTable;
}

void Interpreter::interpret()
{
	mInterpretersInterface.errorReporter()->clear();

	if (mRobotModelManager.model().connectionState() != RobotModelInterface::connectedState) {
		mInterpretersInterface.errorReporter()->addInformation(tr("No connection to robot"));
		return;
	}

	if (mState != idle) {
		mInterpretersInterface.errorReporter()->addInformation(tr("Interpreter is already running"));
		return;
	}

	mRobotModelManager.model().stopRobot();
	mBlocksTable->clear();
	mState = waitingForDevicesConfiguredToLaunch;

	if (!mAutoconfigurer.configure(mGraphicalModelApi.children(Id::rootId()), mRobotModelManager.model().name())) {
		return;
	}

	mLanguageToolbox.clear();

	/// @todo Temporarily loading initial configuration from a network of SensorConfigurationProviders.
	///       To be done more adequately.
	for (PortInfo const &port : mRobotModelManager.model().configurablePorts()) {
		QString const modelName = mRobotModelManager.model().name();
		DeviceInfo const deviceInfo = currentConfiguration(modelName, port);
		mRobotModelManager.model().configureDevice(port, deviceInfo);
	}

	mRobotModelManager.model().applyConfiguration();
}

void Interpreter::stopRobot()
{
	mSensorVariablesUpdater.suspend();
	mRobotModelManager.model().stopRobot();
	mState = idle;
	qDeleteAll(mThreads);
	mThreads.clear();
	mBlocksTable->setFailure();
	emit stopped();
}

int Interpreter::timeElapsed() const
{
	return mState == interpreting
			? mRobotModelManager.model().timeline().timestamp() - mInterpretationStartedTimestamp
			: 0;
}

void Interpreter::connectedSlot(bool success)
{
	qDebug() << "Interpreter::connectedSlot";

	if (success) {
		if (mRobotModelManager.model().needsConnection()) {
			mInterpretersInterface.errorReporter()->addInformation(tr("Connected successfully"));
		}
	} else {
		utils::Tracer::debug(utils::Tracer::initialization, "Interpreter::connectedSlot"
				, "Robot connection status: " + QString::number(success));
		mInterpretersInterface.errorReporter()->addError(tr("Can't connect to a robot."));
	}

	mActionConnectToRobot.setChecked(success);
}

void Interpreter::devicesConfiguredSlot()
{
	utils::Tracer::debug(utils::Tracer::initialization
			, "Interpreter::devicesConfiguredSlot", "Sensors are configured");

	if (mRobotModelManager.model().connectionState() != RobotModelInterface::connectedState) {
		mInterpretersInterface.errorReporter()->addInformation(tr("No connection to robot"));
		mState = idle;
		return;
	}

	if (mState == waitingForDevicesConfiguredToLaunch) {
		mState = interpreting;
		mInterpretationStartedTimestamp = mRobotModelManager.model().timeline().timestamp();

		mSensorVariablesUpdater.run();

		utils::Tracer::debug(utils::Tracer::initialization
				, "Interpreter::devicesConfiguredSlot", "Starting interpretation");

		Id const &currentDiagramId = mInterpretersInterface.activeDiagram();

		details::Thread * const initialThread = new details::Thread(&mGraphicalModelApi
				, mInterpretersInterface, currentDiagramId, *mBlocksTable);

		emit started();

		addThread(initialThread);
	}
}

void Interpreter::threadStopped()
{
	details::Thread * const thread = static_cast<details::Thread *>(sender());

	mThreads.removeAll(thread);
	delete thread;

	if (mThreads.isEmpty()) {
		stopRobot();
	}
}

void Interpreter::newThread(Id const &startBlockId)
{
	details::Thread * const thread = new details::Thread(&mGraphicalModelApi
			, mInterpretersInterface, *mBlocksTable, startBlockId);

	addThread(thread);
}

void Interpreter::addThread(details::Thread * const thread)
{
	if (mThreads.count() >= maxThreadsCount) {
		reportError(tr("Threads limit exceeded. Maximum threads count is %1").arg(maxThreadsCount));
		stopRobot();
	}

	mThreads.append(thread);
	connect(thread, SIGNAL(stopped()), this, SLOT(threadStopped()));

	connect(thread, &details::Thread::newThread, this, &Interpreter::newThread);

	QCoreApplication::processEvents();
	if (mState != idle) {
		thread->interpret();
	}
}

void Interpreter::connectToRobot()
{
	if (mState == interpreting) {
		return;
	}

	if (mRobotModelManager.model().connectionState() == RobotModelInterface::connectedState) {
		mRobotModelManager.model().stopRobot();
		mRobotModelManager.model().disconnectFromRobot();
	} else {
		mRobotModelManager.model().connectToRobot();
	}

	mActionConnectToRobot.setChecked(
			mRobotModelManager.model().connectionState() == RobotModelInterface::connectedState);
}

void Interpreter::disconnectSlot()
{
	mActionConnectToRobot.setChecked(false);
	stopRobot();
}

void Interpreter::reportError(QString const &message)
{
	mInterpretersInterface.errorReporter()->addError(message);
}
<|endoftext|>