/* 
 * $Id: GLSDModuleChecker.cpp,v 1.7 2006/06/27 13:11:40 ozawa Exp $
 *
 * Copyright 2005- ONGS Inc. All rights reserved.
 * 
 * author: Masanori OZAWA (ozawa@ongs.co.jp)
 * version: $Revision: 1.7 $
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY ONGS INC ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL ONGS INC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of the ONGS Inc.
 * 
 */

#include "xdtp.h"
#include "modules/GLSDModuleChecker.h"
#include "Utilities.h"
#include "XMLTool.h"

using namespace XDTP;

GLSDModuleChecker::GLSDModuleChecker()
{
}

GLSDModuleChecker::~GLSDModuleChecker()
{
}

/**
 * 汎用論理構造文書の正当性をチェックします。
 * 
 * @param aDocument ロードした直後のXMLファイル
 * @return 変換処理を中断する場合は false を戻します。
 */
bool GLSDModuleChecker::checkFormat(xmlDocPtr aDocument)
{
    bool result = false;

    XMLTool tool;
    xmlNodePtr node;
    xmlXPathObjectPtr obj;
    xmlNodeSetPtr nodes;
    
    node = xmlDocGetRootElement(aDocument);

    if (xmlStrcmp(node->name, (const xmlChar *)"document")) {
        return false;
    }
    
    if (!checkDocGroup(node)) {
        return false;
    }
    
    obj = tool.getNodeList(node, "./docgroup");
    
    if (!obj) {
        result = false;
    }
    else {
        nodes = obj->nodesetval;
        
        if (1 == nodes->nodeNr) {
            result = checkDocGroup(nodes->nodeTab[0]);
        }
        
        xmlXPathFreeObject(obj);
    }
    
    if (!result) fprintf(stderr, "%s: GLSDModuleChecker: check failed." LINE_SEP, APP_NAME);

    return result;
}

/**
 * DocGroupエレメントの確認。
 * 
 * @param aParentNode
 *            DocGroupの親ノード
 */
bool GLSDModuleChecker::checkDocGroup(xmlNodePtr aParentNode)
{
    bool result = true;
    int count = 0;
    
    XMLTool tool;
    xmlNodePtr node;
    xmlNodeSetPtr nodes;
    xmlXPathObjectPtr obj = tool.getNodeList(aParentNode, "./docgroup");
    xmlXPathObjectPtr children;

    if (obj) {
        nodes = obj->nodesetval;

        for (; result && count < nodes->nodeNr; count++) {
            node = nodes->nodeTab[count];
            children = tool.getNodeList(node, "./*");
            
            if (!children) {
                result = false;
            }
            else {
                if (0 >= children->nodesetval->nodeNr) {
                    result = false;
                }
                else {
                    result = checkDocInfo(node);
                }
                
                xmlXPathFreeObject(children);
            }
        }
        
        xmlXPathFreeObject(obj);
    }
    
    return result;
}

/**
 * DocInfoエレメントの確認。
 * 
 * @param aParentNode
 *            DocInfoの親ノード
 */
bool GLSDModuleChecker::checkDocInfo(xmlNodePtr aParentNode)
{
    bool bp = false;
    bool result = true;
    int count;
    char *endptr;
    Glib::ustring str;
    
    XMLTool tool;
    xmlChar *xchar;
    xmlNodePtr node;
    xmlNodePtr child;
    xmlNodeSetPtr nodes;
    xmlNodeSetPtr childset;
    xmlXPathObjectPtr obj = tool.getNodeList(aParentNode, "./docinfo");
    xmlXPathObjectPtr children;

    if (obj) {
        nodes = obj->nodesetval;
        
        if (1 < nodes->nodeNr) {
            result = false;
        }
        else if (1 == nodes->nodeNr) {
            node = nodes->nodeTab[0];
            children = tool.getNodeList(node, "./*");
            
            if (!children) {
                result = false;
            }
            else if (0 >= children->nodesetval->nodeNr) {
                xmlXPathFreeObject(children);
                result = false;
            }
            else {
                childset = children->nodesetval;
                
                for (count = 0; count < childset->nodeNr; count++) {
                    child = childset->nodeTab[count];
                    
                    if (xmlStrcmp(child->name, (const xmlChar*)"title") == 0 ||
                        xmlStrcmp(child->name, (const xmlChar*)"author") == 0 ||
                        xmlStrcmp(child->name, (const xmlChar*)"firstedition") == 0 ||
                        xmlStrcmp(child->name, (const xmlChar*)"lastmodified") == 0 ||
                        xmlStrcmp(child->name, (const xmlChar*)"copyright") == 0)
                    {
                        bp = false;

                        for (node = child->children; result && node; node = node->next) {
                            if (tool.isElement(node)) {
                                if (xmlStrcmp(node->name, (const xmlChar*)"p") == 0) {
                                    if (bp) result = false;
                                    bp = true;
                                }
                                else result = false;
                            }
                            else if (tool.isText(node)) {
                                xchar = xmlNodeGetContent(node);
                                if (xchar) {
                                    if (0 < Utilities::strTrim((const char*)xchar).length()) result = false;
                                    xmlFree(xchar);
                                }
                            }
                            else if (!tool.isComment(node)) {
                                result = false;
                            }
                        }

                        if (!bp) result = false; // need the 'p' element.
                    }
                    else if (xmlStrcmp(child->name, (const xmlChar*)"initialnumber") == 0) {
                        for (node = child->children; result && node; node = node->next) {
                            if (!tool.isText(node)) result = false;
                        }
                        if (result) {
                            str = tool.getText(child);
                            if (0 >= str.length() || 0 >= strtol(str.c_str(), &endptr, 10) || *endptr != '\0')
                                result = false;
                        }
                    }
                }
                
                xmlXPathFreeObject(children);
            }
        }
        
        xmlXPathFreeObject(obj);
    }
    
    return result;
}


syntax highlighted by Code2HTML, v. 0.9.1