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