"name":"Operations.Assess",
"imports":["Operations.CRM.Customer QoS Mgmt.Create QoS Degradation Report"]
"name":"Operations.CRM.Customer QoS Mgmt.Create QoS Degradation Report",
"imports":["Operations.Assess"]
"name":"Operations.CRM.Customer QoS Mgmt.Manage QoS Violation",
"imports":["Operations.CRM.Customer QoS Mgmt.Create QoS Degradation Report"]
"name":"Operations.CRM.Customer QoS Mgmt.Manage QoS Resolution",
"imports":["Operations.CRM.Customer QoS Mgmt.Create QoS Degradation Report"]
"name":"Operations.CRM.Customer QoS Mgmt.Report QoS Performance",
"imports":["Operations.Assess","Operations.CRM.Customer QoS Mgmt.Create QoS Degradation Report","Operations.CRM.Customer QoS Mgmt.Manage QoS Violation","Operations.CRM.Customer QoS Mgmt.Manage QoS Resolution","Operations.CRM.Customer QoS Mgmt.Close Customer Degradation Report"]
"name":"Operations.CRM.Customer QoS Mgmt.Close Customer Degradation Report",
"imports":["Operations.CRM.Customer QoS Mgmt.Manage QoS Resolution"]
"name":"Operations.SRM.Trouble Mgmt.Trouble Keeping",
"imports":["Operations.CRM.Customer QoS Mgmt.Manage QoS Resolution"]
innerRadius = radius - 200;
var cluster = d3.layout.cluster()
.size([360, innerRadius])
.value(function(d) { return d.size; });
var bundle = d3.layout.bundle();
var line = d3.svg.line.radial()
.radius(function(d) { return d.y; })
.angle(function(d) { return d.x / 180 * Math.PI; });
var svg = d3.select("body").append("svg")
.attr("height", diameter)
.attr("transform", "translate(" + radius + "," + radius + ")");
var link = svg.append("g").selectAll(".link"),
node = svg.append("g").selectAll(".node");
var nodes = cluster.nodes(packageHierarchy(classes)),
links = packageImports(nodes);
var unique_links = links.reduce(function(p,c) {
var index=p.map(function(d,i) { if(d.source===c.target && d.target===c.source) return i;}).shift();
if(!isNaN(index)) p[index].both=true; else p.push(c);
.data(bundle(unique_links))
d.target = d[d.length - 1],
d.both = unique_links.filter(function(v) { if (v.source===d.source && v.target===d.target) return v.both; }).shift();
.data(nodes.filter(function(n) { return !n.children; }))
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); })
.style("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
.text(function(d) { return d.key; })
.on("mouseover", mouseovered)
.on("mouseout", mouseouted);
function mouseovered(d) {
.each(function(n) { n.target = n.source = false; });
.classed("link--both", function(l) { if((l.target===d || l.source===d) && l.both) return l.source.source = l.source.target = l.target.source = l.target.target = true;})
.classed("link--target", function(l) { if (l.target === d && !l.both) return l.source.source = true; })
.classed("link--source", function(l) { if (l.source === d && !l.both) return l.target.target = true; })
.filter(function(l) { return l.target === d || l.source === d; })
.each(function() { this.parentNode.appendChild(this); });
.classed("node--both", function(n) { return n.target && n.source; })
.classed("node--target", function(n) { return n.target; })
.classed("node--source", function(n) { return n.source; });
.classed("link--both", false)
.classed("link--target", false)
.classed("link--source", false);
.classed("node--both", false)
.classed("node--target", false)
.classed("node--source", false);
d3.select(self.frameElement).style("height", diameter + "px");
function packageHierarchy(classes) {
function find(name, data) {
node = map[name] = data || {name: name, children: []};
node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
node.parent.children.push(node);
node.key = name.substring(i + 1);
classes.forEach(function(d) {
function packageImports(nodes) {
nodes.forEach(function(d) {
nodes.forEach(function(d) {
if (d.imports) d.imports.forEach(function(i) {
imports.push({source: map[d.name], target: map[i]});