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