Skip to content

Commit 70edfa2

Browse files
SQL queries view, extended properties background implementation, phase 1
1 parent c0a4a97 commit 70edfa2

File tree

7 files changed

+108
-59
lines changed

7 files changed

+108
-59
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
# Cache UML Explorer
1+
# Cache Class Explorer
22
An UML Class explorer for InterSystems Caché.
33

44
##### Key features
55
+ Build class diagrams;
66
+ Build diagrams for any package or subpackage;
77
+ Edit diagrams after build;
88
+ Export diagrams as an image;
9+
+ See Class methods, properties, parameters, SQL queries and more;
910
+ View class methods code with syntax highlighting;
1011
+ Zoom in and out;
1112
+ Search on diagram or in class tree;

cache/projectTemplate.xml

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<Description>
55
Cache UML Explorer vX.X.X/*build.replace:pkg.version*/
66
Class contains methods that return structured classes/packages data.</Description>
7-
<TimeChanged>63808,84964.699928</TimeChanged>
7+
<TimeChanged>63830,81286.756889</TimeChanged>
88
<TimeCreated>63653,67019.989197</TimeCreated>
99

1010
<Method name="getAllNamespacesList">
@@ -93,6 +93,7 @@ Return structured data about class.</Description>
9393
do oData.classes.%DispatchSetProperty(classDefinition.Name, oClass) // prevent from recursive setup
9494
set package = $LISTTOSTRING($LIST($LISTFROMSTRING(classDefinition.Name, "."), 1, *-1),".")
9595
set oProperties = ##class(%ZEN.proxyObject).%New()
96+
set oQueries = ##class(%ZEN.proxyObject).%New()
9697
9798
set oClass.NAMESPACE = $NAMESPACE
9899
set oClass.SYSTEM = classDefinition.System
@@ -109,57 +110,67 @@ Return structured data about class.</Description>
109110
110111
set oClass.properties = oProperties
111112
set count = classDefinition.Properties.Count()
113+
set props = ##class(%Dictionary.ClassDefinition).%OpenId("%Dictionary.PropertyDefinition")
112114
for i=1:1:count {
113115
set oProp = ##class(%ZEN.proxyObject).%New()
114116
set p = classDefinition.Properties.GetAt(i)
115117
do oProperties.%DispatchSetProperty(p.Name, oProp)
116-
set oProp.private = p.Private
117-
set oProp.readOnly = p.ReadOnly
118-
set oProp.cardinality = p.Cardinality
119-
set oProp.inverse = p.Inverse
118+
for j=1:1:props.Properties.Count() {
119+
set pname = props.Properties.GetAt(j).Name
120+
set:(pname '= "parent") $PROPERTY(oProp, pname) = $PROPERTY(p, pname)
121+
}
120122
if (..classExists(package _ "." _ p.Type)) {
121-
set oProp.type = package _ "." _ p.Type
123+
set oProp.Type = package _ "." _ p.Type
122124
do ..fillClassData(oData, package _ "." _ p.Type)
123125
} elseif (..classExists(..extendClassFromType(p.Type))) {
124-
set oProp.type = ..extendClassFromType(p.Type)
126+
set oProp.Type = ..extendClassFromType(p.Type)
125127
do ..fillClassData(oData, ..extendClassFromType(p.Type))
126128
} else {
127-
set oProp.type = p.Type
129+
set oProp.Type = ..extendClassFromType(p.Type)
128130
}
129131
}
130132
131133
set oMethods = ##class(%ZEN.proxyObject).%New()
132134
set oClass.methods = oMethods
133135
set count = classDefinition.Methods.Count()
136+
set props = ##class(%Dictionary.ClassDefinition).%OpenId("%Dictionary.MethodDefinition")
134137
for i=1:1:count {
135138
set oMeth = ##class(%ZEN.proxyObject).%New()
136139
set met = classDefinition.Methods.GetAt(i)
137140
do oMethods.%DispatchSetProperty(met.Name, oMeth)
138-
set oMeth.private = met.Private
139-
set oMeth.returns = met.ReturnType
140-
set oMeth.classMethod = met.ClassMethod
141-
set oMeth.clientMethod = met.ClientMethod
142-
set oMeth.final = met.Final
143-
set oMeth.abstract = met.Abstract
144-
set oMeth.language = met.Language
145-
set oMeth.notInheritable = met.NotInheritable
146-
set oMeth.serverOnly = met.ServerOnly
147-
set oMeth.sqlProc = met.SqlProc
148-
set oMeth.sqlName = met.SqlName
149-
set oMeth.webMethod = met.WebMethod
150-
set oMeth.zenMethod = met.ZenMethod
141+
for j=1:1:props.Properties.Count() {
142+
set pname = props.Properties.GetAt(j).Name
143+
set:((pname '= "parent") && (pname '= "Implementation")) $PROPERTY(oMeth, pname) = $PROPERTY(met, pname)
144+
}
151145
}
152146
153147
set oParameters = ##class(%ZEN.proxyObject).%New()
154148
set oClass.parameters = oParameters
155149
set count = classDefinition.Parameters.Count()
150+
set props = ##class(%Dictionary.ClassDefinition).%OpenId("%Dictionary.ParameterDefinition")
156151
for i=1:1:count {
157152
set oPar = ##class(%ZEN.proxyObject).%New()
158153
set p = classDefinition.Parameters.GetAt(i)
159-
set oPar.type = p.Type
154+
for j=1:1:props.Properties.Count() {
155+
set pname = props.Properties.GetAt(j).Name
156+
set:(pname '= "parent") $PROPERTY(oPar, pname) = $PROPERTY(p, pname)
157+
}
160158
do oParameters.%DispatchSetProperty(p.Name, oPar)
161159
}
162160
161+
#dim q as %Dictionary.QueryDefinition
162+
set oClass.queries = oQueries
163+
set props = ##class(%Dictionary.ClassDefinition).%OpenId("%Dictionary.QueryDefinition")
164+
for i=1:1:classDefinition.Queries.Count() {
165+
set oProp = ##class(%ZEN.proxyObject).%New()
166+
set q = classDefinition.Queries.GetAt(i)
167+
for j=1:1:props.Properties.Count() {
168+
set pname = props.Properties.GetAt(j).Name
169+
set:(pname '= "parent") $PROPERTY(oProp, pname) = $PROPERTY(q, pname)
170+
}
171+
do oQueries.%DispatchSetProperty(q.Name, oProp)
172+
}
173+
163174
do ..collectInheritance(oData, oClass.super)
164175
165176
quit oClass

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "CacheUMLExplorer",
3-
"version": "1.2.0",
3+
"version": "1.3.0",
44
"description": "An UML Class explorer for InterSystems Caché",
55
"directories": {
66
"test": "test"

web/css/classView.css

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ svg {
1919
/*fill: lightgray;*/
2020
}
2121

22-
.uml-class-attrs-rect, .uml-class-methods-rect {
22+
.uml-class-attrs-rect, .uml-class-methods-rect, .uml-class-queries-rect {
2323
fill: white;
2424
}
2525

@@ -66,6 +66,12 @@ text {
6666
fill: blue;
6767
}
6868

69+
.uml-class-queries-label {
70+
font-family: monospace;
71+
font-weight: 900;
72+
fill: #0d0;
73+
}
74+
6975
.uml-class-params-label {
7076
font-family: monospace;
7177
font-weight: 900;

web/js/ClassView.js

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,8 @@ ClassView.prototype.renderInfoGraphic = function () {
237237
aggregation: {
238238
"Persistent class (one)": {
239239
"DataType class (many)": {
240-
left: "*",
241-
right: 1
240+
left: "many",
241+
right: "one"
242242
}
243243
}
244244
},
@@ -409,19 +409,21 @@ ClassView.prototype.getClassSigns = function (classMetaData) {
409409
*
410410
* @param method
411411
*/
412-
ClassView.prototype.getMethodIcons = function (method) {
412+
ClassView.prototype.getPropertyIcons = function (method) {
413413

414414
var icons = [];
415415

416-
icons.push({ src: lib.image[method["private"] ? "minus" : "plus"] });
417-
if (method["abstract"]) icons.push({ src: lib.image.crystalBall });
418-
if (method["clientMethod"]) icons.push({ src: lib.image.user });
419-
if (method["final"]) icons.push({ src: lib.image.blueFlag });
420-
if (method["notInheritable"]) icons.push({ src: lib.image.redFlag });
421-
if (method["sqlProc"]) icons.push({ src: lib.image.table });
422-
if (method["webMethod"]) icons.push({ src: lib.image.earth });
423-
if (method["zenMethod"]) icons.push({ src: lib.image.zed });
424-
if (method["readOnly"]) icons.push({ src: lib.image.eye });
416+
if (typeof method["Private"] !== "undefined") {
417+
icons.push({ src: lib.image[method["Private"] ? "minus" : "plus"] });
418+
}
419+
if (method["Abstract"]) icons.push({ src: lib.image.crystalBall });
420+
if (method["ClientMethod"]) icons.push({ src: lib.image.user });
421+
if (method["Final"]) icons.push({ src: lib.image.blueFlag });
422+
if (method["NotInheritable"]) icons.push({ src: lib.image.redFlag });
423+
if (method["SqlProc"]) icons.push({ src: lib.image.table });
424+
if (method["WebMethod"]) icons.push({ src: lib.image.earth });
425+
if (method["ZenMethod"]) icons.push({ src: lib.image.zed });
426+
if (method["ReadOnly"]) icons.push({ src: lib.image.eye });
425427

426428
return icons;
427429

@@ -437,6 +439,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
437439
var classParams = classMetaData["parameters"],
438440
classProps = classMetaData["properties"],
439441
classMethods = classMetaData["methods"],
442+
classQueries = classMetaData["queries"],
440443
keyWordsArray = [name],
441444
self = this;
442445

@@ -455,7 +458,8 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
455458
for (n in params) {
456459
keyWordsArray.push(n);
457460
arr.push({
458-
text: n + (params[n]["type"] ? ": " + params[n]["type"] : "")
461+
text: n + (params[n]["Type"] ? ": " + params[n]["Type"] : ""),
462+
icons: self.getPropertyIcons(params[n])
459463
});
460464
}
461465
return arr;
@@ -465,8 +469,8 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
465469
for (n in ps) {
466470
keyWordsArray.push(n);
467471
arr.push({
468-
text: n + (ps[n]["type"] ? ": " + ps[n]["type"] : ""),
469-
icons: self.getMethodIcons(ps[n])
472+
text: n + (ps[n]["Type"] ? ": " + ps[n]["Type"] : ""),
473+
icons: self.getPropertyIcons(ps[n])
470474
});
471475
}
472476
return arr;
@@ -476,18 +480,29 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
476480
for (n in met) {
477481
keyWordsArray.push(n);
478482
arr.push({
479-
text: n + (met[n]["returns"] ? ": " + met[n]["returns"] : ""),
483+
text: n + (met[n]["ReturnType"] ? ": " + met[n]["ReturnType"] : ""),
480484
styles: (function (t) {
481485
return t ? { textDecoration: "underline" } : {}
482486
})(met[n]["classMethod"]),
483487
clickHandler: (function (n) {
484488
return function () { self.showMethodCode(name, n); }
485489
})(n),
486-
icons: self.getMethodIcons(met[n])
490+
icons: self.getPropertyIcons(met[n])
487491
});
488492
}
489493
return arr;
490494
})(classMethods),
495+
queries: (function (qrs) {
496+
var arr = [], n;
497+
for (n in qrs) {
498+
keyWordsArray.push(n);
499+
arr.push({
500+
text: n,
501+
icons: self.getPropertyIcons(qrs[n])
502+
});
503+
}
504+
return arr;
505+
})(classQueries),
491506
classSigns: this.getClassSigns(classMetaData),
492507
classType: classMetaData.$classType,
493508
SYMBOL_12_WIDTH: self.SYMBOL_12_WIDTH
@@ -591,9 +606,11 @@ ClassView.prototype.render = function (data) {
591606
ClassView.prototype.confirmRender = function (data) {
592607

593608
var self = this, p, pp, className,
609+
LINK_TEXT_MARGIN = 22,
594610
uml = joint.shapes.uml, relFrom, relTo,
595611
classes = {}, connector;
596612

613+
console.log(data);
597614
this.filterInherits(data);
598615

599616
// Reset view and zoom again because it may cause visual damage to icons.
@@ -648,8 +665,8 @@ ClassView.prototype.confirmRender = function (data) {
648665
}
649666
}
650667
};
651-
if (link.left) arr.push(getLabel(link.left, 10));
652-
if (link.right) arr.push(getLabel(link.right, -10));
668+
if (link.left) arr.push(getLabel(link.left, LINK_TEXT_MARGIN));
669+
if (link.right) arr.push(getLabel(link.right, -LINK_TEXT_MARGIN));
653670
return arr;
654671
})(data[type][p][pp] || {})
655672
}));

web/js/Logic.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,21 @@ Logic.prototype.fillAssociations = function () {
7575
if (!properties) continue;
7676
for (propertyName in properties) {
7777
po = properties[propertyName];
78-
if (po["cardinality"] === "one") {
79-
if (!aggr[po.type]) aggr[po.type] = {};
80-
aggr[po.type][className] = {
81-
left: "*",
82-
right: "1"
78+
if (po["Cardinality"] === "one") {
79+
if (!aggr[po["Type"]]) aggr[po["Type"]] = {};
80+
aggr[po["Type"]][className] = {
81+
left: "many",
82+
right: "one"
8383
};
84-
} else if (po["cardinality"] === "parent") {
85-
if (!compos[po.type]) compos[po.type] = {};
86-
compos[po.type][className] = {
87-
left: "*",
88-
right: "1"
84+
} else if (po["Cardinality"] === "parent") {
85+
if (!compos[po["Type"]]) compos[po["Type"]] = {};
86+
compos[po["Type"]][className] = {
87+
left: "child",
88+
right: "parent"
8989
};
90-
} else if (self.data.classes[po.type] && !po["cardinality"]) {
91-
if (!assoc[po.type]) assoc[po.type] = {};
92-
assoc[po.type][className] = {};
90+
} else if (self.data.classes[po["Type"]] && !po["Cardinality"]) {
91+
if (!assoc[po["Type"]]) assoc[po["Type"]] = {};
92+
assoc[po["Type"]][className] = {};
9393
}
9494
}
9595
}

web/jsLib/joint.shapes.uml.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ joint.shapes.uml.Class = joint.shapes.basic.Generic.extend({
2222
'<text class="uml-class-attrs-label">Properties</text>',
2323
'<rect class="uml-class-methods-rect"/>',
2424
'<text class="uml-class-methods-label">Methods</text>',
25+
'<rect class="uml-class-queries-rect"/>',
26+
'<text class="uml-class-queries-label">Queries</text>',
2527
'</g>',
2628
'<text class="uml-class-name-text"/>',
2729
'<text class="uml-class-params-text"/>',
2830
'<text class="uml-class-attrs-text"/>',
2931
'<text class="uml-class-methods-text"/>',
32+
'<text class="uml-class-queries-text"/>',
3033
'</g>'
3134
].join(''),
3235

@@ -46,6 +49,7 @@ joint.shapes.uml.Class = joint.shapes.basic.Generic.extend({
4649
'.uml-class-params-rect': { 'stroke': 'black', 'stroke-width': 1, 'fill': 'white' },
4750
'.uml-class-attrs-rect': { 'stroke': 'black', 'stroke-width': 1, 'fill': '#2980b9' },
4851
'.uml-class-methods-rect': { 'stroke': 'black', 'stroke-width': 1, 'fill': '#2980b9' },
52+
'.uml-class-queries-rect': { 'stroke': 'black', 'stroke-width': 1, 'fill': '#2980b9' },
4953

5054
'.uml-class-name-text': {
5155
'ref': '.uml-class-name-rect', 'ref-y': .5, 'ref-x': .5, 'text-anchor': 'middle', 'y-alignment': 'middle', 'font-weight': 'bold',
@@ -63,13 +67,20 @@ joint.shapes.uml.Class = joint.shapes.basic.Generic.extend({
6367
'ref': '.uml-class-methods-rect', 'ref-y': 5, 'ref-x': 5,
6468
'fill': 'black', 'font-size': 12
6569
},
70+
'.uml-class-queries-text': {
71+
'ref': '.uml-class-queries-rect', 'ref-y': 5, 'ref-x': 5,
72+
'fill': 'black', 'font-size': 12
73+
},
6674
'.uml-class-attrs-label': {
6775
ref: '.uml-class-attrs-label', fill: "black", 'font-size': 10,
6876
xPos: -56
6977
},
7078
'.uml-class-methods-label': {
7179
ref: '.uml-class-methods-label', fill: "black", 'font-size': 10
7280
},
81+
'.uml-class-queries-label': {
82+
ref: '.uml-class-queries-label', fill: "black", 'font-size': 10
83+
},
7384
'.uml-class-params-label': {
7485
ref: '.uml-class-methods-label', fill: "black", 'font-size': 10
7586
}
@@ -79,6 +90,7 @@ joint.shapes.uml.Class = joint.shapes.basic.Generic.extend({
7990
params: [],
8091
attributes: [],
8192
methods: [],
93+
queries: [],
8294
classSigns: []
8395

8496
}, joint.shapes.basic.Generic.prototype.defaults),
@@ -90,7 +102,8 @@ joint.shapes.uml.Class = joint.shapes.basic.Generic.extend({
90102
{ type: 'name', text: this.getClassName() },
91103
{ type: 'params', text: (o = this.get('params')) , o: o },
92104
{ type: 'attrs', text: (o = this.get('attributes')), o: o },
93-
{ type: 'methods', text: (o = this.get('methods')) , o: o }
105+
{ type: 'methods', text: (o = this.get('methods')) , o: o },
106+
{ type: 'queries', text: (o = this.get('queries')) , o: o }
94107
],
95108
self = this,
96109
classSigns = this.get('classSigns'),
@@ -185,7 +198,8 @@ joint.shapes.uml.Class = joint.shapes.basic.Generic.extend({
185198
{ type: 'name', text: this.getClassName() },
186199
{ type: 'params', text: this.get('params') },
187200
{ type: 'attrs', text: this.get('attributes') },
188-
{ type: 'methods', text: this.get('methods') }
201+
{ type: 'methods', text: this.get('methods') },
202+
{ type: 'queries', text: this.get('queries') }
189203
];
190204

191205
var offsetY = 0;

0 commit comments

Comments
 (0)