1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski #include "ExternalViewLogger.hxx" 25*b1cdbd2cSJim Jagielski #include <iostream> 26*b1cdbd2cSJim Jagielski #include <boost/assert.hpp> 27*b1cdbd2cSJim Jagielski #include <stdio.h> 28*b1cdbd2cSJim Jagielski 29*b1cdbd2cSJim Jagielski #ifdef WNT 30*b1cdbd2cSJim Jagielski #define SNPRINTF(buffer, size, format, args) _snprintf(buffer, size, format, args) 31*b1cdbd2cSJim Jagielski #else 32*b1cdbd2cSJim Jagielski #define SNPRINTF(buffer, size, format, args) snprintf(buffer, size, format, args) 33*b1cdbd2cSJim Jagielski #endif 34*b1cdbd2cSJim Jagielski 35*b1cdbd2cSJim Jagielski using namespace std; 36*b1cdbd2cSJim Jagielski 37*b1cdbd2cSJim Jagielski namespace util 38*b1cdbd2cSJim Jagielski { 39*b1cdbd2cSJim Jagielski NodeDescription(const string & parent,const string & refersTo,const string & value,bool inUse)40*b1cdbd2cSJim Jagielski NodeDescription::NodeDescription(const string& parent, const string& refersTo, const string& value, bool inUse) : 41*b1cdbd2cSJim Jagielski mParentNodeId(parent), 42*b1cdbd2cSJim Jagielski mRefersToNodeId(refersTo), 43*b1cdbd2cSJim Jagielski mNodeValue(value), 44*b1cdbd2cSJim Jagielski mInUse(inUse) 45*b1cdbd2cSJim Jagielski {} 46*b1cdbd2cSJim Jagielski ExternalViewLoggerImpl(const string & fileName)47*b1cdbd2cSJim Jagielski ExternalViewLoggerImpl::ExternalViewLoggerImpl(const string& fileName) : 48*b1cdbd2cSJim Jagielski mFileName(fileName), 49*b1cdbd2cSJim Jagielski mFile(fileName.c_str()) 50*b1cdbd2cSJim Jagielski { 51*b1cdbd2cSJim Jagielski if (!mFile) 52*b1cdbd2cSJim Jagielski throw "Cannot open file"; 53*b1cdbd2cSJim Jagielski } 54*b1cdbd2cSJim Jagielski getNewStyleName()55*b1cdbd2cSJim Jagielski string ExternalViewLoggerImpl::getNewStyleName() 56*b1cdbd2cSJim Jagielski { 57*b1cdbd2cSJim Jagielski static int i = 0; 58*b1cdbd2cSJim Jagielski char buff[20]; 59*b1cdbd2cSJim Jagielski SNPRINTF(buff, sizeof(buff), "Style_%d", i++); 60*b1cdbd2cSJim Jagielski return string(buff); 61*b1cdbd2cSJim Jagielski } 62*b1cdbd2cSJim Jagielski beginTree()63*b1cdbd2cSJim Jagielski void ExternalViewLoggerImpl::beginTree() 64*b1cdbd2cSJim Jagielski { 65*b1cdbd2cSJim Jagielski mParentNodeStack.push(""); 66*b1cdbd2cSJim Jagielski } 67*b1cdbd2cSJim Jagielski dumpNodeContainer(const std::string & fileName)68*b1cdbd2cSJim Jagielski void ExternalViewLoggerImpl::dumpNodeContainer(const std::string& fileName) 69*b1cdbd2cSJim Jagielski { 70*b1cdbd2cSJim Jagielski std::ofstream file(fileName.c_str()); 71*b1cdbd2cSJim Jagielski NodeContainer_t::iterator iter = mNodeContainer.begin(); 72*b1cdbd2cSJim Jagielski NodeContainer_t::iterator iter_end = mNodeContainer.end(); 73*b1cdbd2cSJim Jagielski for (; iter != iter_end; ++iter) 74*b1cdbd2cSJim Jagielski { 75*b1cdbd2cSJim Jagielski file << iter->first << string(" ") << iter->second->mParentNodeId << string(" ") << iter->second->mRefersToNodeId << string(" ") << iter->second->mNodeValue << endl; 76*b1cdbd2cSJim Jagielski } 77*b1cdbd2cSJim Jagielski } 78*b1cdbd2cSJim Jagielski endTree()79*b1cdbd2cSJim Jagielski void ExternalViewLoggerImpl::endTree() 80*b1cdbd2cSJim Jagielski { 81*b1cdbd2cSJim Jagielski //dumpNodeContainer(mFileName + string(".dmp")); 82*b1cdbd2cSJim Jagielski 83*b1cdbd2cSJim Jagielski mFile << "digraph {" << endl; 84*b1cdbd2cSJim Jagielski mFile << "Root [shape=box, color=grey];" << endl; 85*b1cdbd2cSJim Jagielski 86*b1cdbd2cSJim Jagielski while (!mParentNodeStack.empty()) 87*b1cdbd2cSJim Jagielski mParentNodeStack.pop(); 88*b1cdbd2cSJim Jagielski 89*b1cdbd2cSJim Jagielski mParentNodeStack.push("Root"); 90*b1cdbd2cSJim Jagielski 91*b1cdbd2cSJim Jagielski NodeContainer_t::iterator iter = mNodeContainer.begin(); 92*b1cdbd2cSJim Jagielski NodeContainer_t::iterator iter_end = mNodeContainer.end(); 93*b1cdbd2cSJim Jagielski for (; iter != iter_end; ++iter) 94*b1cdbd2cSJim Jagielski { 95*b1cdbd2cSJim Jagielski if (isUnreferencedLeaf(iter->first)) 96*b1cdbd2cSJim Jagielski { 97*b1cdbd2cSJim Jagielski string newStyleName = getNewStyleName(); 98*b1cdbd2cSJim Jagielski mFile << newStyleName << " [shape=box];" << endl; 99*b1cdbd2cSJim Jagielski mFile << mParentNodeStack.top() << " -> " << newStyleName << endl; 100*b1cdbd2cSJim Jagielski mParentNodeStack.push(newStyleName); 101*b1cdbd2cSJim Jagielski dumpTree(iter->first); 102*b1cdbd2cSJim Jagielski mParentNodeStack.pop(); 103*b1cdbd2cSJim Jagielski } 104*b1cdbd2cSJim Jagielski } 105*b1cdbd2cSJim Jagielski 106*b1cdbd2cSJim Jagielski mFile << "}" << endl; 107*b1cdbd2cSJim Jagielski } 108*b1cdbd2cSJim Jagielski beginNode(const std::string & nodeId,const std::string & value,const std::string & refersToNodeId,bool inUse)109*b1cdbd2cSJim Jagielski void ExternalViewLoggerImpl::beginNode(const std::string& nodeId, const std::string& value, const std::string& refersToNodeId, bool inUse) 110*b1cdbd2cSJim Jagielski { 111*b1cdbd2cSJim Jagielski mNodeContainer.insert( 112*b1cdbd2cSJim Jagielski NodeContainer_t::value_type(nodeId, 113*b1cdbd2cSJim Jagielski NodeDescription::Pointer_t(new NodeDescription(mParentNodeStack.top(), refersToNodeId, value, inUse)))); 114*b1cdbd2cSJim Jagielski mParentNodeStack.push(nodeId); 115*b1cdbd2cSJim Jagielski } 116*b1cdbd2cSJim Jagielski endNode(const std::string & nodeId)117*b1cdbd2cSJim Jagielski void ExternalViewLoggerImpl::endNode(const std::string& nodeId) 118*b1cdbd2cSJim Jagielski { 119*b1cdbd2cSJim Jagielski mParentNodeStack.pop(); 120*b1cdbd2cSJim Jagielski } 121*b1cdbd2cSJim Jagielski isLeaf(const std::string & nodeId)122*b1cdbd2cSJim Jagielski bool ExternalViewLoggerImpl::isLeaf(const std::string& nodeId) 123*b1cdbd2cSJim Jagielski { 124*b1cdbd2cSJim Jagielski bool isLeaf = true; 125*b1cdbd2cSJim Jagielski 126*b1cdbd2cSJim Jagielski NodeContainer_t::const_iterator iter = mNodeContainer.begin(); 127*b1cdbd2cSJim Jagielski NodeContainer_t::const_iterator iter_end = mNodeContainer.end(); 128*b1cdbd2cSJim Jagielski for (; iter != iter_end; ++iter) 129*b1cdbd2cSJim Jagielski { 130*b1cdbd2cSJim Jagielski if (iter->second->mParentNodeId == nodeId) 131*b1cdbd2cSJim Jagielski { 132*b1cdbd2cSJim Jagielski isLeaf = false; 133*b1cdbd2cSJim Jagielski break; 134*b1cdbd2cSJim Jagielski } 135*b1cdbd2cSJim Jagielski } 136*b1cdbd2cSJim Jagielski return isLeaf; 137*b1cdbd2cSJim Jagielski } 138*b1cdbd2cSJim Jagielski isUnreferencedLeaf(const string & nodeId)139*b1cdbd2cSJim Jagielski bool ExternalViewLoggerImpl::isUnreferencedLeaf(const string& nodeId) 140*b1cdbd2cSJim Jagielski { 141*b1cdbd2cSJim Jagielski return isLeaf(nodeId) && !isReferenced(nodeId); 142*b1cdbd2cSJim Jagielski } 143*b1cdbd2cSJim Jagielski isReferenced(const string & nodeId)144*b1cdbd2cSJim Jagielski bool ExternalViewLoggerImpl::isReferenced(const string& nodeId) 145*b1cdbd2cSJim Jagielski { 146*b1cdbd2cSJim Jagielski bool isReferenced = false; 147*b1cdbd2cSJim Jagielski 148*b1cdbd2cSJim Jagielski NodeContainer_t::const_iterator iter = mNodeContainer.begin(); 149*b1cdbd2cSJim Jagielski NodeContainer_t::const_iterator iter_end = mNodeContainer.end(); 150*b1cdbd2cSJim Jagielski for (; iter != iter_end; ++iter) 151*b1cdbd2cSJim Jagielski { 152*b1cdbd2cSJim Jagielski if (iter->second->mRefersToNodeId == nodeId) 153*b1cdbd2cSJim Jagielski { 154*b1cdbd2cSJim Jagielski isReferenced = true; 155*b1cdbd2cSJim Jagielski break; 156*b1cdbd2cSJim Jagielski } 157*b1cdbd2cSJim Jagielski } 158*b1cdbd2cSJim Jagielski return isReferenced; 159*b1cdbd2cSJim Jagielski } 160*b1cdbd2cSJim Jagielski isReferingToOtherNode(const string & nodeId)161*b1cdbd2cSJim Jagielski bool ExternalViewLoggerImpl::isReferingToOtherNode(const string& nodeId) 162*b1cdbd2cSJim Jagielski { 163*b1cdbd2cSJim Jagielski NodeContainer_t::const_iterator iter = mNodeContainer.find(nodeId); 164*b1cdbd2cSJim Jagielski BOOST_ASSERT(iter != mNodeContainer.end()); 165*b1cdbd2cSJim Jagielski return !iter->second->mRefersToNodeId.empty(); 166*b1cdbd2cSJim Jagielski } 167*b1cdbd2cSJim Jagielski hasParent(const string & nodeId)168*b1cdbd2cSJim Jagielski bool ExternalViewLoggerImpl::hasParent(const string& nodeId) 169*b1cdbd2cSJim Jagielski { 170*b1cdbd2cSJim Jagielski NodeContainer_t::const_iterator iter = mNodeContainer.find(nodeId); 171*b1cdbd2cSJim Jagielski BOOST_ASSERT(iter != mNodeContainer.end()); 172*b1cdbd2cSJim Jagielski return iter->second->mParentNodeId != "Root" && iter->second->mParentNodeId != ""; 173*b1cdbd2cSJim Jagielski } 174*b1cdbd2cSJim Jagielski getValue(const string & nodeId)175*b1cdbd2cSJim Jagielski string ExternalViewLoggerImpl::getValue(const string& nodeId) 176*b1cdbd2cSJim Jagielski { 177*b1cdbd2cSJim Jagielski return mNodeContainer.find(nodeId)->second->mNodeValue; 178*b1cdbd2cSJim Jagielski } 179*b1cdbd2cSJim Jagielski dumpTree(const string & nodeId)180*b1cdbd2cSJim Jagielski void ExternalViewLoggerImpl::dumpTree(const string& nodeId) 181*b1cdbd2cSJim Jagielski { 182*b1cdbd2cSJim Jagielski if (nodeId != "Root") 183*b1cdbd2cSJim Jagielski { 184*b1cdbd2cSJim Jagielski mFile << nodeId << " [label=\"(" << getValue(nodeId) << ")\",shape=box];" << endl; 185*b1cdbd2cSJim Jagielski mFile << mParentNodeStack.top() << " -> " << nodeId << ";" << endl; 186*b1cdbd2cSJim Jagielski if (isReferingToOtherNode(nodeId)) 187*b1cdbd2cSJim Jagielski { 188*b1cdbd2cSJim Jagielski mParentNodeStack.push(nodeId); 189*b1cdbd2cSJim Jagielski dumpTree(mNodeContainer.find(nodeId)->second->mRefersToNodeId); 190*b1cdbd2cSJim Jagielski mParentNodeStack.pop(); 191*b1cdbd2cSJim Jagielski } 192*b1cdbd2cSJim Jagielski } 193*b1cdbd2cSJim Jagielski 194*b1cdbd2cSJim Jagielski if (hasParent(nodeId)) 195*b1cdbd2cSJim Jagielski dumpTree(mNodeContainer.find(nodeId)->second->mParentNodeId); 196*b1cdbd2cSJim Jagielski } 197*b1cdbd2cSJim Jagielski 198*b1cdbd2cSJim Jagielski } // namespace util 199*b1cdbd2cSJim Jagielski 200