diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-12-24 04:35:57 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-12-24 04:35:57 +0000 |
commit | 69b7a8dddb2fb1732a5d98808c0360331a2e48d5 (patch) | |
tree | a8293aa0034f3b694258738b31932cbbc2c4189b /sca-cpp/trunk/modules | |
parent | 86fa951ba99a04edf6a41b04751a1ad679dc2d36 (diff) |
Improve component and reference rendering and layout. Recurse over wired references to calculate correct dimensions of each component.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1052446 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk/modules')
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/graph.js | 455 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/scdl.js | 39 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/util.js | 34 |
3 files changed, 364 insertions, 164 deletions
diff --git a/sca-cpp/trunk/modules/js/htdocs/graph.js b/sca-cpp/trunk/modules/js/htdocs/graph.js index 2297f550c2..883b3aa801 100644 --- a/sca-cpp/trunk/modules/js/htdocs/graph.js +++ b/sca-cpp/trunk/modules/js/htdocs/graph.js @@ -103,6 +103,71 @@ var graph; if (graph.supportsVML()) { graph.vmlns='urn:schemas-microsoft-com:vml'; + document.write('<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />'); + + /** + * Make a graph. + */ + graph.mkgraph = function() { + var div = document.createElement('div'); + div.id = 'vmldiv'; + document.body.appendChild(div); + + var vmlg = document.createElement('v:group'); + vmlg.style.width = 500; + vmlg.style.height = 500; + vmlg.coordsize = '500,500'; + div.appendChild(vmlg); + + graph.dragging = null; + + function draggable(n) { + if (n == vmlg) + return null; + if (n.nodeName == 'group') + return n; + return draggable(n.parentNode); + } + + vmlg.onmousedown = function() { + window.event.returnValue = false; + graph.dragging = draggable(window.event.srcElement); + if (graph.dragging == null) + return false; + graph.dragging.parentNode.appendChild(graph.dragging); + graph.dragX = window.event.clientX; + graph.dragY = window.event.clientY; + vmlg.setCapture(); + return false; + }; + + vmlg.onmouseup = function() { + if (graph.dragging == null) + return false; + graph.dragging = null; + vmlg.releaseCapture(); + return false; + }; + + vmlg.onmousemove = function() { + if (graph.dragging == null) + return false; + var origX = graph.dragging.coordorigin.X; + var origY = graph.dragging.coordorigin.Y; + var newX = origX - (window.event.clientX - graph.dragX); + var newY = origY - (window.event.clientY - graph.dragY); + graph.dragX = window.event.clientX; + graph.dragY = window.event.clientY; + graph.dragging.setAttribute('coordorigin', newX + ' ' + newY); + return false; + }; + + graph.textWidthDiv = document.createElement('span'); + graph.textWidthDiv.style.visibility = 'hidden' + div.appendChild(graph.textWidthDiv); + + return vmlg; + }; /** * Make a shape path. @@ -141,8 +206,8 @@ if (graph.supportsVML()) { */ graph.mktitle = function(t) { var title = document.createElement('v:textbox'); - title.style.left = '40'; - title.style.top = '30'; + title.style.left = '25'; + title.style.top = '5'; title.style.position = 'absolute'; var tnode = document.createTextNode(t); title.appendChild(tnode); @@ -154,7 +219,7 @@ if (graph.supportsVML()) { */ graph.titlewidth = function(t) { graph.textWidthDiv.innerHTML = t; - var twidth = textWidthDiv.offsetWidth + 10; + var twidth = graph.textWidthDiv.offsetWidth; graph.textWidthDiv.innerHTML = ''; return twidth; }; @@ -162,18 +227,18 @@ if (graph.supportsVML()) { /** * Make a component shape. */ - graph.mkcompshape = function(name, color, tsvcs, lsvcs, brefs, rrefs) { + graph.mkcompshape = function(comp, cassoc) { + var name = scdl.name(comp); var title = graph.mktitle(name); - var twidth = graph.titlewidth(name); - var d = graph.mkcomppath(twidth, tsvcs, lsvcs, brefs, rrefs).str(); + var d = graph.mkcomppath(comp, cassoc).str(); var shape = document.createElement('v:shape'); shape.style.width = 500; shape.style.height = 500; shape.coordsize = '500,500'; shape.path = d; - shape.fillcolor = color; + shape.fillcolor = graph.color(comp); shape.stroked = 'false'; var contour = document.createElement('v:shape'); @@ -199,81 +264,87 @@ if (graph.supportsVML()) { g.appendChild(title); return g; }; +} + +/** + * SVG rendering. + */ +if (graph.supportsSVG()) { + + graph.svgns='http://www.w3.org/2000/svg'; /** * Make a graph. */ graph.mkgraph = function() { var div = document.createElement('div'); - div.id = 'vmldiv'; + div.id = 'svgdiv'; document.body.appendChild(div); - graph.textWidthDiv = document.createElement('span'); - graph.textWidthDiv.style.visibility = 'hidden' - div.appendChild(graph.textWidthDiv); - - var vmlg = document.createElement('v:group'); - vmlg.style.width = 500; - vmlg.style.height = 500; - vmlg.coordsize = '500,500'; - div.appendChild(vmlg); + var svg = document.createElementNS(graph.svgns, 'svg'); + svg.style.height = '100%'; + svg.style.width = '100%'; + div.appendChild(svg); graph.dragging = null; function draggable(n) { - if (n == vmlg) + if (n == svg) return null; - if (n.nodeName == 'group') + if (n.nodeName == 'g') return n; return draggable(n.parentNode); } - vmlg.onmousedown = function() { - window.event.returnValue = false; - graph.dragging = draggable(window.event.srcElement); + svg.onmousedown = function(e) { + if (e.preventDefault) + e.preventDefault(); + else + e.returnValue= false; + graph.dragging = draggable(e.target); if (graph.dragging == null) return false; graph.dragging.parentNode.appendChild(graph.dragging); - graph.dragX = window.event.clientX; - graph.dragY = window.event.clientY; - vmlg.setCapture(); + var pos = typeof e.touches != "undefined" ? e.touches[0] : e; + graph.dragX = pos.clientX; + graph.dragY = pos.clientY; return false; }; - vmlg.onmouseup = function() { + svg.ontouchstart = svg.onmousedown; + + svg.onmouseup = function(e) { if (graph.dragging == null) return false; graph.dragging = null; - vmlg.releaseCapture(); return false; }; - vmlg.onmousemove = function() { + svg.ontouchend = svg.onmouseup; + + svg.onmousemove = function(e) { if (graph.dragging == null) return false; - var origX = graph.dragging.coordorigin.X; - var origY = graph.dragging.coordorigin.Y; - var newX = origX - (window.event.clientX - graph.dragX); - var newY = origY - (window.event.clientY - graph.dragY); - graph.dragX = window.event.clientX; - graph.dragY = window.event.clientY; - graph.dragging.setAttribute('coordorigin', newX + ' ' + newY); + var matrix = graph.dragging.getCTM(); + var pos = typeof e.touches != "undefined" ? e.touches[0] : e; + var newX = Number(matrix.e) + (pos.clientX - graph.dragX); + var newY = Number(matrix.f) + (pos.clientY - graph.dragY); + graph.dragX = pos.clientX; + graph.dragY = pos.clientY; + graph.dragging.setAttribute('transform', 'translate(' + newX + ',' + newY + ')'); return false; }; - graph.g = vmlg; - return vmlg; - }; - - document.write('<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />'); -} + svg.ontouchmove = svg.onmousemove; -/** - * SVG rendering. - */ -if (graph.supportsSVG()) { + graph.textWidthSvg = document.createElementNS(graph.svgns, 'svg'); + graph.textWidthSvg.style.visibility = 'hidden'; + graph.textWidthSvg.style.height = '0px'; + graph.textWidthSvg.style.width = '0px'; + div.appendChild(graph.textWidthSvg); - graph.svgns='http://www.w3.org/2000/svg'; + return svg; + }; /** * Make a shape path. @@ -313,25 +384,35 @@ if (graph.supportsSVG()) { graph.mktitle = function(t) { var title = document.createElementNS(graph.svgns, 'text'); title.setAttribute('text-anchor', 'start'); - title.setAttribute('x', 40); - title.setAttribute('y', 50); + title.setAttribute('x', 5); + title.setAttribute('y', 15); title.appendChild(document.createTextNode(t)); - graph.g.appendChild(title); + graph.textWidthSvg.appendChild(title); return title; }; /** + * Return a width of a title. + */ + graph.titlewidth = function(t) { + var title = graph.mktitle(t); + var width = title.getBBox().width; + graph.textWidthSvg.removeChild(title); + return width; + }; + + /** * Make a component shape. */ - graph.mkcompshape = function(name, color, tsvcs, lsvcs, brefs, rrefs) { + graph.mkcompshape = function(comp, cassoc) { + var name = scdl.name(comp); var title = graph.mktitle(name); - var twidth = title.getBBox().width; - var d = graph.mkcomppath(twidth, tsvcs, lsvcs, brefs, rrefs).str(); + var d = graph.mkcomppath(comp, cassoc).str(); var shape = document.createElementNS(graph.svgns, 'path'); shape.setAttribute('d', d); - shape.setAttribute('fill', color); + shape.setAttribute('fill', graph.color(comp)); var contour = document.createElementNS(graph.svgns, 'path'); contour.setAttribute('d', d); @@ -347,131 +428,211 @@ if (graph.supportsSVG()) { g.appendChild(title); return g; }; +} - /** - * Make a graph. - */ - graph.mkgraph = function() { - var div = document.createElement('div'); - div.id = 'svgdiv'; - document.body.appendChild(div); +/** + * Make a reference shape path, positioned to the right of a component shape. + */ +graph.mkrrefpath = function(ref, cassoc, path) { + var height = graph.refheight(ref, cassoc); + var ypos = path.ypos(); + return path.rline(0,10).rline(0,10).rcurve(0,5,-5,0).rcurve(-5,0,0,-5).rcurve(0,-5,-5,0).rcurve(-5,0,0,5).rline(0,20).rcurve(0,5,5,0).rcurve(5,0,0,-5).rcurve(0,-5,5,0).rcurve(5,0,0,5).line(path.xpos(),ypos + height); +}; - var svg = document.createElementNS(graph.svgns, 'svg'); - svg.style.height = '100%'; - svg.style.width = '100%'; - div.appendChild(svg); +/** + * Make a reference shape path, positioned at the bottom of a component shape. + */ +graph.mkbrefpath = function(ref, cassoc, path) { + var width = graph.refwidth(ref, cassoc); + var xpos = path.xpos(); + return path.line(xpos - width + 60,path.ypos()).rline(-10,0).rline(-10,0).rcurve(-5,0,0,-5).rcurve(0,-5,5,0).rcurve(5,0,0,-5).rcurve(0,-5,-5,0).rline(-20,0).rcurve(-5,0,0,5).rcurve(0,5,5,0).rcurve(5,0,0,5).rcurve(0,5,-5,0).line(xpos - width,path.ypos()); +}; - graph.dragging = null; +/** + * Make a service shape path, positioned to the left of a component shape. + */ +graph.mklsvcpath = function(svc, path) { + var height = 60; + var ypos = path.ypos(); + return path.rline(0,-10).rline(0, -10).rcurve(0,-5,-5,0).rcurve(-5,0,0,5).rcurve(0,5,-5,0).rcurve(-5,0,0,-5).rline(0,-20).rcurve(0,-5,5,0).rcurve(5,0,0,5).rcurve(0,5,5,0).rcurve(5,0,0,-5).line(path.xpos(), ypos - height); +}; - function draggable(n) { - if (n == svg) - return null; - if (n.nodeName == 'g') - return n; - return draggable(n.parentNode); - } +/** + * Make a service shape path, positioned at the top of a component shape. + */ +graph.mktsvcpath = function(svc, path) { + var width = 60; + var xpos = path.xpos(); + return path.rline(10,0).rline(10,0).rcurve(5,0,0,-5).rcurve(0,-5,-5,0).rcurve(-5,0,0,-5).rcurve(0,-5,5,0).rline(20,0).rcurve(5,0,0,5).rcurve(0,5,-5,0).rcurve(-5,0,0,5).rcurve(0,5,5,0).line(xpos + width,path.ypos()); +}; - svg.onmousedown = function(e) { - if (e.preventDefault) - e.preventDefault(); - else - e.returnValue= false; - graph.dragging = draggable(e.target); - if (graph.dragging == null) - return false; - graph.dragging.parentNode.appendChild(graph.dragging); - var pos = typeof e.touches != "undefined" ? e.touches[0] : e; - graph.dragX = pos.clientX; - graph.dragY = pos.clientY; - return false; - }; - svg.ontouchstart = svg.onmousedown; +/** + * Return the services and references of a component. + */ +graph.tsvcs = function(comp) { + return filter(function(s) { return scdl.align(s) == 'top'; }, scdl.services(comp)); +}; - svg.onmouseup = function(e) { - if (graph.dragging == null) - return false; - graph.dragging = null; - return false; - }; +graph.lsvcs = function(comp) { + return filter(function(s) { var a = scdl.align(s); return a == null || a == 'left'; }, scdl.services(comp)); +}; - svg.ontouchend = svg.onmouseup; +graph.brefs = function(comp) { + return filter(function(r) { return scdl.align(r) == 'bottom'; }, scdl.references(comp)); +}; - svg.onmousemove = function(e) { - if (graph.dragging == null) - return false; - var matrix = graph.dragging.getCTM(); - var pos = typeof e.touches != "undefined" ? e.touches[0] : e; - var newX = Number(matrix.e) + (pos.clientX - graph.dragX); - var newY = Number(matrix.f) + (pos.clientY - graph.dragY); - graph.dragX = pos.clientX; - graph.dragY = pos.clientY; - graph.dragging.setAttribute('transform', 'translate(' + newX + ',' + newY + ')'); - return false; - }; +graph.rrefs = function(comp) { + return filter(function(r) { var a = scdl.align(r); return a == null || a == 'right'; }, scdl.references(comp)); +}; - svg.ontouchmove = svg.onmousemove; +/** + * Return the color of a component. + */ +graph.color = function(comp) { + var c = scdl.color(comp); + return c == null? graph.blue : c; +} - graph.g = svg; - return svg; - }; +/** + * Return the height of a reference. + */ +graph.refheight = function(ref, cassoc) { + var target = assoc(scdl.target(ref), cassoc); + if (isNil(target)) + return 60; + return graph.compheight(cadr(target), cassoc); } /** - * Make a reference shape path, positioned to the right of a component shape. + * Return the total height of a list of references. */ -graph.mkrrefpath = function(path) { - return path.rline(0,10).rcurve(0,5,-5,0).rcurve(-5,0,0,-5).rcurve(0,-5,-5,0).rcurve(-5,0,0,5).rline(0,20).rcurve(0,5,5,0).rcurve(5,0,0,-5).rcurve(0,-5,5,0).rcurve(5,0,0,5).rline(0,10); -}; +graph.refsheight = function(refs, cassoc) { + if (isNil(refs)) + return 0; + return graph.refheight(car(refs), cassoc) + graph.refsheight(cdr(refs), cassoc); +} /** - * Make a reference shape path, positioned at the bottom of a component shape. + * Return the height of a component. */ -graph.mkbrefpath = function(path) { - return path.rline(-10,0).rcurve(-5,0,0,-5).rcurve(0,-5,5,0).rcurve(5,0,0,-5).rcurve(0,-5,-5,0).rline(-20,0).rcurve(-5,0,0,5).rcurve(0,5,5,0).rcurve(5,0,0,5).rcurve(0,5,-5,0).rline(-10,0); +graph.compheight = function(comp, cassoc) { + var lsvcs = graph.lsvcs(comp); + var lsvcsh = Math.max(1, length(lsvcs)) * 60 + 20; + var rrefs = graph.rrefs(comp); + var rrefsh = graph.refsheight(rrefs, cassoc) + 20; + var height = Math.max(lsvcsh, rrefsh); + return height; }; /** - * Make a service shape path, positioned to the left of a component shape. + * Return the width of a reference. */ -graph.mklsvcpath = function(path) { - return path.rline(0,-10).rcurve(0,-5,-5,0).rcurve(-5,0,0,5).rcurve(0,5,-5,0).rcurve(-5,0,0,-5).rline(0,-20).rcurve(0,-5,5,0).rcurve(5,0,0,5).rcurve(0,5,5,0).rcurve(5,0,0,-5).rline(0,-10); -}; +graph.refwidth = function(ref, cassoc) { + var target = assoc(scdl.target(ref), cassoc); + if (isNil(target)) + return 60; + return graph.compwidth(cadr(target), cassoc); +} /** - * Make a service shape path, positioned at the top of a component shape. + * Return the total width of a list of references. */ -graph.mktsvcpath = function(path) { - return path.rline(10,0).rcurve(5,0,0,-5).rcurve(0,-5,-5,0).rcurve(-5,0,0,-5).rcurve(0,-5,5,0).rline(20,0).rcurve(5,0,0,5).rcurve(0,5,-5,0).rcurve(-5,0,0,5).rcurve(0,5,5,0).rline(10,0); -}; +graph.refswidth = function(refs, cassoc) { + if (isNil(refs)) + return 0; + return graph.refwidth(car(refs), cassoc) + graph.refswidth(cdr(refs), cassoc); +} +/** + * Return the width of a component. + */ +graph.compwidth = function(comp, cassoc) { + var twidth = graph.titlewidth(scdl.name(comp)) + 20; + var tsvcs = graph.tsvcs(comp); + var tsvcsw = Math.max(1, length(tsvcs)) * 60 + 20; + var brefs = graph.brefs(comp); + var brefsw = graph.refswidth(brefs, cassoc) + 20; + var width = Math.max(twidth, Math.max(tsvcsw, brefsw)); + return width; +}; /** * Make a component shape path. */ -graph.mkcomppath = function(twidth, tsvcs, lsvcs, brefs, rrefs) { - var height = Math.max(lsvcs, rrefs) * 40 + 60; - var width = Math.max(Math.max(tsvcs, brefs) * 40 + 60, twidth + 20); - - var path = graph.mkpath().rmove(40,30).rline(20,0); - for (var s = 0; s < tsvcs; s++) - path = graph.mktsvcpath(path); - - path = path.line(20 + width,path.ypos()).rcurve(10,0,0,10).rline(0,20); - for (var r = 0; r < rrefs; r++) - path = graph.mkrrefpath(path); - - var boffset = 10 + 30 + (brefs * 40); - path = path.line(path.xpos(),20 + height).rcurve(0,10,-10,0).line(20 + boffset, path.ypos()); - for (var r = 0; r < brefs; r++) - path = graph.mkbrefpath(path); +graph.mkcomppath = function(comp, cassoc) { + var tsvcs = graph.tsvcs(comp); + var lsvcs = graph.lsvcs(comp); + var brefs = graph.brefs(comp); + var rrefs = graph.rrefs(comp); + + var height = graph.compheight(comp, cassoc); + var width = graph.compwidth(comp, cassoc); + + var path = graph.mkpath().move(10,0); + for (var s = 0; s < length(tsvcs); s++) + path = graph.mktsvcpath(tsvcs[s], path); + + path = path.line(width - 10,path.ypos()).rcurve(10,0,0,10); + for (var r = 0; r < length(rrefs); r++) + path = graph.mkrrefpath(rrefs[r], cassoc, path); + + var boffset = 10 + graph.refswidth(brefs, cassoc); + path = path.line(path.xpos(),height - 10).rcurve(0,10,-10,0).line(boffset, path.ypos()); + for (var r = 0; r < length(brefs); r++) + path = graph.mkbrefpath(brefs[r], cassoc, path); + + var loffset = 10 + (length(lsvcs) * 60); + path = path.line(10,path.ypos()).rcurve(-10,0,0,-10).line(path.xpos(), loffset); + for (var s = 0; s < length(lsvcs); s++) + path = graph.mklsvcpath(lsvcs[s], path); + + path = path.line(0,10).rcurve(0,-10,10,0); + return path.end(); +}; - var loffset = 10 + 30 + (lsvcs * 40); - path = path.line(40,path.ypos()).rcurve(-10,0,0,-10).line(path.xpos(), 20 + loffset); - for (var s = 0; s < lsvcs; s++) - path = graph.mklsvcpath(path); +/** + * Render a component. + */ +graph.component = function(comp, cassoc) { + return graph.mkcompshape(comp, cassoc); +}; - path = path.line(30,40).rcurve(0,-10,10,0); - return path.end(); +/** + * Render a composite. + */ +graph.composite = function(compos) { + var name = scdl.name(compos); + var comps = scdl.components(compos); + var cassoc = scdl.nameToElementAssoc(comps); + + function renderReference(ref, cassoc) { + var target = assoc(scdl.target(ref), cassoc); + if (isNil(target)) + return mklist(); + return renderComponent(cadr(target), cassoc); + } + + function renderReferences(refs, cassoc) { + if (isNil(refs)) + return mklist(); + var rref = renderReference(car(refs), cassoc); + if (isNil(rref)) + return renderReferences(cdr(refs), cassoc); + return append(rref, renderReferences(cdr(refs), cassoc)); + } + + function renderComponent(comp, cassoc) { + return append(renderReferences(scdl.references(comp), cassoc), mklist(graph.component(comp, cassoc))); + } + + function renderComponents(comps, cassoc) { + if (isNil(comps)) + return mklist(); + return append(renderComponent(car(comps), cassoc), renderComponents(cdr(comps), cassoc)); + } + + var rcomps = renderComponents(comps, cassoc); + return rcomps; }; diff --git a/sca-cpp/trunk/modules/js/htdocs/scdl.js b/sca-cpp/trunk/modules/js/htdocs/scdl.js index afdb74ac3b..baba0078fe 100644 --- a/sca-cpp/trunk/modules/js/htdocs/scdl.js +++ b/sca-cpp/trunk/modules/js/htdocs/scdl.js @@ -117,19 +117,25 @@ scdl.bindingType = function(l) { * Returns the target of a reference. */ scdl.target = function(l) { - function bindingsTarget(l) { - if (isNil(l)) - return null; - var u = uri(car(l)); - if (!isNil(u)) - return u; - return bindingsTarget(cdr(l)); + function targetURI() { + function bindingsTarget(l) { + if (isNil(l)) + return null; + var u = uri(car(l)); + if (!isNil(u)) + return u; + return bindingsTarget(cdr(l)); + } + + var t = namedAttributeValue("'target", l); + if (!isNil(t)) + return t; + return bindingsTarget(scdl.bindings(l)); } - - var t = namedAttributeValue("'target", l); - if (!isNil(t)) - return t; - return bindingsTarget(scdl.bindings(l)); + var turi = targetURI(); + if (isNil(turi)) + return turi; + return car(tokens(turi)); }; /** @@ -146,3 +152,12 @@ scdl.propertyValue = function(l) { return elementValue(l); }; +/** + * Convert a list of elements to a name -> element assoc list. + */ +scdl.nameToElementAssoc = function(l) { + if (isNil(l)) + return l; + return cons(mklist(scdl.name(car(l)), car(l)), scdl.nameToElementAssoc(cdr(l))); +}; + diff --git a/sca-cpp/trunk/modules/js/htdocs/util.js b/sca-cpp/trunk/modules/js/htdocs/util.js index da069d7ae6..0f966b180e 100644 --- a/sca-cpp/trunk/modules/js/htdocs/util.js +++ b/sca-cpp/trunk/modules/js/htdocs/util.js @@ -109,6 +109,10 @@ function mklist() { return a; } +function length(l) { + return l.length; +} + /** * Scheme-like associations. */ @@ -138,14 +142,34 @@ function filter(f, l) { } /** + * Split a path into a list of segments. + */ +function tokens(path) { + return filter(function(s) { return length(s) != 0; }, path.split("/")); +} + +/** + * Log a value. + */ +function log(v) { + try { + console.log(v); + } catch (e) {} + return true; +} + +/** * Dump an object to the debug console. */ function debug(o) { - for (f in o) { - try { - console.log(f + '=' + o[f]); - } catch (e) {} - } + try { + for (f in o) { + try { + console.log(f + '=' + o[f]); + } catch (e) {} + } + } catch (e) {} + return true; } /** |