concrete 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/CHANGELOG +32 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +87 -0
  4. data/concrete/basic_inline_editor.js +73 -0
  5. data/concrete/clipboard.js +72 -0
  6. data/concrete/concrete.js +58 -0
  7. data/concrete/constraint_checker.js +297 -0
  8. data/concrete/editor.js +964 -0
  9. data/concrete/element_extension.js +68 -0
  10. data/concrete/external_identifier_provider.js +112 -0
  11. data/concrete/helper.js +63 -0
  12. data/concrete/identifier_provider.js +168 -0
  13. data/concrete/inline_editor.js +55 -0
  14. data/concrete/metamodel_provider.js +171 -0
  15. data/concrete/model_interface.js +429 -0
  16. data/concrete/scroller.js +106 -0
  17. data/concrete/selector.js +302 -0
  18. data/concrete/template_provider.js +141 -0
  19. data/concrete/ui/abstract_dialog.js +80 -0
  20. data/concrete/ui/concrete_ui.js +28 -0
  21. data/concrete/ui/create_module_dialog.js +55 -0
  22. data/concrete/ui/images/close.png +0 -0
  23. data/concrete/ui/images/document-new.png +0 -0
  24. data/concrete/ui/images/document-save.png +0 -0
  25. data/concrete/ui/images/edit-find-replace.png +0 -0
  26. data/concrete/ui/images/emblem-symbolic-link.png +0 -0
  27. data/concrete/ui/images/help-browser.png +0 -0
  28. data/concrete/ui/images/minus_11px.png +0 -0
  29. data/concrete/ui/images/plus_11px.png +0 -0
  30. data/concrete/ui/images/preferences-system.png +0 -0
  31. data/concrete/ui/images/process-stop.png +0 -0
  32. data/concrete/ui/images/system-search.png +0 -0
  33. data/concrete/ui/layout_manager.js +54 -0
  34. data/concrete/ui/module_browser.js +88 -0
  35. data/concrete/ui/module_editor.js +217 -0
  36. data/concrete/ui/open_element_dialog.js +90 -0
  37. data/concrete/ui/preferences_dialog.js +75 -0
  38. data/concrete/ui/proceed_dialog.js +52 -0
  39. data/concrete/ui/search_replace_dialog.js +323 -0
  40. data/concrete/ui/style.css +296 -0
  41. data/concrete/ui/toolbar.js +74 -0
  42. data/concrete/ui/workbench.js +165 -0
  43. data/doc/concrete_developers_guide.html +1054 -0
  44. data/doc/concrete_developers_guide.txt +502 -0
  45. data/doc/concrete_users_guide.html +694 -0
  46. data/doc/concrete_users_guide.txt +223 -0
  47. data/example/formula_editor/example_data/example1.json +11 -0
  48. data/example/formula_editor/formula_editor.html +83 -0
  49. data/example/formula_editor/sqrt_horz.png +0 -0
  50. data/example/formula_editor/sqrt_vert.png +0 -0
  51. data/example/formula_editor/style.css +31 -0
  52. data/example/metamodel_editor/edit.rb +54 -0
  53. data/example/metamodel_editor/example_data/formula_metamodel.json +18 -0
  54. data/example/metamodel_editor/example_data/meta_metamodel.json +22 -0
  55. data/example/metamodel_editor/example_data/statemachine_metamodel.json +32 -0
  56. data/example/metamodel_editor/metamodel_editor.html +120 -0
  57. data/example/metamodel_editor/metamodel_editor2.html +135 -0
  58. data/example/metamodel_editor/metamodel_editor3.html +151 -0
  59. data/example/metamodel_editor/style.css +8 -0
  60. data/example/metamodel_editor/style2.css +19 -0
  61. data/example/metamodel_editor/style3.css +35 -0
  62. data/example/minimal_editor/minimal_editor.html +43 -0
  63. data/example/statemachine_editor/example_data/example1.json +11 -0
  64. data/example/statemachine_editor/state_background.png +0 -0
  65. data/example/statemachine_editor/statemachine_editor0.html +55 -0
  66. data/example/statemachine_editor/statemachine_editor1.html +62 -0
  67. data/example/statemachine_editor/statemachine_editor2.html +103 -0
  68. data/example/statemachine_editor/style0.css +8 -0
  69. data/example/statemachine_editor/style1.css +32 -0
  70. data/example/statemachine_editor/style2.css +43 -0
  71. data/example/themes/cobalt.css +176 -0
  72. data/example/themes/dialog-error.png +0 -0
  73. data/example/themes/dialog-information.png +0 -0
  74. data/example/themes/dialog-warning.png +0 -0
  75. data/example/themes/dots_12px.png +0 -0
  76. data/example/themes/fold_button_dots_when_hidden.css +18 -0
  77. data/example/themes/fold_button_plus_minus.css +21 -0
  78. data/example/themes/fold_button_plus_when_hidden.css +18 -0
  79. data/example/themes/light_blue.css +177 -0
  80. data/example/themes/minus_11px.png +0 -0
  81. data/example/themes/minus_13px.png +0 -0
  82. data/example/themes/minus_9px.png +0 -0
  83. data/example/themes/plus_11px.png +0 -0
  84. data/example/themes/plus_13px.png +0 -0
  85. data/example/themes/plus_9px.png +0 -0
  86. data/example/themes/white.css +177 -0
  87. data/lib/concrete/concrete_syntax_provider.rb +63 -0
  88. data/lib/concrete/config.rb +36 -0
  89. data/lib/concrete/file_cache_map.rb +88 -0
  90. data/lib/concrete/index_builder.rb +108 -0
  91. data/lib/concrete/metamodel/concrete_mmm.rb +45 -0
  92. data/lib/concrete/metamodel/ecore_to_concrete.rb +80 -0
  93. data/lib/concrete/server.rb +92 -0
  94. data/lib/concrete/util/logger.rb +24 -0
  95. data/lib/concrete/util/string_writer.rb +17 -0
  96. data/lib/concrete/working_set.rb +41 -0
  97. data/rakefile +33 -0
  98. data/redist/prototype.js +4320 -0
  99. data/redist/scriptaculous/builder.js +136 -0
  100. data/redist/scriptaculous/controls.js +991 -0
  101. data/redist/scriptaculous/dragdrop.js +975 -0
  102. data/redist/scriptaculous/effects.js +1130 -0
  103. data/redist/scriptaculous/scriptaculous.js +60 -0
  104. data/redist/scriptaculous/slider.js +275 -0
  105. data/redist/scriptaculous/sound.js +55 -0
  106. data/redist/scriptaculous/unittest.js +568 -0
  107. data/test/concrete_test.rb +5 -0
  108. data/test/file_cache_map_test.rb +90 -0
  109. data/test/file_cache_map_test/testdir/fileA +1 -0
  110. data/test/index_builder_test.rb +68 -0
  111. data/test/index_builder_test/ecore_index.js +85 -0
  112. data/test/index_builder_test/ecore_index_expected.js +85 -0
  113. data/test/integration/external_elements_test.html +114 -0
  114. data/test/metamodel_test.rb +40 -0
  115. data/test/metamodel_test/concrete_mmm_expected.js +19 -0
  116. data/test/metamodel_test/concrete_mmm_generated.js +19 -0
  117. data/test/metamodel_test/concrete_mmm_regenerated.js +19 -0
  118. data/test/unit/external_identifier_provider_test.html +138 -0
  119. data/test/unit/identifier_provider_test.html +269 -0
  120. data/test/unit/metamodel_provider_test.html +318 -0
  121. data/test/unit/model_interface_test.html +257 -0
  122. data/test/unit/template_provider_test.html +171 -0
  123. data/test/unit/test.css +90 -0
  124. data/test/working_set_test.rb +54 -0
  125. data/test/working_set_test/file1.txt +0 -0
  126. data/test/working_set_test/file2 +0 -0
  127. data/test/working_set_test/subdir/file3.xml +0 -0
  128. metadata +201 -0
@@ -0,0 +1,40 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+
3
+ require 'test/unit'
4
+ require 'rgen/environment'
5
+ require 'rgen/serializer/json_serializer'
6
+ require 'rgen/instantiator/json_instantiator'
7
+ require 'concrete/metamodel/concrete_mmm'
8
+ require 'concrete/metamodel/ecore_to_concrete'
9
+
10
+ class MetamodelTest < Test::Unit::TestCase
11
+ include Concrete::Metamodel
12
+
13
+ TestDir = File.dirname(__FILE__)+"/metamodel_test"
14
+ def test_ecore_to_concrete
15
+ env = RGen::Environment.new
16
+ outfile = TestDir + "/concrete_mmm_generated.js"
17
+ ECoreToConcrete.new(nil, env).trans(ConcreteMMM.ecore.eClasses)
18
+ File.open(outfile, "w") do |f|
19
+ ser = RGen::Serializer::JsonSerializer.new(f)
20
+ ser.serialize(env.find(:class => ConcreteMMM::Classifier).sort{|a,b| a.name <=> b.name})
21
+ end
22
+ assert_equal File.read(TestDir+"/concrete_mmm_expected.js").strip, File.read(outfile).strip
23
+ end
24
+
25
+ def test_json_roundtrip
26
+ env = RGen::Environment.new
27
+ inst = RGen::Instantiator::JsonInstantiator.new(env, ConcreteMMM)
28
+ infile = TestDir + "/concrete_mmm_expected.js"
29
+ inst.instantiate(File.read(infile))
30
+ outfile = TestDir + "/concrete_mmm_regenerated.js"
31
+ File.open(outfile, "w") do |f|
32
+ # mark unresolved references, there should be no unresolved references
33
+ ser = RGen::Serializer::JsonSerializer.new(f, :identifierProvider => proc{|e| e.is_a?(RGen::MetamodelBuilder::MMProxy) && "xxx"})
34
+ ser.serialize(env.find(:class => ConcreteMMM::Classifier).sort{|a,b| a.name <=> b.name})
35
+ end
36
+ assert_equal File.read(infile).strip, File.read(outfile).strip
37
+ end
38
+
39
+ end
40
+
@@ -0,0 +1,19 @@
1
+ [ { "_class": "Datatype", "name": "Boolean" },
2
+ { "_class": "Class", "abstract": false, "superTypes": [ "/Classifier" ], "features": [
3
+ { "_class": "Feature", "name": "abstract", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/Boolean" },
4
+ { "_class": "Feature", "name": "superTypes", "kind": "reference", "lowerLimit": 0, "upperLimit": -1, "type": "/Class" },
5
+ { "_class": "Feature", "name": "features", "kind": "containment", "lowerLimit": 0, "upperLimit": -1, "type": "/Feature" }], "name": "Class" },
6
+ { "_class": "Class", "abstract": true, "features": [
7
+ { "_class": "Feature", "name": "name", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/String" }], "name": "Classifier" },
8
+ { "_class": "Class", "abstract": false, "superTypes": [ "/Classifier" ], "name": "Datatype" },
9
+ { "_class": "Class", "abstract": false, "superTypes": [ "/Datatype" ], "features": [
10
+ { "_class": "Feature", "name": "literals", "kind": "attribute", "lowerLimit": 0, "upperLimit": -1, "type": "/String" }], "name": "Enum" },
11
+ { "_class": "Class", "abstract": false, "features": [
12
+ { "_class": "Feature", "name": "name", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/String" },
13
+ { "_class": "Feature", "name": "kind", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/FeatureKind" },
14
+ { "_class": "Feature", "name": "lowerLimit", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/Integer" },
15
+ { "_class": "Feature", "name": "upperLimit", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/Integer" },
16
+ { "_class": "Feature", "name": "type", "kind": "reference", "lowerLimit": 0, "upperLimit": 1, "type": "/Classifier" }], "name": "Feature" },
17
+ { "_class": "Enum", "literals": [ "attribute", "reference", "containment" ], "name": "FeatureKind" },
18
+ { "_class": "Datatype", "name": "Integer" },
19
+ { "_class": "Datatype", "name": "String" }]
@@ -0,0 +1,19 @@
1
+ [ { "_class": "Datatype", "name": "Boolean" },
2
+ { "_class": "Class", "abstract": false, "superTypes": [ "/Classifier" ], "features": [
3
+ { "_class": "Feature", "name": "abstract", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/Boolean" },
4
+ { "_class": "Feature", "name": "superTypes", "kind": "reference", "lowerLimit": 0, "upperLimit": -1, "type": "/Class" },
5
+ { "_class": "Feature", "name": "features", "kind": "containment", "lowerLimit": 0, "upperLimit": -1, "type": "/Feature" }], "name": "Class" },
6
+ { "_class": "Class", "abstract": true, "features": [
7
+ { "_class": "Feature", "name": "name", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/String" }], "name": "Classifier" },
8
+ { "_class": "Class", "abstract": false, "superTypes": [ "/Classifier" ], "name": "Datatype" },
9
+ { "_class": "Class", "abstract": false, "superTypes": [ "/Datatype" ], "features": [
10
+ { "_class": "Feature", "name": "literals", "kind": "attribute", "lowerLimit": 0, "upperLimit": -1, "type": "/String" }], "name": "Enum" },
11
+ { "_class": "Class", "abstract": false, "features": [
12
+ { "_class": "Feature", "name": "name", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/String" },
13
+ { "_class": "Feature", "name": "kind", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/FeatureKind" },
14
+ { "_class": "Feature", "name": "lowerLimit", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/Integer" },
15
+ { "_class": "Feature", "name": "upperLimit", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/Integer" },
16
+ { "_class": "Feature", "name": "type", "kind": "reference", "lowerLimit": 0, "upperLimit": 1, "type": "/Classifier" }], "name": "Feature" },
17
+ { "_class": "Enum", "literals": [ "attribute", "reference", "containment" ], "name": "FeatureKind" },
18
+ { "_class": "Datatype", "name": "Integer" },
19
+ { "_class": "Datatype", "name": "String" }]
@@ -0,0 +1,19 @@
1
+ [ { "_class": "Datatype", "name": "Boolean" },
2
+ { "_class": "Class", "abstract": false, "superTypes": [ "/Classifier" ], "features": [
3
+ { "_class": "Feature", "name": "abstract", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/Boolean" },
4
+ { "_class": "Feature", "name": "superTypes", "kind": "reference", "lowerLimit": 0, "upperLimit": -1, "type": "/Class" },
5
+ { "_class": "Feature", "name": "features", "kind": "containment", "lowerLimit": 0, "upperLimit": -1, "type": "/Feature" }], "name": "Class" },
6
+ { "_class": "Class", "abstract": true, "features": [
7
+ { "_class": "Feature", "name": "name", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/String" }], "name": "Classifier" },
8
+ { "_class": "Class", "abstract": false, "superTypes": [ "/Classifier" ], "name": "Datatype" },
9
+ { "_class": "Class", "abstract": false, "superTypes": [ "/Datatype" ], "features": [
10
+ { "_class": "Feature", "name": "literals", "kind": "attribute", "lowerLimit": 0, "upperLimit": -1, "type": "/String" }], "name": "Enum" },
11
+ { "_class": "Class", "abstract": false, "features": [
12
+ { "_class": "Feature", "name": "name", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/String" },
13
+ { "_class": "Feature", "name": "kind", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/FeatureKind" },
14
+ { "_class": "Feature", "name": "lowerLimit", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/Integer" },
15
+ { "_class": "Feature", "name": "upperLimit", "kind": "attribute", "lowerLimit": 0, "upperLimit": 1, "type": "/Integer" },
16
+ { "_class": "Feature", "name": "type", "kind": "reference", "lowerLimit": 0, "upperLimit": 1, "type": "/Classifier" }], "name": "Feature" },
17
+ { "_class": "Enum", "literals": [ "attribute", "reference", "containment" ], "name": "FeatureKind" },
18
+ { "_class": "Datatype", "name": "Integer" },
19
+ { "_class": "Datatype", "name": "String" }]
@@ -0,0 +1,138 @@
1
+ <html>
2
+ <head>
3
+ <title>Concrete Unit test file</title>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
5
+ <script src="../../redist/prototype.js" type="text/javascript"></script>
6
+ <script src="../../redist/scriptaculous/unittest.js" type="text/javascript"></script>
7
+ <script type="text/javascript" language="javascript" charset="utf-8">
8
+ // <![CDATA[
9
+ var Concrete = {}
10
+ // ]]>
11
+ </script>
12
+ <script src="../../concrete/external_identifier_provider.js" type="text/javascript"></script>
13
+ <link rel="stylesheet" href="test.css" type="text/css" />
14
+ </head>
15
+ <body>
16
+ <h1>Concrete Unit test file</h1>
17
+ <p>
18
+ Tests for external_identifier_provider.js
19
+ </p>
20
+
21
+ <!-- Log output -->
22
+ <div id="testlog"> </div>
23
+
24
+ <!-- Tests follow -->
25
+ <script type="text/javascript" language="javascript" charset="utf-8">
26
+ // <![CDATA[
27
+
28
+ var Index1 =
29
+ [ { name: "Module1", elements: [
30
+ { name: "A", _class: "ClassA", elements: [
31
+ { name: "A1", _class: "ClassA" },
32
+ { name: "A2", _class: "ClassA" } ]},
33
+ { name: "B", _class: "ClassB", elements: [
34
+ { name: "B1", _class: "ClassB", elements: // value of "elements" not an Array here
35
+ { name: "B11", _class: "ClassB" } } ]} ]},
36
+ { name: "Module2", elements: [
37
+ { name: "AA", _class: "ClassA", elements: [
38
+ { name: "AA1", _class: "ClassA" },
39
+ { name: "AA2", _class: "ClassAA" } ]} ]},
40
+ { name: "Module3", elements: [
41
+ { name: "A", _class: "ClassA", elements: [
42
+ { name: "A1", _class: "ClassA" }]}]}
43
+ ];
44
+
45
+ new Test.Unit.Runner({
46
+
47
+ testGetElementInfo: function() { with(this) {
48
+ var mmp = {metaclassesByName: {"ClassA": "ClassAType"}};
49
+ var ip = new Concrete.IndexBasedExternalIdentifierProvider(Index1, mmp);
50
+
51
+ var ei = ip.getElementInfo(undefined);
52
+ assertEqual(false, ei);
53
+
54
+ ei = ip.getElementInfo("/A/A1");
55
+ assertEqual("ClassAType", ei.type);
56
+ assertEqual("Module1", ei.module);
57
+
58
+ ei = ip.getElementInfo("/A/A1", {ignoreModule: "Module1"});
59
+ assertEqual("ClassAType", ei.type);
60
+ assertEqual("Module3", ei.module);
61
+
62
+ ei = ip.getElementInfo("A/A2");
63
+ assertEqual("ClassAType", ei.type);
64
+ assertEqual("Module1", ei.module);
65
+
66
+ // /A/A3 does not exist
67
+ assertEqual(false, ip.getElementInfo("/A/A3"));
68
+
69
+ ei = ip.getElementInfo("/AA/AA1");
70
+ assertEqual("ClassAType", ei.type);
71
+ assertEqual("Module2", ei.module);
72
+
73
+ // /AA/AA2 exists but the classname can not be found in metamodel provider
74
+ assertEqual(false, ip.getElementInfo("/AA/AA2"));
75
+ }},
76
+
77
+ testGetIdentifiers: function() { with(this) {
78
+ var mmp = {metaclassesByName: {}};
79
+ var ip = new Concrete.IndexBasedExternalIdentifierProvider(Index1, mmp);
80
+
81
+ var classAType = {name: "ClassA", allSubTypes: function() {return []}};
82
+ var idents = ip.getIdentifiers(classAType);
83
+
84
+ assertEqual(7, idents.size());
85
+ assertEqual("/A", idents[0]);
86
+ assertEqual("/A/A1", idents[1]);
87
+ assertEqual("/A/A2", idents[2]);
88
+ assertEqual("/AA", idents[3]);
89
+ assertEqual("/AA/AA1", idents[4]);
90
+ assertEqual("/A", idents[5]);
91
+ assertEqual("/A/A1", idents[6]);
92
+
93
+ var classATypeWithSubtypes = {name: "ClassA", allSubTypes: function() {return [{name: "ClassAA", allSubTypes: function(){return []}}]}};
94
+ idents = ip.getIdentifiers(classATypeWithSubtypes);
95
+
96
+ assertEqual(8, idents.size());
97
+ assertEqual("/A", idents[0]);
98
+ assertEqual("/A/A1", idents[1]);
99
+ assertEqual("/A/A2", idents[2]);
100
+ assertEqual("/AA", idents[3]);
101
+ assertEqual("/AA/AA1", idents[4]);
102
+ assertEqual("/AA/AA2", idents[5]);
103
+ assertEqual("/A", idents[6]);
104
+ assertEqual("/A/A1", idents[7]);
105
+
106
+ var classBType = {name: "ClassB", allSubTypes: function() {return []}};
107
+ idents = ip.getIdentifiers(classBType);
108
+
109
+ assertEqual(3, idents.size());
110
+ assertEqual("/B", idents[0]);
111
+ assertEqual("/B/B1", idents[1]);
112
+ assertEqual("/B/B1/B11", idents[2]);
113
+ }},
114
+
115
+ testGetAllElementInfo: function() { with(this) {
116
+ var mmp = {metaclassesByName: {}};
117
+ var ip = new Concrete.IndexBasedExternalIdentifierProvider(Index1, mmp);
118
+
119
+ var eis = ip.getAllElementInfo();
120
+
121
+ assertEqual(11, eis.size());
122
+ assertEqual("/A", eis[0].identifier);
123
+ assertEqual("ClassA", eis[0].type);
124
+ assertEqual("Module1", eis[0].module);
125
+ assertEqual("/B/B1/B11", eis[5].identifier);
126
+ assertEqual("ClassB", eis[5].type);
127
+ assertEqual("Module1", eis[5].module);
128
+ assertEqual("/A/A1", eis[10].identifier);
129
+ assertEqual("ClassA", eis[10].type);
130
+ assertEqual("Module3", eis[10].module);
131
+ }}
132
+
133
+ });
134
+
135
+ // ]]>
136
+ </script>
137
+ </body>
138
+ </html>
@@ -0,0 +1,269 @@
1
+ <html>
2
+ <head>
3
+ <title>Concrete Unit test file</title>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
5
+ <script src="../../redist/prototype.js" type="text/javascript"></script>
6
+ <script src="../../redist/scriptaculous/unittest.js" type="text/javascript"></script>
7
+ <script type="text/javascript" language="javascript" charset="utf-8">
8
+ // <![CDATA[
9
+ var Concrete = {}
10
+ // ]]>
11
+ </script>
12
+ <script src="../../concrete/helper.js" type="text/javascript"></script>
13
+ <script src="../../concrete/element_extension.js" type="text/javascript"></script>
14
+ <script src="../../concrete/identifier_provider.js" type="text/javascript"></script>
15
+ <link rel="stylesheet" href="test.css" type="text/css" />
16
+ </head>
17
+ <body>
18
+ <h1>Concrete Unit test file</h1>
19
+ <p>
20
+ Tests for identifier_provider.js
21
+ </p>
22
+
23
+ <!-- Log output -->
24
+ <div id="testlog"> </div>
25
+
26
+ <div id="testModelSource" style="display: none">
27
+ <!-- two nested elements -->
28
+ <div class="ct_element">
29
+ <span class="ct_attribute"><span class="ct_slot"><span class="ct_value">E1</span></span></span>
30
+ <div class="ct_containment"><div class="ct_slot">
31
+ <div class="ct_element">
32
+ <span class="ct_attribute"><span class="ct_slot"><span class="ct_value">E11</span></span></span>
33
+ </div>
34
+ </div></div>
35
+ </div>
36
+ <!-- two nested elements with some div in between and multiple child elements -->
37
+ <div>
38
+ <div class="ct_element">
39
+ <span class="ct_attribute"><span class="ct_slot"><span class="ct_value">E2</span></span></span>
40
+ <div>
41
+ <div class="ct_containment"><div class="ct_slot">
42
+ <div class="ct_element">
43
+ <span class="ct_attribute"><span class="ct_slot"><span class="ct_value">E21</span></span></span>
44
+ </div>
45
+ <div class="ct_element">
46
+ <span class="ct_attribute"><span class="ct_slot"><span class="ct_value">E22</span></span></span>
47
+ </div>
48
+ </div></div>
49
+ <div class="ct_containment"><div class="ct_slot">
50
+ <div class="ct_element">
51
+ <span class="ct_attribute"><span class="ct_slot"><span class="ct_value">E23</span></span></span>
52
+ </div>
53
+ </div></div>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ <!-- two nested elements with other elements in between which don't have names -->
58
+ <div>
59
+ <div class="ct_element"> <!-- no name -->
60
+ <div class="ct_containment"><div class="ct_slot">
61
+ <div class="ct_element"> <!-- E3 -->
62
+ <span class="ct_attribute"><span class="ct_slot"><span class="ct_value">E3</span></span></span>
63
+ <div class="ct_containment"><div class="ct_slot">
64
+ <div class="ct_element"> <!-- no name -->
65
+ <div class="ct_containment"><div class="ct_slot">
66
+ <div class="ct_element"> <!-- E31 -->
67
+ <span class="ct_attribute"><span class="ct_slot"><span class="ct_value">E31</span></span></span>
68
+ </div>
69
+ </div></div>
70
+ </div>
71
+ </div></div>
72
+ </div>
73
+ </div></div>
74
+ </div>
75
+ </div>
76
+ <!-- duplicate identifier E1 -->
77
+ <div class="ct_element">
78
+ <span class="ct_attribute"><span class="ct_slot"><span class="ct_value">E1</span></span></span>
79
+ </div>
80
+ </div>
81
+
82
+ <div id="testModel" class="ct_root">
83
+ </div>
84
+
85
+ <!-- Tests follow -->
86
+ <script type="text/javascript" language="javascript" charset="utf-8">
87
+ // <![CDATA[
88
+
89
+ new Test.Unit.Runner({
90
+
91
+ setup: function() {
92
+ var testModel = $('testModel');
93
+ testModel.innerHTML = $('testModelSource').innerHTML;
94
+ setupModel(testModel);
95
+ },
96
+
97
+ testSimple: function() { with(this) {
98
+ var root = $('testModel');
99
+ var rootElements = root.childElements();
100
+ var ip = new Concrete.QualifiedNameBasedIdentifierProvider({nameAttribute: "name", separator: "/", leadingSeparator: true});
101
+
102
+ var e1 = rootElements[0];
103
+ var e1e11 = rootElements[0].down(".ct_element");
104
+
105
+ ip.elementAdded(e1);
106
+
107
+ assertEqual("/E1", ip.getIdentifier(e1));
108
+ assertEqual(e1, ip.getElement("/E1"));
109
+ assertEqual("/E1/E11", ip.getIdentifier(e1e11));
110
+ assertEqual(e1e11, ip.getElement("/E1/E11"));
111
+
112
+ var e2 = rootElements[1].down(".ct_element");
113
+ var e2e21 = rootElements[1].down(".ct_element").select(".ct_element")[0];
114
+ var e2e22 = rootElements[1].down(".ct_element").select(".ct_element")[1];
115
+ var e2e23 = rootElements[1].down(".ct_element").select(".ct_element")[2];
116
+
117
+ ip.elementAdded(e2);
118
+
119
+ assertEqual("/E2", ip.getIdentifier(e2));
120
+ assertEqual("/E2/E21", ip.getIdentifier(e2e21));
121
+ assertEqual("/E2/E22", ip.getIdentifier(e2e22));
122
+ assertEqual("/E2/E23", ip.getIdentifier(e2e23));
123
+ assertEqual(e2, ip.getElement("/E2"));
124
+ assertEqual(e2e21, ip.getElement("/E2/E21"));
125
+ assertEqual(e2e22, ip.getElement("/E2/E22"));
126
+ assertEqual(e2e23, ip.getElement("/E2/E23"));
127
+
128
+ var e3 = rootElements[2].down(".ct_element").down(".ct_element");
129
+ var e3e31 = rootElements[2].down(".ct_element").down(".ct_element").down(".ct_element").down(".ct_element");
130
+
131
+ ip.elementAdded(e3);
132
+
133
+ assertEqual("/E3", ip.getIdentifier(e3));
134
+ assertEqual("/E3/E31", ip.getIdentifier(e3e31));
135
+ assertEqual(e3, ip.getElement("/E3"));
136
+ assertEqual(e3e31, ip.getElement("/E3/E31"));
137
+ }},
138
+
139
+ testRename: function() { with(this) {
140
+ var root = $('testModel');
141
+ var rootElements = root.childElements();
142
+ var ip = new Concrete.QualifiedNameBasedIdentifierProvider({nameAttribute: "name", separator: "/", leadingSeparator: true});
143
+
144
+ var e1 = rootElements[0];
145
+ var e1e11 = rootElements[0].down(".ct_element");
146
+
147
+ ip.elementAdded(e1);
148
+
149
+ var value = e1.down(".ct_attribute").down(".ct_value")
150
+ value.textContent = "X";
151
+ value.value = value.textContent;
152
+
153
+ ip.elementChanged(e1, undefined);
154
+
155
+ assertEqual("/X", ip.getIdentifier(e1));
156
+ assertEqual(undefined, ip.getElement("/E1"));
157
+ assertEqual(e1, ip.getElement("/X"));
158
+ assertEqual("/X/E11", ip.getIdentifier(e1e11));
159
+ assertEqual(undefined, ip.getElement("/E1/E11"));
160
+ assertEqual(e1e11, ip.getElement("/X/E11"));
161
+ }},
162
+
163
+ testRemoveName: function() { with(this) {
164
+ var root = $('testModel');
165
+ var rootElements = root.childElements();
166
+ var ip = new Concrete.QualifiedNameBasedIdentifierProvider({nameAttribute: "name", separator: "/", leadingSeparator: true});
167
+
168
+ var e1 = rootElements[0];
169
+ var e1e11 = rootElements[0].down(".ct_element");
170
+
171
+ ip.elementAdded(e1);
172
+
173
+ e1.down(".ct_attribute").down(".ct_value").remove();
174
+
175
+ ip.elementChanged(e1, undefined);
176
+ assertEqual(undefined, ip.getIdentifier(e1));
177
+ assertEqual(undefined, ip.getElement("/E1"));
178
+ assertEqual("/E11", ip.getIdentifier(e1e11));
179
+ assertEqual(undefined, ip.getElement("/E1/E11"));
180
+ assertEqual(e1e11, ip.getElement("/E11"));
181
+ }},
182
+
183
+ testRemoveElement: function() { with(this) {
184
+ var root = $('testModel');
185
+ var rootElements = root.childElements();
186
+ var ip = new Concrete.QualifiedNameBasedIdentifierProvider({nameAttribute: "name", separator: "/", leadingSeparator: true});
187
+
188
+ var e1 = rootElements[0];
189
+ var e1e11 = rootElements[0].down(".ct_element");
190
+
191
+ ip.elementAdded(e1);
192
+ ip.elementRemoved(e1);
193
+
194
+ assertEqual(undefined, ip.getIdentifier(e1));
195
+ assertEqual(undefined, ip.getElement("/E1"));
196
+ assertEqual(undefined, ip.getIdentifier(e1e11));
197
+ assertEqual(undefined, ip.getElement("/E1/E11"));
198
+ }},
199
+
200
+ testBeforeChange: function() { with(this) {
201
+ var root = $('testModel');
202
+ var rootElements = root.childElements();
203
+ var ip = new Concrete.QualifiedNameBasedIdentifierProvider({nameAttribute: "name", separator: "/", leadingSeparator: true});
204
+
205
+ var e1 = rootElements[0];
206
+ var e1e11 = rootElements[0].down(".ct_element");
207
+
208
+ assertEqual(undefined, ip.getIdentifier(e1));
209
+ assertEqual(undefined, ip.getElement("/E1"));
210
+ assertEqual(undefined, ip.getIdentifier(e1e11));
211
+ assertEqual(undefined, ip.getElement("/E1/E11"));
212
+ }},
213
+
214
+ testDuplicateIdentifier: function() { with(this) {
215
+ var root = $('testModel');
216
+ var rootElements = root.childElements();
217
+ var ip = new Concrete.QualifiedNameBasedIdentifierProvider({nameAttribute: "name", separator: "/", leadingSeparator: true});
218
+
219
+ var e1 = rootElements[0];
220
+ var e4 = rootElements[3];
221
+
222
+ ip.elementAdded(e1);
223
+ assertEqual("/E1", ip.getIdentifier(e1));
224
+ assertEqual(e1, ip.getElement("/E1"));
225
+
226
+ ip.elementAdded(e4);
227
+ // e1 still has its old identifier
228
+ assertEqual("/E1", ip.getIdentifier(e1));
229
+ // e4 has the same identifier
230
+ assertEqual("/E1", ip.getIdentifier(e4));
231
+ // getElement returns an Array holding e1 and e4
232
+ assertEqual(2, ip.getElement("/E1").size());
233
+ assertEqual(e1, ip.getElement("/E1")[0]);
234
+ assertEqual(e4, ip.getElement("/E1")[1]);
235
+
236
+ ip.elementRemoved(e1);
237
+ assertEqual(e4, ip.getElement("/E1"));
238
+
239
+ ip.elementRemoved(e4)
240
+ assertEqual(undefined, ip.getElement("/E1"));
241
+ }},
242
+
243
+ })
244
+
245
+ function setupModel(root) {
246
+ root.select(".ct_element").each(function(e) {
247
+ e.features = e.findFirstDescendants(["ct_attribute", "ct_reference", "ct_containment"], ["ct_element"]);
248
+ var i = 1;
249
+ e.features.each(function(f) {
250
+ f.slot = f.down(".ct_slot");
251
+ if (f.hasClassName("ct_attribute")) {
252
+ f.mmFeature = {name: "name", kind: "attribute", type: "String"};
253
+ f.mmFeature.isContainment = function() { return false; };
254
+ }
255
+ else if (f.hasClassName("ct_containment")) {
256
+ f.mmFeature = {name: "sub"+i, kind: "containment"};
257
+ f.mmFeature.isContainment = function() { return true; };
258
+ }
259
+ f.slot.select(".ct_value").each(function(v) {
260
+ v.value = v.textContent;
261
+ });
262
+ i++;
263
+ });
264
+ });
265
+ }
266
+ // ]]>
267
+ </script>
268
+ </body>
269
+ </html>