~holger-seelig/cobweb.js/trunk

« back to all changes in this revision

Viewing changes to src/cobweb/Components/Core/X3DPrototypeInstance.js

  • Committer: Holger Seelig
  • Date: 2017-08-22 04:53:24 UTC
  • Revision ID: holger.seelig@yahoo.de-20170822045324-4of4xxgt79669gbt
Switched to npm.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: JavaScript; coding: utf-8; tab-width: 3; indent-tabs-mode: tab; c-basic-offset: 3 -*-
 
2
 *******************************************************************************
 
3
 *
 
4
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
5
 *
 
6
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011.
 
7
 *
 
8
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 
9
 *
 
10
 * The copyright notice above does not evidence any actual of intended
 
11
 * publication of such source code, and is an unpublished work by create3000.
 
12
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 
13
 * create3000.
 
14
 *
 
15
 * No permission is granted to copy, distribute, or create derivative works from
 
16
 * the contents of this software, in whole or in part, without the prior written
 
17
 * permission of create3000.
 
18
 *
 
19
 * NON-MILITARY USE ONLY
 
20
 *
 
21
 * All create3000 software are effectively free software with a non-military use
 
22
 * restriction. It is free. Well commented source is provided. You may reuse the
 
23
 * source in any way you please with the exception anything that uses it must be
 
24
 * marked to indicate is contains 'non-military use only' components.
 
25
 *
 
26
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
27
 *
 
28
 * Copyright 2015, 2016 Holger Seelig <holger.seelig@yahoo.de>.
 
29
 *
 
30
 * This file is part of the Cobweb Project.
 
31
 *
 
32
 * Cobweb is free software: you can redistribute it and/or modify it under the
 
33
 * terms of the GNU General Public License version 3 only, as published by the
 
34
 * Free Software Foundation.
 
35
 *
 
36
 * Cobweb is distributed in the hope that it will be useful, but WITHOUT ANY
 
37
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 
38
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 
39
 * details (a copy is included in the LICENSE file that accompanied this code).
 
40
 *
 
41
 * You should have received a copy of the GNU General Public License version 3
 
42
 * along with Cobweb.  If not, see <http://www.gnu.org/licenses/gpl.html> for a
 
43
 * copy of the GPLv3 License.
 
44
 *
 
45
 * For Silvio, Joy and Adi.
 
46
 *
 
47
 ******************************************************************************/
 
48
 
 
49
 
 
50
define ([
 
51
        "jquery",
 
52
        "cobweb/Basic/FieldDefinitionArray",
 
53
        "cobweb/Fields",
 
54
        "cobweb/Base/X3DChildObject",
 
55
        "cobweb/Components/Core/X3DNode",
 
56
        "cobweb/Execution/X3DExecutionContext",
 
57
        "cobweb/Bits/X3DConstants",
 
58
        "cobweb/InputOutput/Generator",
 
59
],
 
60
function ($,
 
61
          FieldDefinitionArray,
 
62
          Fields,
 
63
          X3DChildObject,
 
64
          X3DNode,
 
65
          X3DExecutionContext,
 
66
          X3DConstants,
 
67
          Generator)
 
68
{
 
69
"use strict";
 
70
 
 
71
        function X3DPrototypeInstance (executionContext, protoNode)
 
72
        {
 
73
                this .protoNode        = protoNode;
 
74
                this .fieldDefinitions = new FieldDefinitionArray (protoNode .getFieldDefinitions () .getValue () .slice ());
 
75
 
 
76
                X3DNode             .call (this, executionContext);
 
77
                X3DExecutionContext .call (this, executionContext);
 
78
 
 
79
                this .addType (X3DConstants .X3DPrototypeInstance);
 
80
                this .getRootNodes () .setAccessType (X3DConstants .initializeOnly);
 
81
 
 
82
                this .getScene () .addInitLoadCount (this);
 
83
 
 
84
                if (protoNode .isExternProto)
 
85
                        protoNode .requestAsyncLoad (this .construct .bind (this));
 
86
 
 
87
                else
 
88
                        this .construct ();
 
89
        }
 
90
 
 
91
        X3DPrototypeInstance .prototype = $.extend (Object .create (X3DExecutionContext .prototype),
 
92
                X3DNode .prototype,
 
93
        {
 
94
                constructor: X3DPrototypeInstance,
 
95
                create: function (executionContext)
 
96
                {
 
97
                        return new X3DPrototypeInstance (executionContext, this .protoNode);
 
98
                },
 
99
                getTypeName: function ()
 
100
                {
 
101
                        return this .protoNode .getName ();
 
102
                },
 
103
                getComponentName: function ()
 
104
                {
 
105
                        return "Core";
 
106
                },
 
107
                getContainerField: function ()
 
108
                {
 
109
                        return "children";
 
110
                },
 
111
                construct: function ()
 
112
                {
 
113
                        this .getScene () .removeInitLoadCount (this);
 
114
 
 
115
                        var proto = this .protoNode .getProtoDeclaration ();
 
116
 
 
117
                        if (proto)
 
118
                        {
 
119
                                // If there is a proto the externproto is completely loaded.
 
120
                        
 
121
                                if (! this .metadata_ .getSet ())
 
122
                                        this .metadata_ = proto .metadata_;
 
123
 
 
124
                                if (this .protoNode .isExternProto)
 
125
                                {
 
126
                                        var fieldDefinitions = proto .getFieldDefinitions ();
 
127
 
 
128
                                        for (var i = 0, length = fieldDefinitions .length; i < length; ++ i)
 
129
                                        {
 
130
                                                try
 
131
                                                {
 
132
                                                        var
 
133
                                                                fieldDefinition = fieldDefinitions [i],
 
134
                        field           = this .getField (fieldDefinition .name),
 
135
                                                                protoField      = proto .getField (fieldDefinition .name);
 
136
 
 
137
                                                        // Continue if something is wrong.
 
138
                                                        if (field .getAccessType () !== protoField .getAccessType ())
 
139
                                                                continue;
 
140
 
 
141
                                                        // Continue if something is wrong.
 
142
                                                        if (field .getType () !== protoField .getType ())
 
143
                                                                continue;
 
144
 
 
145
                                                        // Continue if field is eventIn or eventOut.
 
146
                                                        if (! (field .getAccessType () & X3DConstants .initializeOnly))
 
147
                                                                continue;
 
148
 
 
149
                                                        // Is set during parse. 
 
150
                                                        if (field .getSet ())
 
151
                                                                continue;
 
152
 
 
153
                                                        // Has IS references.
 
154
                                                        if (field .hasReferences ())
 
155
                                                                continue;
 
156
 
 
157
                                                        field .setValue (protoField .getValue ());
 
158
                                                }
 
159
                                                catch (error)
 
160
                                                {
 
161
                                                        // Definition exists in proto but does not exist in extern proto.
 
162
                                                        this .addField (fieldDefinition);
 
163
                                                }
 
164
                                        }
 
165
                                }
 
166
 
 
167
                                // Assign metadata.
 
168
 
 
169
                                this .setURL (proto .getURL ());
 
170
 
 
171
                                this .importExternProtos (proto .externprotos);
 
172
                                this .importProtos       (proto .protos);
 
173
                                this .copyRootNodes      (proto .rootNodes);
 
174
 
 
175
                                if (this .isInitialized ())
 
176
                                {
 
177
                                        this .setup ();
 
178
                                        X3DChildObject .prototype .addEvent .call (this);
 
179
                                }
 
180
                        }
 
181
                },
 
182
                setup: function ()
 
183
                {
 
184
                        X3DNode             .prototype .setup .call (this);
 
185
                        X3DExecutionContext .prototype .setup .call (this);
 
186
                },
 
187
                initialize: function ()
 
188
                {
 
189
                        try
 
190
                        {
 
191
                                var proto = this .protoNode .getProtoDeclaration ();
 
192
 
 
193
                                if (proto)
 
194
                                {
 
195
                                        //this .copyImportedNodes (proto);
 
196
                                        this .copyRoutes (proto .routes);
 
197
                                }
 
198
 
 
199
                                // TODO: connect getRootNodes () to X3DChildObject .prototype .addEvent .call (this);
 
200
 
 
201
                                // Now initialize bases.
 
202
        
 
203
                                X3DNode             .prototype .initialize .call (this);
 
204
                                X3DExecutionContext .prototype .initialize .call (this);
 
205
                        }
 
206
                        catch (error)
 
207
                        {
 
208
                                console .error (error .message);
 
209
                        }
 
210
                },
 
211
                getExtendedEventHandling: function ()
 
212
                {
 
213
                        return false;
 
214
                },
 
215
                getInnerNode: function ()
 
216
                {
 
217
                        var rootNodes = this .getRootNodes () .getValue ();
 
218
                        
 
219
                        if (rootNodes .length)
 
220
                        {
 
221
                                var rootNode = rootNodes [0];
 
222
                                
 
223
                                if (rootNode)
 
224
                                        return rootNode .getValue () .getInnerNode ();
 
225
                        }
 
226
 
 
227
                        throw new Error ("Root node not available.");
 
228
                },
 
229
                importExternProtos: function (externprotos)
 
230
                {
 
231
                        for (var i = 0, length = externprotos .length; i < length; ++ i)
 
232
                                this .externprotos .add (externprotos [i] .getName (), externprotos [i]);
 
233
                },
 
234
                importProtos: function (protos)
 
235
                {
 
236
                        for (var i = 0, length = protos .length; i < length; ++ i)
 
237
                                this .protos .add (protos [i] .getName (), protos [i]);
 
238
                },
 
239
                copyRootNodes: function (rootNodes)
 
240
                {
 
241
                        var
 
242
                                rootNodes1 = rootNodes .getValue (),
 
243
                                rootNodes2 = this  .getRootNodes () .getValue ();
 
244
 
 
245
                        for (var i = 0, length = rootNodes1 .length; i < length; ++ i)
 
246
                        {
 
247
                                var value = rootNodes1 [i] .copy (this);
 
248
                                value .addParent (this .getRootNodes ());
 
249
                                rootNodes2 .push (value);
 
250
                        }
 
251
                },
 
252
                copyRoutes: function (routes)
 
253
                {
 
254
                        for (var i = 0, length = routes .length; i < length; ++ i)
 
255
                        {
 
256
                                try
 
257
                                {
 
258
                                        var route = routes [i];
 
259
 
 
260
                                        // new Route ... addUninitializedNode ...
 
261
                                        this .addRoute (this .getNamedNode (route .sourceNode .getNodeName ()),
 
262
                                                        route .sourceField,
 
263
                                                        this .getNamedNode (route .destinationNode .getNodeName ()),
 
264
                                                        route .destinationField);
 
265
                                }
 
266
                                catch (error)
 
267
                                {
 
268
                                        console .log (error);
 
269
                                }
 
270
                        }
 
271
                },
 
272
                toXMLStream: function (stream)
 
273
                {
 
274
                        if (Generator .IsSharedNode (this))
 
275
                        {
 
276
                                stream .string += Generator .Indent ();
 
277
                                stream .string += "<!-- NULL -->";              
 
278
                                return;
 
279
                        }
 
280
 
 
281
                        Generator .EnterScope ();
 
282
 
 
283
                        var name = Generator .Name (this);
 
284
 
 
285
                        if (name .length)
 
286
                        {
 
287
                                if (Generator .ExistsNode (this))
 
288
                                {
 
289
                                        stream .string += Generator .Indent ();
 
290
                                        stream .string += "<ProtoInstance";
 
291
                                        stream .string += " ";
 
292
                                        stream .string += "name='";
 
293
                                        stream .string += Generator .XMLEncode (this .getTypeName ());
 
294
                                        stream .string += "'";
 
295
                                        stream .string += " ";
 
296
                                        stream .string += "USE='";
 
297
                                        stream .string += Generator .XMLEncode (name);
 
298
                                        stream .string += "'";
 
299
 
 
300
                                        var containerField = Generator .ContainerField ();
 
301
 
 
302
                                        if (containerField)
 
303
                                        {
 
304
                                                if (containerField .getName () !== this .getContainerField ())
 
305
                                                {
 
306
                                                        stream .string += " ";
 
307
                                                        stream .string += "containerField='";
 
308
                                                        stream .string += Generator .XMLEncode (containerField .getName ());
 
309
                                                        stream .string += "'";
 
310
                                                }
 
311
                                        }
 
312
 
 
313
                                        stream .string += "/>";
 
314
 
 
315
                                        Generator .LeaveScope ();
 
316
                                        return;
 
317
                                }
 
318
                        }
 
319
 
 
320
                        stream .string += Generator .Indent ();
 
321
                        stream .string += "<ProtoInstance";
 
322
                        stream .string += " ";
 
323
                        stream .string += "name='";
 
324
                        stream .string += Generator .XMLEncode (this .getTypeName ());
 
325
                        stream .string += "'";
 
326
 
 
327
                        if (name .length)
 
328
                        {
 
329
                                Generator .AddNode (this);
 
330
 
 
331
                                stream .string += " ";
 
332
                                stream .string += "DEF='";
 
333
                                stream .string += Generator .XMLEncode (name);
 
334
                                stream .string += "'";
 
335
                        }
 
336
 
 
337
                        var containerField = Generator .ContainerField ();
 
338
 
 
339
                        if (containerField)
 
340
                        {
 
341
                                if (containerField .getName () !== this .getContainerField ())
 
342
                                {
 
343
                                        stream .string += " ";
 
344
                                        stream .string += "containerField='";
 
345
                                        stream .string += Generator .XMLEncode (containerField .getName ());
 
346
                                        stream .string += "'";
 
347
                                }
 
348
                        }
 
349
                
 
350
                        var
 
351
                                fields   = this .getChangedFields (),
 
352
                                metadata = this .metadata_;
 
353
 
 
354
                        try
 
355
                        {
 
356
                                metadata = this .getField ("metadata");
 
357
                        }
 
358
                        catch (error)
 
359
                        { }
 
360
 
 
361
                        if (metadata === this .metadata_)
 
362
                        {
 
363
                                fields = fields .filter (function (value) { return value !== this .metadata_; } .bind (this));
 
364
                        }
 
365
 
 
366
                        if (fields .length === 0 && (metadata === this .metadata_ ? true || ! metadata .getValue () : true))
 
367
                        {
 
368
                                stream .string += "/>";
 
369
                        }
 
370
                        else
 
371
                        {
 
372
                                stream .string += ">\n";
 
373
 
 
374
                                Generator .IncIndent ();
 
375
 
 
376
                                var references = [ ];
 
377
 
 
378
                                for (var i = 0, length = fields .length; i < length; ++ i)
 
379
                                {
 
380
                                        var field = fields [i];
 
381
 
 
382
                                        // If the field is a inputOutput and we have as reference only inputOnly or outputOnly we must output the value
 
383
                                        // for this field.
 
384
 
 
385
                                        var mustOutputValue = false;
 
386
 
 
387
                                        if (Generator .ExecutionContext ())
 
388
                                        {
 
389
                                                if (field .getAccessType () === X3DConstants .inputOutput && ! $.isEmptyObject (field .getReferences ()))
 
390
                                                {
 
391
                                                        var
 
392
                                                                initializableReference = false,
 
393
                                                                fieldReferences        = field .getReferences ();
 
394
 
 
395
                                                        for (var id in fieldReferences)
 
396
                                                        {
 
397
                                                                initializableReference |= fieldReferences [id] .isInitializable ();
 
398
                                                        }
 
399
 
 
400
                                                        if (! initializableReference)
 
401
                                                                mustOutputValue = true;
 
402
                                                }
 
403
                                        }
 
404
 
 
405
                                        // If we have no execution context we are not in a proto and must not generate IS references the same is true
 
406
                                        // if the node is a shared node as the node does not belong to the execution context.
 
407
 
 
408
                                        if ($.isEmptyObject (field .getReferences ()) || ! Generator .ExecutionContext () || mustOutputValue)
 
409
                                        {
 
410
                                                if (mustOutputValue)
 
411
                                                        references .push (field);
 
412
 
 
413
                                                switch (field .getType ())
 
414
                                                {
 
415
                                                        case X3DConstants .MFNode:
 
416
                                                        {
 
417
                                                                stream .string += Generator .Indent ();
 
418
                                                                stream .string += "<fieldValue";
 
419
                                                                stream .string += " ";
 
420
                                                                stream .string += "name='";
 
421
                                                                stream .string += Generator .XMLEncode (field .getName ());
 
422
                                                                stream .string += "'";
 
423
 
 
424
                                                                if (field .length === 0)
 
425
                                                                {
 
426
                                                                        stream .string += "/>\n";
 
427
                                                                }
 
428
                                                                else
 
429
                                                                {
 
430
                                                                        stream .string += ">\n";
 
431
 
 
432
                                                                        Generator .IncIndent ();
 
433
 
 
434
                                                                        field .toXMLStream (stream);
 
435
 
 
436
                                                                        stream .string += "\n";
 
437
 
 
438
                                                                        Generator .DecIndent ();
 
439
 
 
440
                                                                        stream .string += Generator .Indent ();
 
441
                                                                        stream .string += "</fieldValue>\n";
 
442
                                                                }
 
443
 
 
444
                                                                break;
 
445
                                                        }
 
446
                                                        case X3DConstants .SFNode:
 
447
                                                        {
 
448
                                                                if (field .getValue () !== null)
 
449
                                                                {
 
450
                                                                        stream .string += Generator .Indent ();
 
451
                                                                        stream .string += "<fieldValue";
 
452
                                                                        stream .string += " ";
 
453
                                                                        stream .string += "name='";
 
454
                                                                        stream .string += Generator .XMLEncode (field .getName ())
 
455
                                                                        stream .string += "'";
 
456
                                                                        stream .string += ">\n";
 
457
                                                                        
 
458
                                                                        Generator .IncIndent ();
 
459
 
 
460
                                                                        field .toXMLStream (stream);
 
461
 
 
462
                                                                        stream .string += "\n";
 
463
 
 
464
                                                                        Generator .DecIndent ();
 
465
 
 
466
                                                                        stream .string += Generator .Indent ();
 
467
                                                                        stream .string += "</fieldValue>\n";            
 
468
                                                                        break;
 
469
                                                                }
 
470
                
 
471
                                                                // Proceed with next case.
 
472
                                                        }
 
473
                                                        default:
 
474
                                                        {
 
475
                                                                stream .string += Generator .Indent ();
 
476
                                                                stream .string += "<fieldValue";
 
477
                                                                stream .string += " ";
 
478
                                                                stream .string += "name='";
 
479
                                                                stream .string += Generator .XMLEncode (field .getName ())
 
480
                                                                stream .string += "'";
 
481
                                                                stream .string += " ";
 
482
                                                                stream .string += "value='";
 
483
 
 
484
                                                                field .toXMLStream (stream);
 
485
 
 
486
                                                                stream .string += "'";
 
487
                                                                stream .string += "/>\n";
 
488
                                                                break;
 
489
                                                        }
 
490
                                                }
 
491
                                        }
 
492
                                        else
 
493
                                        {
 
494
                                                references .push (field);
 
495
                                        }
 
496
                                }
 
497
 
 
498
                                if (references .length)
 
499
                                {
 
500
                                        stream .string += Generator .Indent ();
 
501
                                        stream .string += "<IS>";
 
502
                                        stream .string += "\n";
 
503
 
 
504
                                        Generator .IncIndent ();
 
505
                
 
506
                                        for (var i = 0, length = references .length; i < length; ++ i)
 
507
                                        {
 
508
                                                var
 
509
                                                        field       = references [i],
 
510
                                                        protoFields = field .getReferences ()
 
511
 
 
512
                                                for (var id in protoFields)
 
513
                                                {
 
514
                                                        var protoField = protoFields [id];
 
515
 
 
516
                                                        stream .string += Generator .Indent ();
 
517
                                                        stream .string += "<connect";
 
518
                                                        stream .string += " ";
 
519
                                                        stream .string += "nodeField='";
 
520
                                                        stream .string += Generator .XMLEncode (field .getName ());
 
521
                                                        stream .string += "'";
 
522
                                                        stream .string += " ";
 
523
                                                        stream .string += "protoField='";
 
524
                                                        stream .string += Generator .XMLEncode (protoField .getName ());
 
525
                                                        stream .string += "'";
 
526
                                                        stream .string += "/>\n";
 
527
                                                }
 
528
                                        }
 
529
 
 
530
                                        Generator .DecIndent ();
 
531
 
 
532
                                        stream .string += Generator .Indent ();
 
533
                                        stream .string += "</IS>\n";
 
534
                                }
 
535
 
 
536
                                if (metadata === this .metadata_)
 
537
                                {
 
538
                                        if (metadata .getValue ())
 
539
                                        {
 
540
                                                metadata .toXMLStream (stream);
 
541
 
 
542
                                                stream .string += "\n";
 
543
                                        }
 
544
                                }
 
545
 
 
546
                                Generator .DecIndent ();
 
547
 
 
548
                                stream .string += Generator .Indent ();
 
549
                                stream .string += "</ProtoInstance>";
 
550
                        }
 
551
 
 
552
                        Generator .LeaveScope ();
 
553
                },
 
554
        });
 
555
 
 
556
        return X3DPrototypeInstance;
 
557
});
 
558
 
 
559