blob: 30eaa1a08458ff1eb049b49b7d66a05a79844210 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "ExternalViewLogger.hxx"
#include <iostream>
#include <boost/assert.hpp>
#include <stdio.h>
#ifdef WNT
#define SNPRINTF(buffer, size, format, args) _snprintf(buffer, size, format, args)
#else
#define SNPRINTF(buffer, size, format, args) snprintf(buffer, size, format, args)
#endif
using namespace std;
namespace util
{
NodeDescription::NodeDescription(const string& parent, const string& refersTo, const string& value, bool inUse) :
mParentNodeId(parent),
mRefersToNodeId(refersTo),
mNodeValue(value),
mInUse(inUse)
{}
ExternalViewLoggerImpl::ExternalViewLoggerImpl(const string& fileName) :
mFileName(fileName),
mFile(fileName.c_str())
{
if (!mFile)
throw "Cannot open file";
}
string ExternalViewLoggerImpl::getNewStyleName()
{
static int i = 0;
char buff[20];
SNPRINTF(buff, sizeof(buff), "Style_%d", i++);
return string(buff);
}
void ExternalViewLoggerImpl::beginTree()
{
mParentNodeStack.push("");
}
void ExternalViewLoggerImpl::dumpNodeContainer(const std::string& fileName)
{
std::ofstream file(fileName.c_str());
NodeContainer_t::iterator iter = mNodeContainer.begin();
NodeContainer_t::iterator iter_end = mNodeContainer.end();
for (; iter != iter_end; ++iter)
{
file << iter->first << string(" ") << iter->second->mParentNodeId << string(" ") << iter->second->mRefersToNodeId << string(" ") << iter->second->mNodeValue << endl;
}
}
void ExternalViewLoggerImpl::endTree()
{
//dumpNodeContainer(mFileName + string(".dmp"));
mFile << "digraph {" << endl;
mFile << "Root [shape=box, color=grey];" << endl;
while (!mParentNodeStack.empty())
mParentNodeStack.pop();
mParentNodeStack.push("Root");
NodeContainer_t::iterator iter = mNodeContainer.begin();
NodeContainer_t::iterator iter_end = mNodeContainer.end();
for (; iter != iter_end; ++iter)
{
if (isUnreferencedLeaf(iter->first))
{
string newStyleName = getNewStyleName();
mFile << newStyleName << " [shape=box];" << endl;
mFile << mParentNodeStack.top() << " -> " << newStyleName << endl;
mParentNodeStack.push(newStyleName);
dumpTree(iter->first);
mParentNodeStack.pop();
}
}
mFile << "}" << endl;
}
void ExternalViewLoggerImpl::beginNode(const std::string& nodeId, const std::string& value, const std::string& refersToNodeId, bool inUse)
{
mNodeContainer.insert(
NodeContainer_t::value_type(nodeId,
NodeDescription::Pointer_t(new NodeDescription(mParentNodeStack.top(), refersToNodeId, value, inUse))));
mParentNodeStack.push(nodeId);
}
void ExternalViewLoggerImpl::endNode(const std::string& nodeId)
{
mParentNodeStack.pop();
}
bool ExternalViewLoggerImpl::isLeaf(const std::string& nodeId)
{
bool isLeaf = true;
NodeContainer_t::const_iterator iter = mNodeContainer.begin();
NodeContainer_t::const_iterator iter_end = mNodeContainer.end();
for (; iter != iter_end; ++iter)
{
if (iter->second->mParentNodeId == nodeId)
{
isLeaf = false;
break;
}
}
return isLeaf;
}
bool ExternalViewLoggerImpl::isUnreferencedLeaf(const string& nodeId)
{
return isLeaf(nodeId) && !isReferenced(nodeId);
}
bool ExternalViewLoggerImpl::isReferenced(const string& nodeId)
{
bool isReferenced = false;
NodeContainer_t::const_iterator iter = mNodeContainer.begin();
NodeContainer_t::const_iterator iter_end = mNodeContainer.end();
for (; iter != iter_end; ++iter)
{
if (iter->second->mRefersToNodeId == nodeId)
{
isReferenced = true;
break;
}
}
return isReferenced;
}
bool ExternalViewLoggerImpl::isReferingToOtherNode(const string& nodeId)
{
NodeContainer_t::const_iterator iter = mNodeContainer.find(nodeId);
BOOST_ASSERT(iter != mNodeContainer.end());
return !iter->second->mRefersToNodeId.empty();
}
bool ExternalViewLoggerImpl::hasParent(const string& nodeId)
{
NodeContainer_t::const_iterator iter = mNodeContainer.find(nodeId);
BOOST_ASSERT(iter != mNodeContainer.end());
return iter->second->mParentNodeId != "Root" && iter->second->mParentNodeId != "";
}
string ExternalViewLoggerImpl::getValue(const string& nodeId)
{
return mNodeContainer.find(nodeId)->second->mNodeValue;
}
void ExternalViewLoggerImpl::dumpTree(const string& nodeId)
{
if (nodeId != "Root")
{
mFile << nodeId << " [label=\"(" << getValue(nodeId) << ")\",shape=box];" << endl;
mFile << mParentNodeStack.top() << " -> " << nodeId << ";" << endl;
if (isReferingToOtherNode(nodeId))
{
mParentNodeStack.push(nodeId);
dumpTree(mNodeContainer.find(nodeId)->second->mRefersToNodeId);
mParentNodeStack.pop();
}
}
if (hasParent(nodeId))
dumpTree(mNodeContainer.find(nodeId)->second->mParentNodeId);
}
} // namespace util