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