source: sandbox/2.4.1-3/prototype/api/datalayer.js @ 6514

Revision 6514, 128.8 KB checked in by gustavo, 12 years ago (diff)

Ticket #2766 - implementacao da dfd0065 e correcao de bugs da dfd0099

  • Property svn:executable set to *
Line 
1   internalUrl = /^([A-z0-9-_]+)(:[A-z0-9-_]+)?$/;
2internalUri = /^([a-zA-Z0-9-_]+)\(([a-zA-Z0-9-_]+)\):\/\/(.*)|([a-zA-Z0-9-_]+):\/\/(.*)$/;
3isGeneratedId = /^\d+\(javascript\)$/;
4arrayName = /^([A-z0-9-_]+)\[\]$/;
5startsDoubleDot = /^:/;
6isIframe = /^iframe.*/;
7FILE = 'files';
8// cached_urls = {};
9
10$.ajaxPrefilter(function( options, originalOptions, jqXHR ){
11
12      if( options.url != 'undefined' && internalUrl.test( options.url ) ){
13
14//        if( !cached_urls[options.url] )
15//            return;
16//        alert( options.url + " dentro" );
17
18           var callback = ( options.success || options.complete || $.noop );
19
20          if( isIframe.test( options.dataType ) || options.data instanceof FormData )
21          {
22              options.url = options.fileInput.parents( 'form' ).attr( 'action' );
23           
24              res = internalUrl.exec( options.url );
25
26              var data = {};
27
28              data[ res[1] ] = DataLayer.form( options.fileInput.parents( 'form' ), options.fileInput );
29
30              options.formData = DataLayer.serializeForm( data );
31
32              callback = function( data ){
33
34                    //coutinho, escreva seu codigo aqui.
35
36                    return callback( DataLayer.encode( res[2], data ) );
37
38              }
39
40              options.url = DataLayer.dispatchPath + 'post.php';
41
42              if( typeof FormData !== "undefined" && options.data instanceof FormData )
43              {
44                  options.data = new FormData();
45
46                  $.each(options.formData, function (index, field) {
47                            options.data.append(field.name, field.value);
48                        });
49                 
50                  $.each(options.files, function (index, file) {
51                            options.data.append(options.paramName, file);
52                        });
53              }
54
55              return( true );
56          }
57
58          jqXHR.abort();
59
60          switch( options.type.toUpperCase() )
61          {
62            case 'GET':
63                  return callback( DataLayer.get( options.url, /*false,*/ options.data ) );
64
65            case 'POST':
66                  return callback( DataLayer.put( options.url, options.data ) );
67          }
68
69          //return( false );
70
71//        options.url = params[1];
72//        options.data = ( options.data || "" ) + "&" + params[2];
73      }
74
75});
76
77// $("a").live("click", function( event ){
78//
79//     event.preventDefault();
80//
81//     $.ajax({
82//
83//     
84//
85//     });
86//
87// });
88
89$("form").live( "submit", function( event ){
90
91    var $this = $(this), action = $this.attr('action'), res = false,
92   
93    method = $this.attr( 'method' ) || 'POST',
94   
95    fileInputs = $this.find('input[type="file"]');
96   
97    if( fileInputs.length && !$this.is('[enctype="multipart/form-data"]') )
98    {
99        event.preventDefault();
100
101        DataLayer.send( action,
102                        [ method, 'iframe json' ], {},
103                        //TODO: check the type for conversion
104                        DataLayer.receive,
105                        false, { 'formData': $this.serializeArray(),  'fileInput': fileInputs, 'paramName': FILE + '[]' } );
106
107        return( false );
108    }
109   
110    if( res = internalUrl.exec( action ) )
111    {
112        event.preventDefault();
113
114        var data = DataLayer.form( this );
115       
116        switch( method.toUpperCase() )
117        {
118          case 'GET':
119                DataLayer.get( res[0], data );
120
121          case 'POST':
122                DataLayer.put( res[1], data );
123        }
124
125        return( false );
126    }
127
128    return( true );
129});
130
131this.storage = new $.store();
132
133DataLayer = {
134
135    links: {},
136    nestedLinks: {},
137    concepts: {},
138    notArray: {},
139    listeners: {},
140    encoders: {},
141    decoders: {},
142    templates: {},
143    criterias: {},
144    tasks: {},
145   
146    /**
147     * A função render é responsável pela integração dos templates com os dados provenientes do conceito, ou mesmo dados custom.
148     *
149     * Use:
150     *
151     * DataLayer.render (
152     *                   'template/listaEmArvore',                                                              //aqui se passa a URL do template em questão
153     *                   'folder:tree' OR { 'node': ['1', '2', '3'] },                                          //aqui se passa o conceito da qual o template vai ser compilado, juntamente com seu respectivo codec
154     *                   '123' OR [ 'AND', [ '=', 'name', 'dedeu' ], [ '=', 'icon', 'folder.png' ] ] OR false   //aqui se passa um id ou filtro quando for nescessário filtrar os conceitos que vão ser usados no render.
155     *                                                                                                          //Se for suprimido, ou receber false, são trazidos todos os conceitos sem filtro
156     *                  );
157     */
158
159    render: function( templateName, data, filter, formatter, force ){
160
161        if( $.isFunction( filter ) )
162        {
163            force = formatter;
164            formatter = filter;
165            filter = false;
166        }
167
168        if( typeof data === "string" )
169        {
170            data = this.get( data, filter, force ) || {};
171        }
172       
173        var formatting = function( template ){
174
175              if( template === false ) return( false );
176
177              if( template )
178                  DataLayer.templates[ templateName ] = new EJS({ text: template, cache: false });
179
180              var html = DataLayer.templates[ templateName ].render( { data: data } );
181
182              if( !formatter )
183                  return( html );
184
185              return formatter( html );
186        }
187
188        if( this.templates[ templateName ] )
189        {
190            return formatting();
191        }
192
193        return this.send( DataLayer.templatePath + templateName, 'get', false, formatting, !!!formatter );
194    },
195   
196    send: function( url, type, data, callback, sync, extraOptions ){
197
198          var result = false, fired = false;
199     
200          var envelope = {
201
202              'async': ( typeof sync !== "undefined" ? !sync : !!callback ),
203              'url': url,
204              'success': function( dt, textStatus, jqXHR ){
205
206                    if( callback )
207                    {
208                        fired = true;
209                        result = callback( dt, textStatus, jqXHR );
210                    }
211                    else
212                        result = dt;
213
214                },
215              'error': function( dt, textStatus, jqXHR ){
216
217                    if( callback )
218                    {
219                        fired = true;
220                        result = callback( $.parseJSON(dt.responseText), textStatus, jqXHR );
221                    }
222                    else
223                        result = $.parseJSON(dt.responseText);
224
225                },
226              'complete': function( jqXHR, textStatus ){
227
228                  if( !fired && callback )
229                      result = callback( false, textStatus, jqXHR );
230
231              },
232
233              'type': $.isArray( type ) ? type[0] : type,
234              'data': data
235
236            };
237
238          if( $.isArray( type ) && type[1] )
239              envelope['dataType'] = type[1];
240
241          if( extraOptions )
242              envelope = $.extend( envelope, extraOptions );
243
244          $.ajax( envelope );
245          return( result );
246    },
247   
248    /**
249    * This method is used to read resources from the server.
250    *
251    * @param uri Uri of the resource that gonna be readed.
252    * @param callback A function that is called when the resource is loaded successfully. When the parameter is ignored the request is made synchrounsly.
253    * @param accept The attribute accept that is used to ask the target format to the server
254    * @return The target resource when the callback is ommitted ( made it synchronous )
255    */
256
257    read: function( uri, data, callback, accept ){
258        //return this.send( this.dispatchPath + 'rest' + uri, [ 'get', accept || 'json' ], false, callback );
259        //http://expressodev.prognus.com.br/cristiano/expresso-api/rest/maillast
260        //return this.send( ('rest' + uri), [ 'get', accept || 'json' ], data, callback, !!!callback,
261console.log(this.dispatchPath+'../rest'+uri);
262        return this.send( (this.dispatchPath + '../rest' + uri), [ 'get', accept || 'json' ], data, callback, !!!callback,
263        {'beforeSend' : function (xhr){
264            xhr.setRequestHeader('Authorization', "OAUTH Bearer " + (DataLayer.me ? DataLayer.me.token : DataLayer.dispatch("../prototype/me").token))}
265        });
266     
267    },
268
269    /**
270    * This method is used to create resources from the server.
271    *
272    * @param uri Uri of the resource that gonna be readed.
273    * @param callback A function that is called when the resource is created on the server successfully. When the parameter is ignored the request is made synchrounsly.
274    * @param accept The attribute accept that is used to ask the target format to the server.
275    * @return The result response of the create from the server when the callback is ommitted ( made it synchronous )
276    */
277   
278    create: function( uri, data, callback, accept ){
279        //return this.send( 'rest' + uri, [ 'post', accept || 'json' ], data, callback, !!!callback,
280        return this.send( (this.dispatchPath + '../rest' + uri), [ 'post', accept || 'json' ], data, callback, !!!callback,
281        {'beforeSend' : function (xhr){
282                //xhr.setRequestHeader('Authorization', "OAUTH Bearer " + DataLayer.me.token)}
283                xhr.setRequestHeader('Authorization', "OAUTH Bearer " + (DataLayer.me ? DataLayer.me.token : DataLayer.dispatch("../prototype/me").token))}
284        });     
285    },
286
287    /**
288    * This method is used to update resources from the server.
289    *
290    * @param uri Uri of the resource that gonna be readed.
291    * @param callback A function that is called when the resource is update on the server successfully. When the parameter is ignored the request is made synchrounsly.
292    * @param accept The attribute accept that is used to ask the target format to the server
293    * @return The result response of the update from the server when the callback is ommitted ( made it synchronous )
294    */
295
296    update: function( uri, data, callback, accept ){
297     
298        //return this.send( 'rest' + uri, [ 'put', accept || 'json' ], data, callback, !!!callback,
299        return this.send( (this.dispatchPath + '../rest' + uri), [ 'put', accept || 'json' ], data, callback, !!!callback,
300        {'beforeSend' : function (xhr){
301            //xhr.setRequestHeader('Authorization', "OAUTH Bearer " + DataLayer.me.token)}
302                xhr.setRequestHeader('Authorization', "OAUTH Bearer " + (DataLayer.me ? DataLayer.me.token : DataLayer.dispatch("../prototype/me").token))}
303        });
304     
305    },
306
307    /**
308    * This method is used to delete resources from the server.
309    *
310    * @param uri Uri of the resource that gonna be readed.
311    * @param callback A function that is called when the resource is deleted successfully in the server. When the parameter is ignored the request is made synchrounsly.
312    * @param accept The attribute accept that is used to ask the target format to the server
313    * @return The result response of the delete from the server when the callback is ommitted ( made it synchronous )
314    */
315
316    delete: function( uri, callback, accept ){
317        //return this.send( 'rest' + uri, [ 'delete', accept || 'json' ], false, callback, !!!callback,
318        return this.send( (this.dispatchPath + '../rest' + uri), [ 'delete', accept || 'json' ], false, callback, !!!callback,
319        {'beforeSend' : function (xhr){
320            //xhr.setRequestHeader('Authorization', "OAUTH Bearer " + DataLayer.me.token)}
321                xhr.setRequestHeader('Authorization', "OAUTH Bearer " + (DataLayer.me ? DataLayer.me.token : DataLayer.dispatch("../prototype/me").token))}
322        });
323     
324    },
325   
326    dispatch: function( dispatcher, data, callback, isPost, dataType ){
327     
328      return this.send( this.dispatchPath + dispatcher + ".php",
329                        [ ( isPost ? 'post' : 'get' ), dataType || 'json' ],
330                        data,
331                        callback );
332
333//       $.ajax({
334//            'async': !!callback,
335//            'url': this.dispatchPath + dispatcher + ".php",
336//            'type': ( isPost ? 'post' : 'get' ),
337//            'dataType': 'json',
338//            'data': data,
339//            'success': function( dt, textStatus, jqXHR ){
340//
341//                  if( callback )
342//                  {
343//                      fired = true;
344//                      callback( dt, textStatus, jqXHR );
345//                  }
346//                  else
347//                      result = dt;
348//
349//              },
350//            'complete': function( jqXHR, textStatus ){
351//
352//                if( !fired && callback )
353//                    callback( false, textStatus, jqXHR );
354//
355//            }/*,
356//            'processData': false*/
357//        });
358
359      //return( result );
360    },
361
362    form: function( target, fileInputs ){
363
364        var params = {}, $this = $(target), inputArray = $this.serializeArray();
365
366        if( !$this.is( "form" ) )
367            $this = $this.parents( "form" );
368               
369        if( fileInputs )
370                fileInputs.each( function( i, el ){
371
372              inputArray[ inputArray.length ] = { name: $(this).prop("name"), value: FILE + i };
373
374                });
375
376        $.each( inputArray, function( i, el ){
377
378            if( newName = arrayName.exec( el.name ) )
379                el.name = newName[1];
380            else if( !params[ el.name ] )
381                return( params[ el.name ] = el.value );
382
383            params[ el.name ] = params[ el.name ] || [];
384
385            if( $.type(params[ el.name ]) !== "array" )
386                params[ el.name ] = [ params[ el.name ] ];
387
388            params[ el.name ].push( el.value );
389        });
390
391//      alert(dump(params));
392
393        return this.decode( $this.attr( "action" ), params );
394    },
395       
396        serializeForm: function( data, level ){
397       
398                var formData = [];
399       
400                for( key in data )
401                {
402                        var value = data[key];
403
404                        if( level !== undefined )
405                                key = level+'['+key+']';
406
407                        if( $.isArray(value) || $.isPlainObject(value) )
408                                formData = formData.concat( this.serializeForm( value, key ) );
409                        else
410                                formData[ formData.length ] = { name: key, value: value };
411                }
412               
413                return( formData );
414        },
415
416    blend: function( action, data ){
417
418//      if( notArray = (!$.isArray(data)) )
419//          data = [ data ];
420
421        var form = $('form[action="'+action+'"]');
422
423        form.get(0).reset();
424
425        var named = form.find( 'input[name]' );
426
427        for( var name in data )
428        {
429            named.filter( '[name="'+name+'"]' ).val( data[name] );
430        }
431    },
432
433    /**
434     * A função put é responsável pela inserção de dados no DataLayer.
435     *
436     * Use:
437     *
438     * DataLayer.put    (
439     *                   'folder' OR 'folder:tree',                                                             //aqui se passa o conceito a ser armazenado. Caso o :codec seja declarado, os dados passam pelo decode do mesmo antes de ser armazenado
440     *                   '123' OR [ 'AND', [ '=', 'name', 'dedeu' ], [ '=', 'icon', 'folder.png' ] ] OR false,  //aqui se passa um id ou filtro quando for nescessário setar especificamente quais são os conceitos que vão ser atualizados. Caso se passe false ou mesmo o suprima o DataLayer cria um novo elemento e retorna o novo ID.
441     *                    { 'node': [ '1', '2', '3' ] }                                                         //aqui se passa a estrutura de dados a serem armazenados. Caso venha um id na mesma, o conceito e armazenado e atualizado seguindo o mesmo.
442     *                  );
443     */
444   
445    put: function( concept, filter, data, oneSide ){
446     
447      ///////////////////////////// normalize ////////////////////////////////
448        if( arguments.length == 2 )
449        {
450            data = filter;
451            filter = false;
452        }
453        if( typeof data === "undefined" ||
454            $.type(data) === "boolean" )
455        {
456            oneSide = data;
457            data = filter;
458            filter = false;
459        }
460       
461        if( !concept || !data )
462            return( false );
463
464        var decoder = "", id = false, bothSides = (typeof oneSide === "undefined"), notArray, res;
465       
466        if( $.type(filter) === "string" )
467        {
468            id = filter;
469            filter = false;
470        }
471
472        if( id )
473            data.id = id;
474
475        if( notArray = ( $.type( data ) !== "array" ) )
476            data = [ data ];
477
478        if( res = internalUrl.exec( concept ) )
479        {
480            //TODO: verificar se a decodificaçao deve ser feita em cada item do array
481            data = this.decode( concept, data );
482            concept = res[1];
483            decoder = res[2];
484        }
485
486      ////////////////////////////////////////////////////////////////////////
487
488        if( bothSides || !oneSide )
489        {
490            var result = false, links = this.links( concept ), nestedLinks = this.links( concept, true ),
491            current = this.check( concept ) || {}, ids = [];
492
493            for( var i = 0; i < data.length; i++ )
494            {
495                var key = ids[ ids.length ] = data[i].id || this.generateId( concept ), updateSet = {};
496
497                ////////////////////////////// linkage /////////////////////////////////   
498                for( var link in links )
499                {
500                    if( data[i][link] )
501                    {
502                        var notArray2 = false;
503
504                        if( notArray2 = this.hasOne( concept, link ) )
505                            data[i][link] = [ data[i][link] ];
506
507                        var _this = this, dependency = this.isDependency( concept, link );
508
509                        $.each( data[i][link], function( ii, el ){
510
511                                var isRef = false;
512
513                                if( isRef = ($.type(el) === "string") )
514                                    el = { id: el };
515
516                                //removido pois o mesmo esta gerando inconsistencia em tudo
517//                              if( DataLayer.isConcept( links[link], nestedLinks[link] ) )
518                                if( !DataLayer.hasOne( links[link], nestedLinks[link] ) )
519                                {
520                                    el[ nestedLinks[link] ] = el[ nestedLinks[link] ] || [];
521                                    el[ nestedLinks[link] ].push( key );
522                                }
523                                else
524                                    el[ nestedLinks[link] ] = key;
525
526                                if( isRef && ( !current[ key ] || !current[ key ][ link ] ||
527                                               (notArray2 ? current[ key ][ link ] !== el.id : !$.inArray( el.id, current[ key ][ link ] )) ) )
528                                {
529                                    updateSet[ links[link] ] = updateSet[ links[link] ] || [];
530                                    updateSet[ links[link] ].push( el );
531                                }
532                                else if( !isRef )
533                                    data[i][link][ii] = _this.put( links[link], el, oneSide );
534                            });
535
536                        if( notArray2 )
537                            data[i][link] = data[i][link][0];
538                    }
539                }
540                //////////////////////////////////////////////////////////////////////////
541
542                if( data[i].id )
543                    data[i] = this.merge( current[ data[i].id ], data[i] );
544
545                 current[ key ] = data[i];
546
547                if( bothSides )
548                  this.report( concept, key, data[i] );
549            }
550
551            this.store( concept, current );
552
553            for( var setKey in updateSet )
554            {
555                if( bothSides )
556                    for( var i = 0; i < updateSet[ setKey ].length; i++ )
557                      this.report( setKey, updateSet[ setKey ][i].id, updateSet[ setKey ][i] );
558                   
559                DataLayer.put( setKey, updateSet[ setKey ], false );
560            }
561        }
562
563        if( oneSide )
564            this.commit( concept, ids/*, true */);
565
566        this.broadcast( concept, oneSide ? 'server' : bothSides ? 'serverclient' : 'client', true );
567
568        return( notArray ? ids[0] : ids );
569
570    },
571   
572     /**
573     * A função remove é responsável pela remoção de dados no DataLayer.
574     *
575     * Use:
576     *
577     * DataLayer.remove (
578     *                   'folder',       //aqui se passa o conceito a ser removido.
579     *                   '123' OR false, //aqui se passa um id quando for nescessário remover especificamente alguém. Caso se passe false ou mesmo o suprima o DataLayer remove o conceito inteiro.
580     *                  );
581     */
582   
583    remove: function( concept, id, oneSide ){
584       
585        if( arguments.length === 2 && typeof id === "boolean" )
586        {
587                oneSide = id;
588                id = false;
589        }
590
591        var bothSides = (typeof oneSide === "undefined"),
592
593        links = this.links( concept ), nestedLinks = this.links( concept, true ), ids = [],
594
595        current = this.check( concept, id );
596
597        if( !current ) return;
598       
599        if( typeof id === "string" )
600        {
601            current.id = id;
602            current = [ current ];
603        }
604
605        $.each( current, function(i, o)
606        {
607            var currentId = ids[ ids.length ] = current[i].id;
608
609            if( bothSides )
610              DataLayer.report( concept, currentId, false );
611
612            if( bothSides || !oneSide )
613              DataLayer.del( concept, currentId );
614
615            for( var link in links )
616            {
617                        if( !current[i][link] )
618                                continue;
619
620                        if( DataLayer.hasOne( concept, link ) )
621                                current[i][link] = [ current[i][link] ];
622
623                        $.each( current[i][link], function( ii, el ){
624
625                                el = DataLayer.storage.cache[links[link]][el];
626
627                                if( notArrayNested = ( $.type( el[ nestedLinks[link] ] ) !== "array" ) )
628                                        el[ nestedLinks[link] ] = [ el[nestedLinks[link]] ];
629
630                                el[ nestedLinks[link] ] = $.grep( el[ nestedLinks[link] ], function( nested, iii ){
631                                        return ( currentId !== nested );
632                                });
633
634                                if( notArrayNested )
635                                        el[ nestedLinks[link] ] = el[ nestedLinks[link] ][0] || false;
636                                if(!el[ nestedLinks[link] ] || !el[ nestedLinks[link] ].length)
637                                        delete el[ nestedLinks[link] ];
638                        });
639            }
640        });
641
642        if( oneSide )
643            this.commit( concept, ids );
644
645        this.broadcast( concept, oneSide ? 'server' : bothSides ? 'serverclient' : 'client', false );
646    },
647   
648    report: function( concept, id, data )
649    {     
650        var current = this.check( ':current', concept ) || {};
651
652        if( !current[ id ] )
653            current[ id ] = this.check( concept, id ) || {};
654       
655        this.store( ':current', concept, current );
656
657        var diff = this.diff( current[ id ], data );
658
659        var diffs = this.check( ':diff', concept ) || {};
660
661        if( diffs[ id ] )
662            diff = this.merge( diffs[ id ], diff );
663
664        if( !diff || !$.isEmptyObject( diff ) )
665            diffs[ id ] = diff;
666
667        this.store( ':diff', concept, diffs );
668    },
669
670//     enqueue: function( queueName, concept, id, data ){
671//
672//      var queue = this.check( ':' + queueName, concept ) || {};
673//
674//
675//     },
676//     
677//     dequeue: function( queueName, concept, id ){
678//
679//     
680//
681//     },
682   
683   
684   
685    rollback: function( concept, ids ){
686     
687        var queue = this.prepareQ( 'current', concept, ids );
688
689        ids = [];
690
691        for( var id in queue )
692        {
693             this.put( concept, id, queue[id], false );
694
695             ids[ ids.length ] = id;
696        }
697
698        this.clearQ( concept, ( ids.length ? ids : false ) );
699
700        this.broadcast( concept, 'revert' );
701     
702    },
703   
704    prepareQ: function( queueName, concept, ids ){
705     
706      var notArray = false;
707     
708      if( notArray = ($.type(concept) !== "array") )
709          concept = [ concept ];
710     
711      var q = {};
712     
713      for( var i = 0; i < concept.length; i++ )
714      {
715          var queue = this.check( ':' + queueName, concept[i] || false );
716         
717          if( !queue ) continue;
718
719          if( ids )
720          {
721              if( $.type(ids) !== "array" )
722                  ids = [ ids ];
723
724              var filtered = {};
725
726              for( var ii = 0; ii < ids.length; ii++ )
727              {
728                  filtered[ ids[ii] ] = queue[ ids[ii] ];
729              }
730
731              queue = filtered;
732          }
733
734          q[ concept[i] ] = queue;
735      }
736     
737      return( notArray ? q[ concept[0] ] : q );
738    },
739   
740    clearQ: function( concept, ids ){
741     
742        var current = this.check( ':current', concept || false );
743        var diffs = this.check( ':diff', concept || false );
744
745        if( !ids )
746            current = diffs = {};
747        else
748        {
749            if( notArray = ($.type(ids) !== "array") )
750              ids = [ ids ];
751
752            for( var i = 0; i < ids.length; i++ )
753            {
754                delete current[ ids[i] ];
755                delete diffs[ ids[i] ];
756            }
757        }
758
759        this.store( ':current', concept, current );
760        this.store( ':diff', concept, diffs );
761    },
762
763    commit: function( concept, ids, callback ){
764     
765        var queue = this.prepareQ( 'diff', concept, ids );
766
767        this.sync( queue, !$.isArray(concept) && concept || false, callback );
768    },
769   
770    sync: function( queue, concept, callback ){
771
772        if( !queue || $.isEmptyObject( queue ) )
773            return;
774
775        if( concept )
776        {
777          var helper = {};
778          helper[concept] = queue;
779          queue = helper;
780        }
781
782        var data = {}, URIs = {};
783
784        for( var concept in queue )
785            for( var id in queue[concept] )
786            {
787                data[ this.URI( concept, id ) ] = queue[concept][id];
788                URIs[ this.URI( concept, id ) ] = { concept: concept, id: id };
789            }
790
791        if( $.isEmptyObject( data ) )
792            return;
793
794        this.dispatch( "Sync", data, function( data, status, jqXHR ){
795
796//          switch( status )
797//          {
798//            case "error":
799//            case "parsererror":
800//              return DataLayer.rollback( concept, URI );
801//            case "success":
802//              return DataLayer.commit();
803//            case "timeout":
804//            case "notmodified":
805//          }
806
807            var received = DataLayer.receive( data );
808
809            for( var URI in URIs )
810                if( typeof received[URI] !== "undefined" )
811                    DataLayer.clearQ( URIs[URI].concept, URIs[URI].id );
812
813            if( callback )
814                callback( received );
815
816//          for( var URI in data )
817//          {
818//              var parsed = DataLayer.parseURI( URI ),
819//   
820//              concept = parsed[1], id = parsed[3];
821//
822//              if( $.type(data[URI]) === "string" )
823//              {
824//                //TODO:threat the exception thrown
825//                DataLayer.rollback( concept, id );
826//                delete URIs[ URI ];
827//                continue;
828//              }
829//
830//              if( data[URI] === false ){
831//                DataLayer.remove( concept, id, false );
832//                continue;
833//              }
834//
835//              if( id !== data[URI].id )
836//                DataLayer.move( concept, id, data[URI].id );
837//             
838//              DataLayer.put( concept, id, data[URI], false );
839//          }
840//         
841//          for( var URI in URIs )
842//               DataLayer.clearQ( URIs[URI].concept, URIs[URI].id );
843//         
844//          if( callback )
845//              callback();
846
847        }, true );
848
849    },
850   
851    receive: function( data ){
852     
853        var received = {};
854       
855            for( var URI in data )
856            {
857                var parsed = DataLayer.parseURI( URI ),
858   
859            concept = parsed[4], id = parsed[5];
860
861            received[ URI ] = data[ URI ];
862
863                if( $.type(data[URI]) === "string" )
864                {
865                  //TODO:threat the exception thrown
866                  DataLayer.rollback( concept, id );
867                  continue;
868                }
869
870                if( data[URI] === false ){
871                  DataLayer.remove( concept, id, false );
872                  continue;
873                }
874
875                if( id !== data[URI].id )
876                  DataLayer.move( concept, id, data[URI].id );
877               
878                DataLayer.put( concept,  data[URI].id || id, data[URI], false );
879            }
880           
881        return( received );
882           
883    },
884   
885    unique: function( origArr ){
886
887        var newArr = [];
888     
889        for ( var x = 0; x < origArr.length; x++ )
890        {
891                var found = false;
892            for ( var y = 0; !found && y < newArr.length; y++ )
893                if ( origArr[x] === newArr[y] ) 
894                  found = true;
895
896            if ( !found )
897                newArr[ newArr.length ] = origArr[x];
898        }
899
900        return newArr;
901    },
902
903    merge: function( current, data ){
904     
905        return this.copy(  data, current );
906
907//      return $.extend( current, data );
908
909    },
910   
911    // clone objects, skip other types.
912    clone: function(target) {
913            if ( typeof target == 'object' ) {
914                    Clone.prototype = target;
915                    return new Clone();
916            } else {
917                    return target;
918            }
919    },
920     
921    // Shallow Copy
922    shallowCopy: function(target) {
923            if (typeof target !== 'object' ) {
924                    return target;  // non-object have value sematics, so target is already a copy.
925            } else {
926                    var value = target.valueOf();
927                    if (target != value) {
928                            // the object is a standard object wrapper for a native type, say String.
929                            // we can make a copy by instantiating a new object around the value.
930                            return new target.constructor(value);
931                    } else {
932                            // ok, we have a normal object. If possible, we'll clone the original's prototype
933                            // (not the original) to get an empty object with the same prototype chain as
934                            // the original.  If just copy the instance properties.  Otherwise, we have to
935                            // copy the whole thing, property-by-property.
936                            if ( target instanceof target.constructor && target.constructor !== Object ) {
937                                    var c = clone(target.constructor.prototype);
938     
939                                    // give the copy all the instance properties of target.  It has the same
940                                    // prototype as target, so inherited properties are already there.
941                                    for ( var property in target) {
942                                            if (target.hasOwnProperty(property)) {
943                                                    c[property] = target[property];
944                                            }
945                                    }
946                            } else {
947                                    var c = {};
948                                    for ( var property in target ) c[property] = target[property];
949                            }
950                           
951                            return c;
952                    }
953            }
954    },
955
956    // entry point for deep copy.
957    // source is the object to be deep copied.
958    // depth is an optional recursion limit. Defaults to 256.
959    // deep copy handles the simple cases itself: non-objects and object's we've seen before.
960    // For complex cases, it first identifies an appropriate DeepCopier, then delegate the details of copying the object to him.
961    copy: function(source, result, depth) {
962     
963            // null is a special case: it's the only value of type 'object' without properties.
964            if ( source === null ) return null;
965
966            // All non-objects use value semantics and don't need explict copying.       
967                if ( typeof source !== 'object' ) return source;
968
969            if( !depth || !(depth instanceof RecursionHelper) ) depth = new RecursionHelper(depth);
970
971            var cachedResult = depth.getCachedResult(source);
972
973            // we've already seen this object during this deep copy operation
974            // so can immediately return the result.  This preserves the cyclic
975            // reference structure and protects us from infinite recursion.
976            if ( cachedResult ) return cachedResult;
977
978            // objects may need special handling depending on their class.  There is
979            // a class of handlers call "DeepCopiers"  that know how to copy certain
980            // objects.  There is also a final, generic deep copier that can handle any object.
981            for ( var i=0; i<this.comparators.length; i++ ) {
982
983                    var comparator = this.comparators[i];
984
985                    if ( comparator.can(source) ) {
986       
987                            // once we've identified which DeepCopier to use, we need to call it in a very
988                            // particular order: create, cache, populate.  This is the key to detecting cycles.
989                            // We also keep track of recursion depth when calling the potentially recursive
990                            // populate(): this is a fail-fast to prevent an infinite loop from consuming all
991                            // available memory and crashing or slowing down the browser.
992     
993                            if( !result )
994                                // Start by creating a stub object that represents the copy.
995                                result = comparator.create(source);
996                            else if( !comparator.can(result) )
997                                throw new Error("can't compare diferent kind of objects.");
998
999                            // we now know the deep copy of source should always be result, so if we encounter
1000                            // source again during this deep copy we can immediately use result instead of
1001                            // descending into it recursively. 
1002                            depth.cacheResult(source, result);
1003
1004                            // only DeepCopier.populate() can recursively deep copy.  So, to keep track
1005                            // of recursion depth, we increment this shared counter before calling it,
1006                            // and decrement it afterwards.
1007                            depth.depth++;
1008                            if ( depth.depth > depth.maxDepth ) {
1009                                    throw new Error("Exceeded max recursion depth in deep copy.");
1010                            }
1011
1012                            // It's now safe to let the comparator recursively deep copy its properties.
1013                            var returned = comparator.populate( function(source, result) { return DataLayer.copy(source, result, depth); }, source, result );
1014       
1015                                if(returned)
1016                                        result = returned;
1017
1018                            depth.depth--;
1019
1020                            return result;
1021                    }
1022            }
1023            // the generic copier can handle anything, so we should never reach this line.
1024            throw new Error("no DeepCopier is able to copy " + source);
1025    },
1026
1027    // publicly expose the list of deepCopiers.
1028    comparators: [],
1029
1030    // make deep copy() extensible by allowing others to
1031    // register their own custom Comparators.
1032    registerComparator: function(comparatorOptions) {
1033
1034          // publicly expose the Comparator class.
1035          var comparator = {
1036
1037              // determines if this Comparator can handle the given object.
1038              can: function(source) { return false; },
1039   
1040              // starts the deep copying process by creating the copy object.  You
1041              // can initialize any properties you want, but you can't call recursively
1042              // into the copy().
1043              create: function(source) { },
1044
1045              // Completes the deep copy of the source object by populating any properties
1046              // that need to be recursively deep copied.  You can do this by using the
1047              // provided deepCopyAlgorithm instance's copy() method.  This will handle
1048              // cyclic references for objects already deepCopied, including the source object
1049              // itself.  The "result" passed in is the object returned from create().
1050              populate: function(deepCopyAlgorithm, source, result) {}
1051          };
1052
1053          for ( var key in comparatorOptions ) comparator[key] = comparatorOptions[key];
1054
1055          this.comparators.unshift( comparator );
1056    },
1057   
1058    escapedJSON: function(text)
1059    {
1060          return JSON.stringify( text ).replace( /[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&" );
1061    },
1062 
1063    diff: function( base, toDiff ){
1064
1065        if( typeof base === 'undefined' || $.isEmptyObject(base) )
1066            return( toDiff );
1067
1068        if( toDiff === false )
1069            return( false );
1070
1071        toDiff = $.extend( {}, toDiff );
1072
1073        for( var key in toDiff )
1074        {
1075            switch( $.type(toDiff[key]) )
1076            {
1077              case 'object':
1078                if( $.isEmptyObject(toDiff[key] = this.diff( base[key], toDiff[key] )) )
1079                  delete toDiff[key];
1080              break;
1081              case 'array':
1082                if( base[key] && !(toDiff[key] = $.grep( toDiff[key], function( el, i ){ return( $.isArray( el ) || $.isPlainObject( el ) ? !RegExp( DataLayer.escapedJSON( el ) ).test( JSON.stringify(base[key]) ) : $.inArray( el, base[key] ) === -1 ); } )).length )
1083                  delete toDiff[key];
1084              break;
1085              default:
1086                if( base[key] == toDiff[key] )
1087                  delete toDiff[key];
1088            }
1089        }
1090
1091        return( toDiff );
1092
1093    },
1094   
1095    links: function( concept, reverse ){
1096
1097        if( !this.links[ concept ] )
1098        {
1099            var result = this.dispatch( "links", { concept: concept } ) || false;
1100
1101            if( !result )
1102                return( false );
1103
1104            this.concepts[ concept ] = $.extend( this.concepts[ concept ] || {},
1105                                                 result['concepts'] || {} );
1106
1107            this.links[ concept ] =  result['links'] || {};
1108           
1109            this.notArray[ concept ] = result['hasOne'] || {};
1110
1111           this.nestedLinks[ concept ] = result['nestedLinks'] || {};
1112        }
1113
1114        if( reverse )
1115        {
1116            return( this.nestedLinks[ concept ] );
1117        }
1118
1119        return( this.links[ concept ] );
1120
1121    },
1122   
1123    isDependency: function( concept, attr ){
1124     
1125        if( typeof this.concepts[concept] === "undefined" )
1126        {
1127            this.links( concept );
1128        }
1129
1130        return !!this.concepts[ concept ][ attr ];
1131    },
1132   
1133    hasOne: function( concept, attr ){
1134     
1135        if( typeof this.notArray[concept] === "undefined" )
1136        {
1137            this.links( concept );
1138        }
1139
1140        return !!this.notArray[ concept ][ attr ];
1141    },
1142   
1143    URI: function( concept, URI, context ){
1144     
1145        if( res = internalUrl.exec( concept ) )
1146            concept = res[1];
1147       
1148        context = context ? "(" + context + ")" : "";
1149     
1150        if( URI )
1151            return( concept + context + "://" + URI );
1152        else
1153            return( concept );
1154     
1155    },
1156   
1157    parseURI: function( URI ){
1158
1159        return internalUri.exec( URI ) || false;
1160
1161    },
1162   
1163   
1164   
1165   
1166    generateId: function( concept ){
1167     
1168        var newId = this.counter + "(javascript)";
1169     
1170        this.store( ":counter", (this.counter++) + "" );
1171       
1172        return( newId );
1173    },
1174   
1175
1176   
1177
1178    get: function( concept, /*URI, */filter, oneSide ){
1179
1180        ///////////////////////////// normalize ////////////////////////////////
1181        if( arguments.length == 2 && $.type(filter) === "boolean" )
1182        {
1183            oneSide = filter;
1184            filter = false;
1185        }
1186       
1187        var encoder = false, id = false, bothSides = (typeof oneSide === 'undefined'), res;
1188       
1189        if( $.type(filter) === "string" )
1190        {
1191            id = filter;
1192            filter = false;
1193        }
1194
1195        filter = filter || false;
1196
1197        if( !concept )
1198            return( false );
1199
1200        if( res = internalUrl.exec( concept ) )
1201        {
1202            encoder = concept;
1203            concept = res[1];
1204
1205            if( filter )
1206                filter = this.criteria( encoder, filter );
1207        }
1208       
1209        if ( $.type(filter) === "array" )
1210        {
1211            filter = { filter: filter, criteria: false };
1212        }
1213       
1214        //////////////////////////////////////////////////////////////////////////
1215       
1216        var result = false;
1217       
1218        if( bothSides || !oneSide )
1219            result = this.check( concept, id || filter );
1220       
1221        if (bothSides && filter.filter)
1222                result = false;
1223
1224               
1225        if( !result && (bothSides || oneSide) )
1226        {
1227            result = this.request( concept, id || filter.filter, filter.criteria );
1228
1229            if( result && bothSides && (!filter ||
1230                                        !filter.criteria ||
1231                                        !filter.criteria.format) )
1232            {
1233              var newResult = [];
1234           
1235              $.each( result, function( i, res ){
1236                        newResult[ i ] = $.extend( {}, res );
1237                  });
1238
1239              this.put( concept, id, newResult, false );
1240            }
1241        }
1242
1243        if( /*result &&*/ encoder )
1244            result = this.encode( encoder, result, filter ); //TODO: retirar o filtro no método encode
1245
1246        return( result );
1247    },
1248   
1249    filter: function( base, filter, criteria ){
1250     
1251        if( !$.isArray( filter || [] ) )
1252            filter = filter.filter || false;
1253
1254        if( !filter )
1255            return( base );
1256
1257        var filtered = [];
1258     
1259        for( var key in base )
1260            if( this.storage.filter( base[key], filter ) )
1261                filtered[ filtered.length ] = key;
1262
1263        return( filtered );
1264    },
1265
1266        converterType: function( filter ){
1267
1268                        return isNaN(parseInt(filter)) ? filter : parseInt(filter);
1269               
1270        },
1271
1272   
1273    compare: function( operator, base, test ){
1274     
1275        base = this.converterType(base);
1276        test = this.converterType(test);
1277         
1278    switch( operator ){
1279       
1280        case '*':  return RegExp( ".*" + test + ".*" ).test( base );
1281        case '^':  return RegExp( "^" + test +  ".*" ).test( base );
1282        case '$':  return RegExp( ".*"  + test + "$" ).test( base );
1283
1284        case '&':  return ( base && test );
1285        case '|':  return ( base || test );
1286
1287        case '=':  return ( base == test );
1288        case '<=': return ( base <= test );
1289        case '>=': return ( base >= test );
1290        case '>':  return ( base <  test );
1291        case '<':  return ( base >  test );
1292       
1293        default: return true;
1294        }
1295     
1296    },
1297   
1298//     clone: function( object ){
1299//
1300//      new { prototype: object };
1301//
1302//     },
1303
1304    check: function( namespace, filter ){
1305
1306        if( !namespace )
1307            return( false );
1308
1309        var result = this.storage.get( namespace );
1310
1311        if( !filter || !result )
1312          return( result || false );
1313
1314        var keys = DataLayer.copy( filter );
1315
1316        if( notArray = $.type(keys) === "string" )
1317            keys = [ keys ];
1318        else if( $.type(keys) !== "array" )
1319                keys = this.filter( result, keys.filter, keys.criteria );
1320
1321        var res = [];
1322
1323        for( var i = 0; i < keys.length; i++ )
1324            res[ res.length ] = result[keys[i]];
1325
1326        return( notArray ? res[0] || false : res.length ? res : false );
1327    },
1328
1329    storage: {
1330     
1331        cache: {},
1332     
1333        set: function( key, value ){
1334
1335            this.cache[key] = value;
1336
1337        },
1338        get: function( key ){
1339
1340            return DataLayer.copy( this.cache[key] );
1341
1342        },
1343        del: function( key ){
1344
1345            delete this.cache[key];
1346
1347        },
1348       
1349        filter: function( base, filter ){
1350     
1351            var bool, op = filter.shift();
1352
1353            switch( op )
1354            {
1355                case 'IN':
1356                  for( var i = 0, f = []; i < filter[1].length || !(filter = f); i++ )
1357                      f[i] = [ '=', filter[0], filter[1][i] ];
1358                case 'OR':
1359                    op = '|';
1360                    bool = false;
1361                break;
1362                case 'AND':
1363                    op = '&';
1364                    bool = true;
1365                break;
1366                default : return DataLayer.compare( op, base[ filter[0] ], filter[1] );
1367            }
1368           
1369            for( var strict = bool;
1370
1371                filter.length && ( strict ? bool : !bool );
1372           
1373                bool = DataLayer.compare( op, bool, this.filter( base, filter.shift() ) ) );
1374
1375            return( bool );
1376        }
1377    },
1378
1379    flush: function(){
1380
1381    },
1382   
1383    restore: function(){
1384     
1385    },
1386
1387    store: function( namespace, key, data ){
1388
1389        if( !data )
1390          return this.storage.set( namespace, key );
1391
1392        var res = this.check( namespace ) || {};
1393
1394        res[key] = data;
1395
1396        return this.storage.set( namespace, res );
1397    },
1398
1399    del: function( namespace, key ){
1400     
1401        if( !key )
1402          return this.storage.del( namespace );
1403
1404        var res = this.check( namespace ) || {};
1405
1406        delete res[key];
1407       
1408        if( !$.isEmptyObject( res ) )
1409            return this.storage.set( namespace, res );
1410
1411        this.storage.del( namespace );
1412     
1413    },
1414   
1415     move: function( concept, oldId, newId ){
1416
1417        this.put( concept, newId, this.check( concept, oldId ), false );
1418
1419        this.remove( concept, oldId, false );
1420    },
1421   
1422
1423   
1424   
1425   
1426    request: function( concept, filter, criteria ){
1427
1428      var id = false, criteria = criteria || {};
1429
1430      if( $.type(filter) === "string" )
1431      {
1432          id = filter;
1433          filter = false;
1434      }
1435
1436      return this.dispatch( "request", {
1437
1438          concept: concept || '',
1439          id: id || '',
1440          filter: filter || '',
1441          criteria: criteria || '',
1442          service: criteria.service || '',
1443          properties: criteria.properties || ''
1444
1445      } );
1446    },
1447
1448   
1449    //         sync: function( data, callback ){
1450//
1451//      if( !data || $.isEmptyObject( data ) )
1452//          return;
1453//       
1454//      this.send( "Sync", data, function( data, status, jqXHR ){
1455//
1456// //       switch( status )
1457// //       {
1458// //         case "error":
1459// //         case "parsererror":
1460// //           return DataLayer.rollback( concept, URI );
1461// //         case "success":
1462// //           return DataLayer.commit();
1463// //         case "timeout":
1464// //         case "notmodified":
1465// //       }
1466//
1467//          if( callback )
1468//          {
1469//              var result = callback( data, status, jqXHR );
1470//
1471//              if( result === false )
1472//                  return;
1473//              else if( typeof result != "undefined" )
1474//                  data = result;
1475//          }
1476//
1477//          for( var URI in data )
1478//          {
1479//              var parsed = DataLayer.parseURI( URI ),
1480//   
1481//              concept = parsed[1], /*URI = parsed[3],*/
1482//
1483//              links = DataLayer.links( concept );
1484//
1485//              for( var linkName in links )
1486//              {
1487//                  var subURI = data[URI][linkName];
1488//
1489//                  if( subURI && data[subURI] )
1490//                  {
1491//                      data[URI][linkName] = DataLayer.put( linkName, subURI, data[subURI], false );
1492//
1493//                      delete( data[subURI] );
1494//                  }
1495//              }
1496//
1497//              DataLayer.put( concept, URI, data[URI], false );
1498//          }
1499//      }, true );
1500//
1501//     },
1502
1503//     report: function( concept, URI, data, sync )
1504//     {
1505//      var current = this.dequeue( 'current', concept, URI );
1506//
1507//      if( !current )
1508//          this.enqueue( 'current', concept, URI, ( current = this.check( concept, URI ) || {} ) );
1509//
1510//      var diff = this.diff( current, data );
1511//
1512//      if( !diff )
1513//          this.dequeue( 'current', concept, URI, true );
1514//      else
1515//          this.enqueue( 'diff', concept, URI, diff );
1516//     
1517//      if( sync )
1518//          this.commit( concept, URI, function(){
1519//
1520//              DataLayer.set( concept, URI, data, false );
1521//
1522//          });
1523//     },
1524   
1525//     enqueue: function( type, concept, URI, obj ){
1526//       
1527//      //var newURI = this.URI( concept, URI );
1528//     
1529//      if( !this.queue[type] )
1530//          this.queue[type] = {};
1531//
1532//      if( !this.queue['all'] )
1533//          this.queue['all'] = {};
1534//     
1535//      if( !this.queue[type][concept] )
1536//          this.queue[type][concept] = {};
1537//     
1538//      if( !this.queue['all'][type] )
1539//          this.queue['all'][type] = {};
1540//     
1541//      if( !this.queue['all'][type][/*new*/URI] )
1542//          this.queue[type][concept][URI] = this.queue['all'][type][/*new*/URI] = obj;
1543//
1544//      this.store( ':queue', this.queue );
1545//     },
1546//     
1547//     dequeue: function( type, concept, URI, remove ){
1548//       
1549//       ///////////////////////////// normalize ////////////////////////////////
1550//      if( arguments.length < 4 && $.type(URI) === 'boolean' )
1551//      {
1552//          remove = URI;
1553//          URI = false;
1554//      }
1555//      if( arguments.length < 3 && $.type(concept) === 'boolean' )
1556//      {
1557//          remove = concept;
1558//          concept = false;
1559//      }
1560//       //////////////////////////////////////////////////////////////////////////
1561//       
1562//      if( !this.queue[type] || !this.queue['all'] )
1563//          return( false );
1564//     
1565//      if( !concept )
1566//      {
1567//          var obj = this.queue['all'][type];
1568//         
1569//          if( remove )
1570//          {
1571//              delete this.queue['all'][type];
1572//              delete this.queue[type];
1573//          }
1574//
1575//          this.store( ':queue', this.queue );
1576//          return( obj );
1577//      }
1578//
1579//      if( !this.queue[type][concept] )
1580//          return( false );
1581//     
1582//      if( !URI )
1583//      {
1584//          var obj = this.queue[type][concept];
1585//
1586//          if( remove )
1587//          {
1588//              var URIs = this.queue[type][concept];
1589//
1590//              for( var subURI in URIs )
1591//                   delete this.queue['all'][type][subURI];
1592//
1593//              delete this.queue[type][concept];
1594//          }
1595//
1596//          this.store( ':queue', this.queue );
1597//          return( obj );
1598//      }
1599//
1600// //   var newURI = URI ? this.URI( concept, URI ) : concept;
1601//     
1602//      var obj = this.queue['all'][type][/*new*/URI];
1603//   
1604//      if( remove )
1605//      {
1606//          delete this.queue['all'][type][/*new*/URI];
1607//          delete this.queue[type][concept][URI];
1608//      }
1609//
1610//      this.store( ':queue', this.queue );
1611//      return( obj );
1612//     },
1613   
1614           //TODO: definir a 'usage' desta função e refatora-la
1615//     set: function( concept, filter, data, oneSide ){
1616//
1617//      ///////////////////////////// normalize ////////////////////////////////
1618//      if( arguments.length == 2 )
1619//      {
1620//          data = filter;
1621//          filter = false;
1622//      }
1623//      if( $.type(data) === "boolean" )
1624//      {
1625//          oneSide = data;
1626//          data = filter;
1627//          filter = false;
1628//      }
1629//     
1630//      if( !concept || !data )
1631//          return( false );
1632//
1633//      var decoder = "", URI = false, bothSides = (typeof oneSide === "undefined");
1634//     
1635//      if( $.type(filter) === "string" )
1636//      {
1637//          URI = filter;
1638//          filter = false;
1639//      }
1640//
1641//      if( res = internalUrl.exec( concept ) )
1642//      {
1643//          //TODO: verificar se a decodificaçao deve ser feita em cada item do array
1644//          data = this.decode( concept, data );
1645//          concept = res[1];
1646//          decoder = res[2];
1647//      }
1648//      ///////////////////////////////////////////////////////////////////////////
1649//
1650//      if( bothSides || oneSide )
1651//          this.report( concept, URI, data, !bothSides );
1652//
1653//      if( bothSides || !oneSide )
1654//      {
1655//          if( URI )
1656//          {
1657//            var helper = {};
1658//            helper[URI] = data;
1659//            data = helper;
1660//          }
1661//
1662//          for( var URI in data )
1663//          {
1664//              var current = this.check( concept, URI ) || {};
1665//
1666//              data[URI] = this.merge( current, data[URI] );
1667//
1668//              this.store( concept, URI, data[URI] );
1669//          }
1670//
1671//      }
1672//
1673//      this.broadcast( concept, oneSide ? 'client' : 'server' );
1674//
1675//      return( true );
1676//     },
1677//     put: function( concept, URI, data, oneSide ){
1678//       
1679//       ///////////////////////////// normalize ////////////////////////////////
1680//      if( $.type(URI) !== "string" && arguments.length < 4 )
1681//      {
1682//          oneSide = data;
1683//          data = URI;
1684//          URI = false;
1685//      }
1686//       ////////////////////////////////////////////////////////////////////////
1687//       
1688//       ////////////////////////////// linkage /////////////////////////////////
1689//      var result = false, links = this.links( concept );
1690//
1691//      for( var link in links )
1692//      {
1693//          if( data[link] )
1694//          {
1695//              if( $.isArray( data[link] ) )
1696//              {
1697//                  data[link] = this.put( links[link], data[link].URI, data[link], oneSide );
1698//              }
1699//              else if( $.isObject( data[link] ) )
1700//              {
1701//                  $.each( data[link], function( i, el ){
1702//
1703//                        data[link][i] = this.put( links[link], el.URI, el, oneSide );
1704//
1705//                  });
1706//              }
1707//          }
1708//      }
1709//       //////////////////////////////////////////////////////////////////////////
1710//     
1711//      if( typeof data.URI === "undefined" )
1712//      {
1713//          URI = this.add( concept, data, oneSide );
1714//      }
1715//      else if( data.URI === false )
1716//      {
1717//          status = this.remove( concept, URI, oneSide );
1718//      }
1719//      else
1720//      {
1721//          status = this.set( concept, URI, data, oneSide );
1722//      }
1723//
1724//      if( URI && data.URI && URI !== data.URI )
1725//          this.move( concept, URI, data.URI );
1726//
1727//      return( data.URI || URI );
1728//
1729//     },
1730   
1731    //     add: function( concept, data, oneSide ){
1732//       
1733//       ///////////////////////////// normalize ////////////////////////////////
1734//      if( !concept || !data )
1735//          return( false );
1736//
1737//      if( res = internalUrl.exec( concept ) )
1738//      {
1739//          //TODO: verificar se a decodificaᅵᅵo deve ser feita em cada item do array
1740//          data = this.decode( concept, data );
1741//          concept = res[1];
1742//          decoder = res[2];
1743//      }
1744//
1745//      var bothSides = (typeof oneSide === "undefined"), uris = [];
1746//
1747//      if( notArray = $.type(data) !== "array" )
1748//          data = [ data ];
1749//       //////////////////////////////////////////////////////////////////////////
1750//
1751//      for( var i = 0; i < data.length; i++ )
1752//      {
1753//          var URI = uris[i] = this.generateURI( concept );
1754//
1755//          this.set( concept, URI, data[i], oneSide );
1756//      }
1757//
1758//      return( notArray ? uris[0] : uris );
1759//     },
1760//      put: function( concept, data ){
1761//
1762//      var decoder = "";
1763//
1764//      if( res = internalUrl.exec( concept ) )
1765//      {
1766//          data = this.decode( concept, data );
1767//          concept = res[1];
1768//          decoder = res[2];
1769//      }
1770//
1771//      var New = [], Update = [], uris = [];
1772//
1773//      if( notArray = $.type(data) !== "array" )
1774//          data = [ data ];
1775//     
1776//      for( var i = 0; i < data.length; i++ )
1777//      {
1778//          if( !data[i].URI )
1779//          {
1780//              uris[ uris.length ] = data[i].URI = this.create( concept, data[i] );
1781//              New[ New.length ] = data[i];
1782//              continue;
1783//          }
1784//
1785//          for( var key in data[i] )
1786//              if( klass = this.isReference( concept, key, data[i][key] ) )
1787//                    data[i][key] = this.put( klass + decoder, data[i][key] );
1788//
1789//          Update[ Update.length ] = this.update( concept, data[i].URI, data[i] );
1790//      }
1791//
1792//      this.report( concept, { "created": New, "updated": Update });
1793//
1794//      return( notArray ? uris[0] : uris );
1795//     },
1796//     merge: function( concept, current, data ){
1797//
1798//      current = current || {};
1799//
1800//      for( var key in data )
1801//          current[key] = (klass = this.isReference( concept, key, data[key] )) ?
1802//                         this.merge( klass, current[key], data[key] ) : data[key];
1803//
1804//      return( current );
1805//     },
1806//
1807//     isReference: function( concept, key, value ){
1808//
1809//       return( ($.type(value) === "object" ||
1810//             $.type(value) === "array" )? this.links[concept][key] : false );
1811//
1812//     },
1813//     
1814//     set: function( concept, data, URI, mergeable ){
1815//     
1816//      if( URI )
1817//      {
1818//          var res = this.get( concept, true ) || {};
1819//         
1820//          if( mergeable )
1821//              data = this.merge( res[URI] || {}, data );
1822//
1823//          res[URI] = data;
1824//
1825//          data = res;
1826//      }
1827//
1828//      return this.store( concept, data );
1829//     },   
1830//
1831//     create: function( concept, data ){
1832//
1833//       if( notArray = ($.type(data) !== "array") )
1834//          data = [ data ];
1835//
1836//       var uris = [];
1837//
1838//       for( var i = 0; i < data.length; i++ )
1839//       {
1840//        uris[ uris.length ] = data[i].URI = "javascript://" + (this.counter + i);
1841//
1842//        this.set( concept, data[i], data[i].URI );
1843//       }
1844// 
1845//       this.set( ":counter", (this.counter += data.length) );
1846//
1847//       return notArray ? uris[0] : uris;
1848//     },
1849//
1850//     update: function( concept, URI, data )
1851//     {
1852//      var target = this.check( concept, URI ) || {};
1853//
1854//      target = this.merge( concept, target, data );
1855//
1856//      if( target.URI !== URI )
1857//          this.remove( concept, URI );
1858//
1859//      this.set( concept, target, target.URI );
1860//
1861//      return( target );
1862//     },
1863//
1864//     remove: function( concept, URI ){
1865//
1866//      if( !URI )
1867//          return this.storage.del( concept );
1868//
1869//      var res = this.check( concept );
1870//
1871//      delete res[URI];
1872//     
1873//      this.set( concept, res );
1874//     },
1875//
1876//     del: function( concept, URI ){
1877//
1878//      this.remove( concept, URI );
1879//
1880//      this.report( concept, { "deleted": { 'URI': URI } });
1881//     },
1882//
1883//     report: function( concept, changes ){
1884//
1885//       this.broadcast( concept, changes.created, changes.updated, changes.deleted );
1886//
1887//      if( changes.created )
1888//          this.sync( concept, changes.created, 'create' );
1889//      if( changes.updated )
1890//          this.sync( concept, changes.updated, 'update' );
1891//      if( changes.deleted )
1892//          this.sync( concept, changes.deleted, 'delete' );
1893//
1894//     },
1895//
1896//
1897//    sync: function( concept, data, type ){
1898//
1899//      if( $.type(data) !== "array" )
1900//          data = [ data ];
1901//
1902//      $.each( data, function( i, el ){
1903//
1904//         DataLayer.send( concept, el, type );
1905//
1906//      });
1907//
1908//     },
1909//     
1910//     
1911//     
1912//     
1913//
1914//     request: function( concept, URI, filter ){
1915//
1916// //       if( startsDoubleDot.test(concept) )
1917// //     return( false );
1918//
1919//       filter = filter || {};
1920//
1921//       if( URI )
1922//      filter.URI = URI;
1923//
1924//       return this.send( concept, filter, "read", true );
1925//
1926//     },
1927//
1928//     send: function( concept, data, type, wait ){
1929//
1930//       switch( type )
1931//       {
1932//      case "create": type = "POST"; break;
1933//      case "update": type = "PUT"; break;
1934//      case "delete": type = "DELETE"; break;
1935//      case "read": type = "GET"; break;
1936//       }
1937//
1938//       var url = this.basePath + concept;
1939//
1940//       var result = [], notArray = false;
1941//
1942// //      alert( data.URI );
1943//
1944//       if( data.URI && data.URI.indexOf("javascript://") !== 0 )
1945//        url += "/" + data.URI;
1946//
1947//       var callback = function( dt, textStatus, jqXHR ){
1948//
1949//          if( notArray = (!$.isArray( dt )) )
1950//              dt = [ dt ];
1951//
1952//          $.each( dt, function( i, el ){
1953//
1954//              if( !el || !el.URI )
1955//                  return;
1956//
1957//              if( data.URI )
1958//                  el = DataLayer.update( concept, data.URI, el );
1959//              else
1960//                  DataLayer.set( concept, el, el.URI );
1961//
1962//              result[ result.length ] = el;
1963//              DataLayer.broadcast( concept );
1964//        });
1965//       };
1966//
1967//       $.ajax({
1968//            'async': ( !wait ),
1969//            'url': url,
1970//            'type': type,
1971//            'success': callback,
1972//            'dataType': 'json',
1973//            'data': data/*,
1974//            'processData': false*/
1975//        });
1976//
1977//       return( notArray ? result[0] || false : result );
1978//     },
1979   
1980   
1981    generateURI: function( concept ){
1982     
1983        return this.URI( concept, this.generateId( concept ), "javascript" );
1984
1985    },
1986   
1987
1988    broadcast: function( concept, status, diff ){
1989
1990        if( this.listeners[ concept ] )
1991            for( var i = 0;
1992                i < this.listeners[ concept ].length;
1993                this.listeners[ concept ][ i++ ]( status, diff ) );
1994    },
1995
1996    listen: function( concept, listener ){
1997
1998        this.register( "listeners", concept, listener );
1999
2000    },
2001
2002    codec: function( concept, namespace, codec ){
2003
2004        if( codec.encoder )
2005            this.encoder( concept, namespace, codec.encoder );
2006        if( codec.decoder )
2007            this.decoder( concept, namespace, codec.decoder );
2008        if( codec.criteria )
2009            this.register( "criterias", concept + ":" + namespace, codec.criteria );
2010
2011    },
2012
2013    encoder: function( concept, namespace, encoder ){
2014
2015        this.register( "encoders", concept + ":" + namespace, encoder );
2016
2017    },
2018
2019    encode: function( encoder, data, filter ){
2020
2021        if( this.encoders[ encoder ] )
2022            for( var i = 0;
2023                i < this.encoders[ encoder ].length;
2024                data = this.encoders[ encoder ][ i++ ]( data, filter ) );
2025
2026        return( data );
2027    },
2028
2029    decoder: function( concept, namespace, decoder ){
2030
2031        this.register( "decoders", concept + ":" + namespace, decoder );
2032
2033    },
2034
2035    decode: function( decoder, data ){
2036
2037        if( this.decoders[ decoder ] )
2038            for( var i = 0;
2039                i < this.decoders[ decoder ].length;
2040                data = this.decoders[ decoder ][ i++ ]( data ) );
2041
2042        return( data );
2043    },
2044
2045    criteria: function( codec, filter ){
2046
2047        if( this.criterias[ codec ] )
2048            for( var i = 0;
2049                i < this.criterias[ codec ].length;
2050                filter = this.criterias[ codec ][ i++ ]( filter ) );
2051
2052        return( filter );
2053
2054    },
2055
2056    register: function( kind, concept, deployable ){
2057
2058      if( arguments.length < 3 )
2059      {
2060          deployable = concept;
2061          concept = kind;
2062          kind = 'global';
2063      }
2064
2065      if( !this[ kind ][ concept ] )
2066            this[ kind ][ concept ] = [];
2067
2068        this[ kind ][ concept ][ this[ kind ][ concept ].length ] = deployable;
2069
2070    },
2071   
2072    start: function(){
2073
2074        var timer = function(){
2075
2076              setTimeout( timer, 1000 );
2077
2078              var now = parseInt( $.now() / 1000 );
2079
2080              var tasks = DataLayer.tasks[ now ];
2081
2082              if( !tasks ) return;
2083
2084              for( var i = 0; i < tasks.length; i++ )
2085              {
2086                  var result = tasks[i].task( now );
2087
2088                  if( tasks[i].factor )
2089                  DataLayer.schedule( tasks[i].task, tasks[i].factor );
2090              }
2091     
2092              delete DataLayer.tasks[ now ];
2093        };
2094
2095        setTimeout( timer, 1000 );
2096    },
2097   
2098    task: function( timestamp, task, factor )
2099    {
2100        if( !this.tasks[ timestamp ] )
2101            this.tasks[ timestamp ] = [];
2102
2103        this.tasks[ timestamp ][ this.tasks[ timestamp ].length ] = { task: task, factor: factor || false };
2104    },
2105
2106    schedule: function( task, time ){
2107
2108        time = time || 1;
2109       
2110        var index = parseInt( $.now() / 1000 ) + time;
2111
2112        this.task( index, task, time );
2113    },
2114   
2115    poll: function( concept, time ){
2116     
2117      this.schedule( function( now ){
2118 
2119          DataLayer.commit( concept );
2120
2121        }, time || 5 );
2122    },
2123   
2124    init: function(){
2125     
2126        this.counter = parseInt( this.get( ":counter", false ) ) || 0;
2127
2128        if( !this.dispatchPath )
2129            this.dispatchPath = "prototype/";
2130
2131        if( !this.templatePath )
2132            this.templatePath = "";
2133
2134        if( !this.basePath )
2135            this.basePath = this.dispatchPath + "REST.php?q=";
2136
2137        this.schedule( function( now ){
2138
2139            DataLayer.flush();
2140
2141        });
2142
2143        this.start();
2144        this.me = this.dispatch( "me" );
2145    }
2146}
2147
2148// the re-usable constructor function used by clone().
2149function Clone() {}
2150
2151//Recursion Helper
2152function RecursionHelper(){ this.clear(); };
2153
2154RecursionHelper.prototype = {
2155 
2156        constructor: RecursionHelper,
2157
2158        // copiedObjects keeps track of objects already copied by this
2159        // deepCopy operation, so we can correctly handle cyclic references.
2160        copiedObjects: [],
2161
2162        depth: 0,
2163
2164        maxDepth: 256,
2165
2166        //reset the recursion helper cache
2167        clear: function(){
2168                this.copiedObjects = [];
2169                this.depth = 0;
2170        },
2171
2172        // add an object to the cache.  No attempt is made to filter duplicates;
2173        // we always check getCachedResult() before calling it.
2174        cacheResult: function(source, result) {
2175                this.copiedObjects.push([source, result]);
2176        },
2177
2178        // Returns the cached copy of a given object, or undefined if it's an
2179        // object we haven't seen before.
2180        getCachedResult: function(source) {
2181
2182                for ( var i=0; i<this.copiedObjects.length; i++ ) {
2183                        if ( this.copiedObjects[i][0] === source ) {
2184                                return this.copiedObjects[i][1];
2185                        }
2186                }
2187
2188                return undefined;
2189        }
2190};
2191
2192// Generic Object copier
2193// the ultimate fallback DeepCopier, which tries to handle the generic case.  This
2194// should work for base Objects and many user-defined classes.
2195DataLayer.registerComparator({
2196        can: function(source) { return true; },
2197
2198        create: function(source) {
2199                if ( source instanceof source.constructor ) {
2200                        return DataLayer.clone(source.constructor.prototype);
2201                } else {
2202                        return {};
2203                }
2204        },
2205
2206        populate: function(deepCopy, source, result) {
2207                for ( var key in source ) {
2208                        if ( source.hasOwnProperty(key) ) {
2209                                result[key] = deepCopy(source[key], result[key]);
2210                        }
2211                }
2212                return result;
2213        }
2214});
2215
2216// Array copier
2217DataLayer.registerComparator({
2218        can: function(source) {
2219                return ( source instanceof Array );
2220        },
2221
2222        create: function(source) {
2223                return new source.constructor();
2224        },
2225
2226        populate: function(deepCopy, source, result) {
2227                for ( var i=0; i<source.length; i++) {
2228                        result.push( deepCopy(source[i], result[i]) );
2229                }
2230                result =  DataLayer.unique( result )
2231                return result;
2232        }
2233});
2234
2235// Date copier
2236DataLayer.registerComparator({
2237        can: function(source) {
2238                return ( source instanceof Date );
2239        },
2240
2241        create: function(source) {
2242                return new Date(source);
2243        }
2244});
2245
2246// HTML DOM Node copier
2247DataLayer.registerComparator({
2248
2249        // function to detect Nodes.  In particular, we're looking
2250        // for the cloneNode method.  The global document is also defined to
2251        // be a Node, but is a special case in many ways.
2252        can: function(source) {
2253         
2254          if ( window.Node ) {
2255                  return source instanceof Node;
2256          } else {
2257                  // the document is a special Node and doesn't have many of
2258                  // the common properties so we use an identity check instead.
2259                  if ( source === document ) return true;
2260                  return (
2261                          typeof source.nodeType === 'number' &&
2262                          source.attributes &&
2263                          source.childNodes &&
2264                          source.cloneNode
2265                  );
2266          }
2267      },
2268
2269      create: function(source) {
2270              // there can only be one (document).
2271              if ( source === document ) return document;
2272
2273              // start with a shallow copy.  We'll handle the deep copy of
2274              // its children ourselves.
2275              return source.cloneNode(false);
2276      },
2277     
2278      diff: function(base, source){
2279       
2280      },
2281
2282      populate: function(deepCopy, source, result) {
2283              // we're not copying the global document, so don't have to populate it either.
2284              if ( source === document ) return document;
2285
2286              // if this Node has children, deep copy them one-by-one.
2287              if ( source.childNodes && source.childNodes.length ) {
2288                      for ( var i=0; i<source.childNodes.length; i++ ) {
2289                              var childCopy = deepCopy(source.childNodes[i], result.childNodes[i] || false );
2290                              result.appendChild(childCopy);
2291                      }
2292              }
2293                return result;
2294      }
2295});
2296
2297DataLayer.init();
2298
2299// setTimeout(function(){
2300// 
2301//     
2302//
2303// }, 1000 );
2304
2305// var DataLayer = {
2306//
2307//     get: function( concept, filter ){
2308//
2309//      var data = this.storage.get( concept );
2310//
2311//      if( !filter )
2312//          return( data );
2313//
2314//      return this.filter( data, filter );
2315//     },
2316//     
2317//     filter:function( data, filter ){
2318//       
2319//      if( filter.charAt )
2320//          filter = { URI: filter };
2321//     
2322//      var filtered = [];
2323//
2324//      $.each(data, function(i, obj){
2325//       
2326//          for( var attr in filter )
2327//              if( filter[attr] !== obj[attr] )
2328//                  return( true );
2329//
2330//          filtered[i] = obj;
2331//      });
2332//
2333//      return( filtered );
2334//     },
2335//
2336//     find: function( concept, filter, callback ){
2337//
2338//      var data = this.get( concept, filter );
2339//
2340//      if( data )
2341//          return callback( data );
2342//
2343//      //TODO: register callback like a weak listener
2344//
2345// //   $.ajax({
2346// //         type: 'GET',
2347// //         data: $.param( filter ),
2348// //         success: callback, 
2349// //         url: BASE_PATH + filter.URI || concept
2350// //   });
2351//      this.report( concept, filter );
2352//     },
2353//
2354//     put: function( concept, data, filter ){
2355//
2356//      var beforeDiff = this.store( concept, $.extend({},data) );
2357//
2358//      this.report( concept, data, filter, beforeDiff );
2359//     },
2360//     
2361//     
2362//     /*var data = {
2363//                      startTime: $.now(),
2364//                      endTime: $.now() + 1800000,
2365//                      summary: "meu querido evento",
2366//                      description: "desc do evento",
2367//                      location: "prognus software livre",
2368//                      class: 1,
2369//                      calendar: 1,
2370//                      category: 1,
2371//                      participants: [ {
2372//                                         user: { isExternal: true, mail: "user7@prognus.org", name: "user7" }
2373//                                    },{
2374//                                         user: "1003"
2375//                                    } ]
2376//
2377//                };*/
2378//     
2379//
2380//     merge:function( data, target ){
2381//       
2382//      var diff = { New: {}, Update:{}, Delete: {} };
2383//       
2384//      for( var key in data )
2385//      {
2386//          if( !target[ key ] )
2387//              diff.New[ key ] = target[ key ] = data[ key ];
2388//
2389//         
2390//       
2391//      }
2392//       
2393//     }
2394//
2395//     store: function( concept, data, filter ){
2396//
2397//      if( !data.spline )
2398//          data = [ data ];
2399//
2400//      var target = this.storage.get( concept );
2401//     
2402//      var diff = { New: {}, Update:{}, Delete: {} };
2403//
2404//      for( var i = 0; i < data.length; i++ )
2405//      {
2406//          if( data[i].URI && target[ data[i].URI ] )
2407//          {
2408//              diff.Update[ data[i].URI ] = this.merge( target[ data[i].URI ], data[i] );
2409//          }
2410//          else
2411//          {
2412//              diff.New[] = data[i];
2413//          }
2414//      }
2415//
2416//     
2417//
2418//      this.broadcast( concept, data );
2419//
2420//      if( filter )
2421//          target = this.filter( target, filter );
2422//
2423//      if( target )
2424//          data = $.extend( target, data );
2425//
2426//      this.storage.set( concept, data );
2427//
2428// //   return;
2429//     },
2430//     
2431//     set: function( concept, data, filter ){
2432//
2433//       
2434//
2435//     },
2436//
2437//     post: function( concept, data, filter, isNew ){
2438//
2439//      var callback = function(  ){ DataLayer.store( concept, data, filter ) };
2440//
2441//      //TODO: register callback like a weak listener
2442//
2443//      this.report( concept, data, filter, isNew );
2444//     },
2445//     
2446//     report: function( concept, filter, postData, isNew ){
2447//       
2448//      $.ajax({
2449//              type: postData ? isNew ? 'POST' : 'PUT' : 'GET',
2450//              data: postData || $.param( filter ),
2451//              success: function( data ){ DataLayer.broadcast( concept ) },
2452//              url: BASE_PATH + filter.URI || concept
2453//        });
2454//     },
2455//     
2456//     del:function( concept, filter ){
2457//
2458//       
2459//
2460//     }
2461//     
2462//     broadcast: function( concept, data ){
2463//
2464//     
2465//
2466//     },
2467//
2468//     pool: function(){
2469//       
2470//     },
2471//
2472//     refresh: function(){
2473//       
2474//     }
2475// };
2476
2477//
2478// DataLayer = {
2479//   
2480//     get: function( concept, filter ){
2481//
2482//      var data = this.storage.get( concept );
2483//
2484//      if( !filter )
2485//          return( data );
2486//
2487//      if( filter.charAt )
2488//          filter = { URI: filter };
2489//     
2490//      var filtered = [];
2491//
2492//      $.each(data, function(i, obj){
2493//       
2494//          for( var attr in filter )
2495//              if( filter[attr] !== obj[attr] )
2496//                  return( true );
2497//
2498//          filtered[i] = obj;
2499//      });
2500//
2501//      return( filtered );
2502//     },
2503//
2504//     find: function( concept, filter, callback ){
2505//
2506//      var data = this.get( concept, filter );
2507//
2508//      if( data )
2509//          return callback( data );
2510//
2511//       $.ajax({
2512//            type: 'GET',
2513//            data: $.param( filter ),
2514//            success: callback, 
2515//            url: filter.URI || concept
2516//      });
2517//     },
2518//
2519//     put: function( concept, data, filter ){
2520//
2521//      var target = this.get( concept, filter );
2522//
2523//      if( target )
2524//          data = $.extend( target, data );
2525//       
2526//      this.storage.set( concept, data );
2527//     
2528//      //diff
2529//     },
2530//     
2531//     post: function( concept, data, filter ){
2532//
2533//     
2534//
2535//     },
2536//     
2537//     pool: function(){
2538//       
2539//     },
2540//     
2541//     queue: function(){
2542//       
2543//     },
2544//     
2545//     dequeue: function(){
2546//       
2547//     },
2548//     
2549//     refresh: function(){
2550//       
2551//     }
2552// }
2553
2554// var DataLayer = {
2555 
2556//       cache: {},
2557 
2558//       get: function( concept, location ){
2559       
2560           /* if( location )
2561            {*/
2562//              var schema = $.data( this.cache, concept + ':schema' );
2563//              var uri = [];
2564//
2565//              $.each( schema, function( i, addrs ){
2566//                    uri[ uri.length ] = location[addrs];
2567//              });
2568
2569                /*var filter = [], result = false;
2570
2571                while( !(result = $.data( this.cache, uri.join( '.' ) )) || !(uri = uri.join('.')) )
2572                  filter[ filter.length ] = uri.pop();
2573 
2574                if( !filter.length )
2575                {
2576                    var indexes = $.data( this.cache, uri + ':indexes' );
2577
2578                    if( indexes )
2579                        Array.prototype.concat.apply( result, indexes );
2580                   
2581                    return( result );
2582                }
2583
2584                for( var i = 0; i < result.length; i++ )
2585                {
2586                   
2587                }
2588
2589                if( result.length )
2590                    return( result );
2591            }*/
2592
2593//          var data = $.data( this.cache, concept );
2594
2595//          if( !data )
2596//              $.ajax( );
2597
2598//          return( data );
2599//       },
2600     
2601//       data: function(){
2602//
2603//       
2604//
2605//       }
2606//       
2607//       search: function( concept, filter ){
2608//
2609//        var schema = $.data( this.cache, concept + ':schema' );
2610//        var uri = [];
2611//
2612//        $.each( schema, function( i, addrs ){
2613//              uri[ uri.length ] = location[addrs];
2614//        });
2615//       }
2616//       put: function( concept, data, location ){
2617
2618//          if( location )
2619//          {
2620//              var schema = $.data( this.cache, concept + ':schema');
2621//              var uri = [];
2622
2623//              $.each( schema, function( i, addrs ){
2624//                    uri[ uri.length ] = location[addrs];
2625//              });
2626
2627//              var result = false, filter = [];
2628
2629//              while( !(result = $.data( this.cache, uri.join('.')) )
2630//                  filter[ filter.length ] = uri.pop();
2631
2632//              $.data( this.cache, '
2633
2634//          }
2635
2636//              var model = this.storage.get( concept );
2637//
2638//              $.each( model, function( i, o ){
2639//                  $.each( location, function( ii, attr ){
2640//                       if( o[ii] === attr )
2641//                          return( false );
2642//                  });
2643//              });
2644
2645//          return $.data( this.cache, concept, data );
2646
2647//       },
2648//       del: function( concept, location ){
2649//
2650//          if( location )
2651//          {
2652//              var schema = $.data( this.cache, 'concepts', concept );
2653//              var uri = [];
2654//
2655//              $.each( schema, function( i, addrs ){
2656//                    uri[ uri.length ] = location[addrs];
2657//              });
2658//
2659//              concept = uri.join( '.' );
2660
2661//              var model = this.storage.get( concept );
2662//
2663//              $.each( model, function( i, o ){
2664//                  $.each( location, function( ii, attr ){
2665//                       if( o[ii] === attr )
2666//                          return( false );
2667//                  });
2668//              });
2669//          }
2670//         
2671//     
2672//          $.removeData( this.cache, concept );
2673//       }
2674// }
2675
2676// internalUrl = /^([A-z0-9-_]+)(:[A-z0-9-_]+)?$/;
2677// internalUri = /^([a-zA-Z0-9-_]+)\(([a-zA-Z0-9-_]+)\):\/\/(.*)|([a-zA-Z0-9-_]+):\/\/(.*)$/;
2678// isGeneratedId = /^\d+\(javascript\)$/;
2679// arrayName = /^([A-z0-9-_]+)\[\]$/;
2680// startsDoubleDot = /^:/;
2681// FILE = 'files';
2682// // cached_urls = {};
2683//
2684// $.ajaxPrefilter(function( options, originalOptions, jqXHR ){
2685//
2686//       if( options.url != 'undefined' && internalUrl.test( options.url ) ){
2687//
2688// //     if( !cached_urls[options.url] )
2689// //         return;
2690// //     alert( options.url + " dentro" );
2691//        jqXHR.abort();
2692//
2693//        var callback = ( options.success || options.complete || $.noop );
2694//
2695//        switch( options.type.toUpperCase() )
2696//        {
2697//          case 'GET':
2698//                return callback( DataLayer.get( options.url, /*false,*/ options.data ) );
2699//
2700//          case 'POST':
2701//                return callback( DataLayer.put( options.url, options.data ) );
2702//        }
2703//
2704//        //return( false );
2705//
2706// //     options.url = params[1];
2707// //     options.data = ( options.data || "" ) + "&" + params[2];
2708//       }
2709//
2710// });
2711//
2712// // $("a").live("click", function( event ){
2713// //
2714// //     event.preventDefault();
2715// //
2716// //     $.ajax({
2717// //
2718// //   
2719// //
2720// //     });
2721// //
2722// // });
2723//
2724// $("form").live( "submit", function( event ){
2725//
2726//     var $this = $(this), action = $this.attr('action'), res = false,
2727//     
2728//     method = $this.attr( 'method' ),
2729//     
2730//     fileInputs = $this.find('input[type="file"]');
2731//     
2732//     if( fileInputs.length && !$this.is('[enctype="multipart/form-data"]') )
2733//     {
2734//      event.preventDefault();
2735//     
2736//      var formData = $this.serializeArray(), callback = DataLayer.receive;
2737//       
2738//      if( res = internalUrl.exec( action ) )
2739//      {
2740//          var data = {}, action = res[1];
2741//
2742//          data[action] = DataLayer.form( this, fileInputs );
2743//
2744//          formData = DataLayer.serializeForm( data );
2745//             
2746//              action = DataLayer.dispatchPath + 'post.php';
2747//          callback = $.noop;
2748//      }
2749//
2750//      DataLayer.send( action,
2751//                      [ method, 'iframe json' ], {},
2752//                      //TODO: check the type for conversion
2753//                      callback,
2754//                      false, { 'formData': formData,  'fileInput': fileInputs, 'paramName': FILE + '[]' } );
2755//
2756//      return( false );
2757//     }
2758//     
2759//     if( res = internalUrl.exec( action ) )
2760//     {
2761//      event.preventDefault();
2762//
2763//      var data = DataLayer.form( this );
2764//     
2765//      switch( method.toUpperCase() )
2766//      {
2767//        case 'GET':
2768//              DataLayer.get( res[0], data );
2769//
2770//        case 'POST':
2771//              DataLayer.put( res[1], data );
2772//      }
2773//
2774//      return( false );
2775//     }
2776//
2777//     return( true );
2778// });
2779//
2780// this.storage = new $.store();
2781//
2782// DataLayer = {
2783//
2784//     links: {},
2785//     concepts: {},
2786//     listeners: {},
2787//     encoders: {},
2788//     decoders: {},
2789//     templates: {},
2790//     criterias: {},
2791//     tasks: [],
2792//
2793//     render: function( templateName, data, filter, formatter, force ){
2794//
2795//      if( $.isFunction( filter ) )
2796//      {
2797//          force = formatter;
2798//          formatter = filter;
2799//          filter = false;
2800//      }
2801//
2802//      if( typeof data === "string" )
2803//      {
2804//          data = this.get( data, filter, force ) || {};
2805//      }
2806//     
2807//      var formatting = function( template ){
2808//
2809//            if( template === false ) return( false );
2810//
2811//            if( template )
2812//                DataLayer.templates[ templateName ] = new EJS({ text: template, cache: false });
2813//
2814//            var html = DataLayer.templates[ templateName ].render( { data: data } );
2815//
2816//            if( !formatter )
2817//                return( html );
2818//
2819//            return formatter( html );
2820//      }
2821//
2822//      if( this.templates[ templateName ] )
2823//      {
2824//          return formatting();
2825//      }
2826//
2827//      return this.send( DataLayer.templatePath + templateName, 'get', false, formatting, !!!formatter );
2828//     },
2829//     
2830//     send: function( url, type, data, callback, sync, extraOptions ){
2831//       
2832//        var result = false, fired = false;
2833//       
2834//        var envelope = {
2835//
2836//            'async': ( typeof sync !== "undefined" ? !sync : !!callback ),
2837//            'url': url,
2838//            'success': function( dt, textStatus, jqXHR ){
2839//
2840//                  if( callback )
2841//                  {
2842//                      fired = true;
2843//                      result = callback( dt, textStatus, jqXHR );
2844//                  }
2845//                  else
2846//                      result = dt;
2847//
2848//              },
2849//            'complete': function( jqXHR, textStatus ){
2850//
2851//                if( !fired && callback )
2852//                    result = callback( false, textStatus, jqXHR );
2853//
2854//            },
2855//
2856//            'type': $.isArray( type ) ? type[0] : type,
2857//            'data': data
2858//
2859//          };
2860//
2861//        if( $.isArray( type ) && type[1] )
2862//            envelope['dataType'] = type[1];
2863//
2864//        if( extraOptions )
2865//            envelope = $.extend( envelope, extraOptions );
2866//
2867//        $.ajax( envelope );
2868//       
2869//        return( result );
2870//     },
2871//     
2872//     dispatch: function( dispatcher, data, callback, isPost, dataType ){
2873//       
2874//       return this.send( this.dispatchPath + dispatcher + ".php",
2875//                      [ ( isPost ? 'post' : 'get' ), dataType || 'json' ],
2876//                      data,
2877//                      callback );
2878//
2879// //       $.ajax({
2880// //         'async': !!callback,
2881// //         'url': this.dispatchPath + dispatcher + ".php",
2882// //         'type': ( isPost ? 'post' : 'get' ),
2883// //         'dataType': 'json',
2884// //         'data': data,
2885// //         'success': function( dt, textStatus, jqXHR ){
2886// //
2887// //               if( callback )
2888// //               {
2889// //                   fired = true;
2890// //                   callback( dt, textStatus, jqXHR );
2891// //               }
2892// //               else
2893// //                   result = dt;
2894// //
2895// //           },
2896// //         'complete': function( jqXHR, textStatus ){
2897// //
2898// //             if( !fired && callback )
2899// //                 callback( false, textStatus, jqXHR );
2900// //
2901// //         }/*,
2902// //         'processData': false*/
2903// //     });
2904//
2905//       //return( result );
2906//     },
2907//
2908//     form: function( target, fileInputs ){
2909//
2910//      var params = {}, $this = $(target), inputArray = $this.serializeArray();
2911//
2912//      if( !$this.is( "form" ) )
2913//          $this = $this.parents( "form" );
2914//             
2915//      if( fileInputs )
2916//              fileInputs.each( function( i, el ){
2917//
2918//            inputArray[ inputArray.length ] = { name: $(this).prop("name"), value: FILE + i };
2919//
2920//              });
2921//
2922//      $.each( inputArray, function( i, el ){
2923//
2924//          if( newName = arrayName.exec( el.name ) )
2925//              el.name = newName[1];
2926//          else if( !params[ el.name ] )
2927//              return( params[ el.name ] = el.value );
2928//
2929//          params[ el.name ] = params[ el.name ] || [];
2930//
2931//          if( $.type(params[ el.name ]) !== "array" )
2932//              params[ el.name ] = [ params[ el.name ] ];
2933//
2934//          params[ el.name ].push( el.value );
2935//      });
2936//
2937// //   alert(dump(params));
2938//
2939//      return this.decode( $this.attr( "action" ), params );
2940//     },
2941//     
2942//      serializeForm: function( data, level ){
2943//     
2944//              var formData = [];
2945//     
2946//              for( key in data )
2947//              {
2948//                      var value = data[key];
2949//
2950//                      if( level !== undefined )
2951//                              key = level+'['+key+']';
2952//
2953//                      if( $.isArray(value) || $.isPlainObject(value) )
2954//                              formData = formData.concat( this.serializeForm( value, key ) );
2955//                      else
2956//                              formData[ formData.length ] = { name: key, value: value };
2957//              }
2958//             
2959//              return( formData );
2960//      },
2961//
2962//     blend: function( action, data ){
2963//
2964// //   if( notArray = (!$.isArray(data)) )
2965// //       data = [ data ];
2966//
2967//      var form = $('form[action="'+action+'"]');
2968//
2969//      form.get(0).reset();
2970//
2971//      var named = form.find( 'input[name]' );
2972//
2973//      for( var name in data )
2974//      {
2975//          named.filter( '[name="'+name+'"]' ).val( data[name] );
2976//      }
2977//     },
2978//
2979// 
2980//     
2981//     put: function( concept, filter, data, oneSide ){
2982//       
2983//       ///////////////////////////// normalize ////////////////////////////////
2984//      if( arguments.length == 2 )
2985//      {
2986//          data = filter;
2987//          filter = false;
2988//      }
2989//      if( typeof data === "undefined" ||
2990//          $.type(data) === "boolean" )
2991//      {
2992//          oneSide = data;
2993//          data = filter;
2994//          filter = false;
2995//      }
2996//     
2997//      if( !concept || !data )
2998//          return( false );
2999//
3000//      var decoder = "", id = false, bothSides = (typeof oneSide === "undefined"), notArray, res;
3001//     
3002//      if( $.type(filter) === "string" )
3003//      {
3004//          id = filter;
3005//          filter = false;
3006//      }
3007//
3008//      if( id )
3009//          data.id = id;
3010//
3011//      if( notArray = ( $.type( data ) !== "array" ) )
3012//          data = [ data ];
3013//
3014//      if( res = internalUrl.exec( concept ) )
3015//      {
3016//          //TODO: verificar se a decodificaçao deve ser feita em cada item do array
3017//          data = this.decode( concept, data );
3018//          concept = res[1];
3019//          decoder = res[2];
3020//      }
3021//
3022//       ////////////////////////////////////////////////////////////////////////
3023//
3024//      if( bothSides || !oneSide )
3025//      {
3026//          var result = false, links = this.links( concept ),
3027//          current = this.check( concept ) || {}, ids = [];
3028//
3029//          for( var i = 0; i < data.length; i++ )
3030//          {
3031//              var key = ids[ ids.length ] = data[i].id || this.generateId( concept ), updateSet = {};
3032//
3033//              ////////////////////////////// linkage /////////////////////////////////   
3034//              for( var link in links )
3035//              {
3036//                  if( data[i][link] )
3037//                  {
3038//                      var isConcept = false;
3039//                   
3040//                      if( isConcept = this.isConcept( concept, link ) )
3041//                          data[i][link] = [ data[i][link] ];
3042//
3043//                      var _this = this;
3044//
3045//                      $.each( data[i][link], function( ii, el ){
3046//
3047//                              var isRef = false;
3048//
3049//                              if( isRef = ($.type(el) === "string") )
3050//                                  el = { id: el };
3051//
3052//                              var nestedLinks = _this.links( links[link], true );
3053//                              //removido pois o mesmo esta gerando inconsistencia em tudo
3054//                              //if( DataLayer.isConcept( links[link], nestedLinks[concept] ) )
3055//                              if( isConcept )
3056//                              {
3057//                                  el[ nestedLinks[link] ] = el[ nestedLinks[link] ] || [];
3058//                                  el[ nestedLinks[link] ].push( key );
3059//                              }
3060//                              else
3061//                                  el[ nestedLinks[link] ] = key;
3062//
3063//                              if( isRef && ( !current[ key ] || !current[ key ][ link ] ||
3064//                                             (isConcept ? current[ key ][ link ] !== el.id : !$.inArray( el.id, current[ key ][ link ] )) ) )
3065//                              {
3066//                                  updateSet[ links[link] ] = updateSet[ links[link] ] || [];
3067//                                  updateSet[ links[link] ].push( el );
3068//                              }
3069//                              else if( !isRef )
3070//                                  data[i][link][ii] = _this.put( links[link], el, oneSide );
3071//                          });
3072//
3073//                      if( isConcept )
3074//                          data[i][link] = data[i][link][0];
3075//                  }
3076//              }
3077//              //////////////////////////////////////////////////////////////////////////
3078//
3079//              if( data[i].id )
3080//                  data[i] = this.merge( current[ data[i].id ], data[i] );
3081//
3082//               current[ key ] = data[i];
3083//
3084//              if( bothSides )
3085//                this.report( concept, key, data[i] );
3086//          }
3087//
3088//          this.store( concept, current );
3089//
3090//          for( var setKey in updateSet )
3091//          {
3092//              if( bothSides )
3093//                  for( var i = 0; i < updateSet[ setKey ].length; i++ )
3094//                    this.report( setKey, updateSet[ setKey ][i].id, updateSet[ setKey ][i] );
3095//                 
3096//              DataLayer.put( setKey, updateSet[ setKey ], false );
3097//          }
3098//      }
3099//
3100//      if( oneSide )
3101//          this.commit( concept, ids/*, true */);
3102//
3103//      this.broadcast( concept, oneSide ? 'server' : bothSides ? 'serverclient' : 'client', true );
3104//
3105//      return( notArray ? ids[0] : ids );
3106//
3107//     },
3108//     
3109//     remove: function( concept, id, oneSide ){
3110//       
3111//      var bothSides = (typeof oneSide === "undefined"),
3112//
3113//      links = this.links( concept ), ids = [],
3114//
3115//      current = this.check( concept, id );
3116//
3117//      if( !current ) return;
3118//     
3119//      if( id )
3120//          current.id = id;
3121//
3122//      if( notArray = ( $.type( current ) !== "array" ) )
3123//          current = [ current ];
3124//
3125//      for( var i = 0; i < current.length; i++ )
3126//      {
3127//          var currentId = ids[ ids.length ] = current[i].id;
3128//
3129//          if( bothSides )
3130//            this.report( concept, currentId, false );
3131//
3132//          if( bothSides || !oneSide )
3133//            this.del( concept, currentId );
3134//
3135//          for( var link in links )
3136//          {
3137//              if( !current[i][link] )
3138//                  continue;
3139//
3140//              var nestedLinks = this.links( links[link], true );
3141//
3142//              if( isConcept = this.isConcept( concept, link ) )
3143//                  current[i][link] = [ current[i][link] ];
3144//
3145//              $.each( current[i][link], function( ii, el ){
3146//
3147//                      el = DataLayer.storage.cache[links[link]][el];
3148//
3149//                      if( notArrayNested = ( $.type( el[ nestedLinks[link] ] ) !== "array" ) )
3150//                          el[ nestedLinks[link] ] = [ el[nestedLinks[link]] ];
3151//
3152//                      el[ nestedLinks[link] ] = $.grep( el[ nestedLinks[link] ], function( nested, iii ){
3153//                          return ( currentId !== nested );
3154//                      });
3155//
3156//                      if( notArrayNested )
3157//                          el[ nestedLinks[link] ] = el[ nestedLinks[link] ][0] || false;
3158//                      if(!el[ nestedLinks[link] ] || !el[ nestedLinks[link] ].length)
3159//                              delete el[ nestedLinks[link] ];
3160//              });
3161//          }
3162//      }
3163//
3164//      if( oneSide )
3165//          this.commit( concept, ids );
3166//
3167//      this.broadcast( concept, oneSide ? 'server' : bothSides ? 'serverclient' : 'client', false );
3168//     },
3169//     
3170//     report: function( concept, id, data )
3171//     {     
3172//      var current = this.check( ':current', concept ) || {};
3173//
3174//      if( !current[ id ] )
3175//          current[ id ] = this.check( concept, id ) || {};
3176//     
3177//      this.store( ':current', concept, current );
3178//
3179//      var diff = this.diff( current[ id ], data );
3180//
3181//      var diffs = this.check( ':diff', concept ) || {};
3182//
3183//      if( diffs[ id ] )
3184//          diff = this.merge( diffs[ id ], diff );
3185//
3186//      if( !diff || !$.isEmptyObject( diff ) )
3187//          diffs[ id ] = diff;
3188//
3189//      this.store( ':diff', concept, diffs );
3190//     },
3191//
3192// //     enqueue: function( queueName, concept, id, data ){
3193// //
3194// //   var queue = this.check( ':' + queueName, concept ) || {};
3195// //
3196// //
3197// //     },
3198// //     
3199// //     dequeue: function( queueName, concept, id ){
3200// //
3201// //   
3202// //
3203// //     },
3204//     
3205//     
3206//     
3207//     rollback: function( concept, ids ){
3208//       
3209//      var queue = this.prepareQ( 'current', concept, ids );
3210//
3211//      ids = [];
3212//
3213//      for( var id in queue )
3214//      {
3215//           this.put( concept, id, queue[id], false );
3216//
3217//           ids[ ids.length ] = id;
3218//      }
3219//
3220//      this.clearQ( concept, ( ids.length ? ids : false ) );
3221//
3222//      this.broadcast( concept, 'revert' );
3223//       
3224//     },
3225//     
3226//     prepareQ: function( queueName, concept, ids ){
3227//       
3228//       var notArray = false;
3229//       
3230//       if( notArray = ($.type(concept) !== "array") )
3231//        concept = [ concept ];
3232//       
3233//       var q = {};
3234//       
3235//       for( var i = 0; i < concept.length; i++ )
3236//       {
3237//        var queue = this.check( ':' + queueName, concept[i] || false );
3238//       
3239//        if( !queue ) continue;
3240//
3241//        if( ids )
3242//        {
3243//            if( $.type(ids) !== "array" )
3244//                ids = [ ids ];
3245//
3246//            var filtered = {};
3247//
3248//            for( var ii = 0; ii < ids.length; ii++ )
3249//            {
3250//                filtered[ ids[ii] ] = queue[ ids[ii] ];
3251//            }
3252//
3253//            queue = filtered;
3254//        }
3255//
3256//        q[ concept[i] ] = queue;
3257//       }
3258//       
3259//       return( notArray ? q[ concept[0] ] : q );
3260//     },
3261//     
3262//     clearQ: function( concept, ids ){
3263//       
3264//              var current = this.check( ':current', concept || false );
3265//      var diffs = this.check( ':diff', concept || false );
3266//
3267//      if( !ids )
3268//          current = diffs = {};
3269//      else
3270//      {
3271//          if( notArray = ($.type(ids) !== "array") )
3272//            ids = [ ids ];
3273//
3274//          for( var i = 0; i < ids.length; i++ )
3275//          {
3276//              delete current[ ids[i] ];
3277//              delete diffs[ ids[i] ];
3278//          }
3279//      }
3280//
3281//      this.store( ':current', concept, current );
3282//      this.store( ':diff', concept, diffs );
3283//     },
3284//
3285//     commit: function( concept, ids, callback ){
3286//       
3287//      var queue = this.prepareQ( 'diff', concept, ids );
3288//
3289//      this.sync( queue, !$.isArray(concept) && concept || false, callback );
3290//     },
3291//     
3292//     sync: function( queue, concept, callback ){
3293//
3294//      if( !queue || $.isEmptyObject( queue ) )
3295//          return;
3296//
3297//      if( concept )
3298//      {
3299//        var helper = {};
3300//        helper[concept] = queue;
3301//        queue = helper;
3302//      }
3303//
3304//      var data = {}, URIs = {};
3305//
3306//      for( var concept in queue )
3307//          for( var id in queue[concept] )
3308//          {
3309//              data[ this.URI( concept, id ) ] = queue[concept][id];
3310//              URIs[ this.URI( concept, id ) ] = { concept: concept, id: id };
3311//          }
3312//
3313//      if( $.isEmptyObject( data ) )
3314//          return;
3315//
3316//      this.dispatch( "Sync", data, function( data, status, jqXHR ){
3317//
3318// //       switch( status )
3319// //       {
3320// //         case "error":
3321// //         case "parsererror":
3322// //           return DataLayer.rollback( concept, URI );
3323// //         case "success":
3324// //           return DataLayer.commit();
3325// //         case "timeout":
3326// //         case "notmodified":
3327// //       }
3328//
3329//          var received = DataLayer.receive( data );
3330//
3331//          for( var URI in URIs )
3332//              if( typeof received[URI] !== "undefined" )
3333//                  DataLayer.clearQ( URIs[URI].concept, URIs[URI].id );
3334//
3335//          if( callback )
3336//              callback( received );
3337//
3338// //       for( var URI in data )
3339// //       {
3340// //           var parsed = DataLayer.parseURI( URI ),
3341// //   
3342// //           concept = parsed[1], id = parsed[3];
3343// //
3344// //           if( $.type(data[URI]) === "string" )
3345// //           {
3346// //             //TODO:threat the exception thrown
3347// //             DataLayer.rollback( concept, id );
3348// //             delete URIs[ URI ];
3349// //             continue;
3350// //           }
3351// //
3352// //           if( data[URI] === false ){
3353// //             DataLayer.remove( concept, id, false );
3354// //             continue;
3355// //           }
3356// //
3357// //           if( id !== data[URI].id )
3358// //             DataLayer.move( concept, id, data[URI].id );
3359// //           
3360// //           DataLayer.put( concept, id, data[URI], false );
3361// //       }
3362// //       
3363// //       for( var URI in URIs )
3364// //            DataLayer.clearQ( URIs[URI].concept, URIs[URI].id );
3365// //       
3366// //       if( callback )
3367// //           callback();
3368//
3369//      }, true );
3370//
3371//     },
3372//     
3373//     receive: function( data ){
3374//       
3375//      var received = {};
3376//     
3377//          for( var URI in data )
3378//          {
3379//              var parsed = DataLayer.parseURI( URI ),
3380//   
3381//          concept = parsed[4], id = parsed[5];
3382//
3383//          received[ URI ] = data[ URI ];
3384//
3385//              if( $.type(data[URI]) === "string" )
3386//              {
3387//                //TODO:threat the exception thrown
3388//                DataLayer.rollback( concept, id );
3389//                continue;
3390//              }
3391//
3392//              if( data[URI] === false ){
3393//                DataLayer.remove( concept, id, false );
3394//                continue;
3395//              }
3396//
3397//              if( id !== data[URI].id )
3398//                DataLayer.move( concept, id, data[URI].id );
3399//             
3400//              DataLayer.put( concept, id, data[URI], false );
3401//          }
3402//         
3403//      return( received );
3404//         
3405//     },
3406//     
3407//     unique: function( origArr ){
3408//
3409//      var newArr = [];
3410//       
3411//      for ( var x = 0; x < origArr.length; x++ )
3412//      {
3413//              var found = false;
3414//          for ( var y = 0; !found && y < newArr.length; y++ )
3415//              if ( origArr[x] === newArr[y] ) 
3416//                found = true;
3417//
3418//          if ( !found )
3419//              newArr[ newArr.length ] = origArr[x];
3420//      }
3421//
3422//      return newArr;
3423//     },
3424//
3425//     merge: function( current, data ){
3426//       
3427//      return this.copy(  data, current );
3428//
3429// //   return $.extend( current, data );
3430//
3431//     },
3432//     
3433//     // clone objects, skip other types.
3434//     clone: function(target) {
3435//          if ( typeof target == 'object' ) {
3436//                  Clone.prototype = target;
3437//                  return new Clone();
3438//          } else {
3439//                  return target;
3440//          }
3441//     },
3442//       
3443//     // Shallow Copy
3444//     shallowCopy: function(target) {
3445//          if (typeof target !== 'object' ) {
3446//                  return target;  // non-object have value sematics, so target is already a copy.
3447//          } else {
3448//                  var value = target.valueOf();
3449//                  if (target != value) {
3450//                          // the object is a standard object wrapper for a native type, say String.
3451//                          // we can make a copy by instantiating a new object around the value.
3452//                          return new target.constructor(value);
3453//                  } else {
3454//                          // ok, we have a normal object. If possible, we'll clone the original's prototype
3455//                          // (not the original) to get an empty object with the same prototype chain as
3456//                          // the original.  If just copy the instance properties.  Otherwise, we have to
3457//                          // copy the whole thing, property-by-property.
3458//                          if ( target instanceof target.constructor && target.constructor !== Object ) {
3459//                                  var c = clone(target.constructor.prototype);
3460//       
3461//                                  // give the copy all the instance properties of target.  It has the same
3462//                                  // prototype as target, so inherited properties are already there.
3463//                                  for ( var property in target) {
3464//                                          if (target.hasOwnProperty(property)) {
3465//                                                  c[property] = target[property];
3466//                                          }
3467//                                  }
3468//                          } else {
3469//                                  var c = {};
3470//                                  for ( var property in target ) c[property] = target[property];
3471//                          }
3472//                         
3473//                          return c;
3474//                  }
3475//          }
3476//     },
3477//
3478//     // entry point for deep copy.
3479//     // source is the object to be deep copied.
3480//     // depth is an optional recursion limit. Defaults to 256.
3481//     // deep copy handles the simple cases itself: non-objects and object's we've seen before.
3482//     // For complex cases, it first identifies an appropriate DeepCopier, then delegate the details of copying the object to him.
3483//     copy: function(source, result, depth) {
3484//       
3485//          // null is a special case: it's the only value of type 'object' without properties.
3486//          if ( source === null ) return null;
3487//
3488//          // All non-objects use value semantics and don't need explict copying.
3489//          if ( typeof source !== 'object' ) return source;
3490//
3491//          if( !depth || !(depth instanceof RecursionHelper) ) depth = new RecursionHelper(depth);
3492//
3493//          var cachedResult = depth.getCachedResult(source);
3494//
3495//          // we've already seen this object during this deep copy operation
3496//          // so can immediately return the result.  This preserves the cyclic
3497//          // reference structure and protects us from infinite recursion.
3498//          if ( cachedResult ) return cachedResult;
3499//
3500//          // objects may need special handling depending on their class.  There is
3501//          // a class of handlers call "DeepCopiers"  that know how to copy certain
3502//          // objects.  There is also a final, generic deep copier that can handle any object.
3503//          for ( var i=0; i<this.comparators.length; i++ ) {
3504//
3505//                  var comparator = this.comparators[i];
3506//
3507//                  if ( comparator.can(source) ) {
3508//     
3509//                          // once we've identified which DeepCopier to use, we need to call it in a very
3510//                          // particular order: create, cache, populate.  This is the key to detecting cycles.
3511//                          // We also keep track of recursion depth when calling the potentially recursive
3512//                          // populate(): this is a fail-fast to prevent an infinite loop from consuming all
3513//                          // available memory and crashing or slowing down the browser.
3514//       
3515//                          if( !result )
3516//                              // Start by creating a stub object that represents the copy.
3517//                              result = comparator.create(source);
3518//                          else if( !comparator.can(result) )
3519//                              throw new Error("can't compare diferent kind of objects.");
3520//
3521//                          // we now know the deep copy of source should always be result, so if we encounter
3522//                          // source again during this deep copy we can immediately use result instead of
3523//                          // descending into it recursively. 
3524//                          depth.cacheResult(source, result);
3525//
3526//                          // only DeepCopier.populate() can recursively deep copy.  So, to keep track
3527//                          // of recursion depth, we increment this shared counter before calling it,
3528//                          // and decrement it afterwards.
3529//                          depth.depth++;
3530//                          if ( depth.depth > depth.maxDepth ) {
3531//                                  throw new Error("Exceeded max recursion depth in deep copy.");
3532//                          }
3533//
3534//                          // It's now safe to let the comparator recursively deep copy its properties.
3535//                          var returned = comparator.populate( function(source, result) { return DataLayer.copy(source, result, depth); }, source, result );
3536//     
3537//                              if(returned)
3538//                                      result = returned;
3539//
3540//                          depth.depth--;
3541//
3542//                          return result;
3543//                  }
3544//          }
3545//          // the generic copier can handle anything, so we should never reach this line.
3546//          throw new Error("no DeepCopier is able to copy " + source);
3547//     },
3548//
3549//     // publicly expose the list of deepCopiers.
3550//     comparators: [],
3551//
3552//     // make deep copy() extensible by allowing others to
3553//     // register their own custom Comparators.
3554//     registerComparator: function(comparatorOptions) {
3555//
3556//        // publicly expose the Comparator class.
3557//        var comparator = {
3558//
3559//            // determines if this Comparator can handle the given object.
3560//            can: function(source) { return false; },
3561//     
3562//            // starts the deep copying process by creating the copy object.  You
3563//            // can initialize any properties you want, but you can't call recursively
3564//            // into the copy().
3565//            create: function(source) { },
3566//
3567//            // Completes the deep copy of the source object by populating any properties
3568//            // that need to be recursively deep copied.  You can do this by using the
3569//            // provided deepCopyAlgorithm instance's copy() method.  This will handle
3570//            // cyclic references for objects already deepCopied, including the source object
3571//            // itself.  The "result" passed in is the object returned from create().
3572//            populate: function(deepCopyAlgorithm, source, result) {}
3573//        };
3574//
3575//        for ( var key in comparatorOptions ) comparator[key] = comparatorOptions[key];
3576//
3577//        this.comparators.unshift( comparator );
3578//     },
3579// 
3580//     diff: function( base, toDiff ){
3581//
3582//      if( typeof base === 'undefined' || $.isEmptyObject(base) )
3583//          return( toDiff );
3584//
3585//      if( toDiff === false )
3586//          return( false );
3587//
3588//      toDiff = $.extend( {}, toDiff );
3589//
3590//      for( var key in toDiff )
3591//      {
3592//          switch( $.type(toDiff[key]) )
3593//          {
3594//            case 'object':
3595//              if( $.isEmptyObject(toDiff[key] = this.diff( base[key], toDiff[key] )) )
3596//                delete toDiff[key];
3597//            break;
3598//            case 'array':
3599//              if( base[key] && !(toDiff[key] = $.grep( toDiff[key], function( el, i ){ return( $.inArray( el, base[key] ) === -1 ); } )).length )
3600//                delete toDiff[key];
3601//            break;
3602//            default:
3603//              if( base[key] == toDiff[key] )
3604//                delete toDiff[key];
3605//          }
3606//      }
3607//
3608//      return( toDiff );
3609//
3610//     },
3611//     
3612//     links: function( concept, reverse ){
3613//
3614//      if( !this.links[ concept ] )
3615//      {
3616//          var result = this.dispatch( "links", { concept: concept } ) || false;
3617//
3618//          if( !result )
3619//              return( false );
3620//
3621//          this.concepts[ concept ] = $.extend( this.concepts[ concept ] || {},
3622//                                               result['concepts'] || {} );
3623//
3624//          this.links[ concept ] =  result['links'] || {};
3625//          this.nestedLinks[ concept ] = result['nestedLinks'] || {};
3626//      }
3627//
3628//      if( reverse )
3629//      {
3630//          return( this.nestedLinks[ concept ] );
3631// //       var reverted = {}, llinks = this.links[ concept ];
3632// //     
3633// //       for( var key in llinks )
3634// //           reverted[ llinks[key] ] = key;
3635// //
3636// //       return( reverted );
3637//      }
3638//
3639//      return( this.links[ concept ] );
3640//
3641//     },
3642//     
3643//     isConcept: function( concept, attr ){
3644//       
3645//      if( typeof this.concepts[concept] === "undefined" )
3646//      {
3647//          this.links( concept );
3648//      }
3649//
3650//      return !!this.concepts[ concept ][ attr ];
3651//     },
3652//     
3653//     URI: function( concept, URI, context ){
3654//       
3655//      if( res = internalUrl.exec( concept ) )
3656//          concept = res[1];
3657//     
3658//      context = context ? "(" + context + ")" : "";
3659//       
3660//      if( URI )
3661//          return( concept + context + "://" + URI );
3662//      else
3663//          return( concept );
3664//       
3665//     },
3666//     
3667//     parseURI: function( URI ){
3668//
3669//      return internalUri.exec( URI ) || false;
3670//
3671//     },
3672//     
3673//     
3674//   
3675//     
3676//     generateId: function( concept ){
3677//       
3678//      var newId = this.counter + "(javascript)";
3679//       
3680//      this.store( ":counter", (this.counter++) + "" );
3681//     
3682//      return( newId );
3683//     },
3684//   
3685//
3686//   
3687//
3688//     get: function( concept, /*URI, */filter, oneSide ){
3689//
3690//      ///////////////////////////// normalize ////////////////////////////////
3691//      if( arguments.length == 2 && $.type(filter) === "boolean" )
3692//      {
3693//          oneSide = filter;
3694//          filter = false;
3695//      }
3696//     
3697//      var encoder = false, id = false, bothSides = (typeof oneSide === 'undefined'), res;
3698//     
3699//      if( $.type(filter) === "string" )
3700//      {
3701//          id = filter;
3702//          filter = false;
3703//      }
3704//
3705//      filter = filter || false;
3706//
3707//      if( !concept )
3708//          return( false );
3709//
3710//      if( res = internalUrl.exec( concept ) )
3711//      {
3712//          encoder = concept;
3713//          concept = res[1];
3714//
3715//          if( filter )
3716//              filter = this.criteria( encoder, filter );
3717//      }
3718//     
3719//      if ( $.type(filter) === "array" )
3720//      {
3721//          filter = { filter: filter, criteria: false };
3722//      }
3723//     
3724//      //////////////////////////////////////////////////////////////////////////
3725//     
3726//      var result = false;
3727//
3728//      if( bothSides || !oneSide )
3729//          result = this.check( concept, id || filter );
3730//
3731//      if( !result && (bothSides || oneSide) )
3732//      {
3733//          result = this.request( concept, id || filter.filter, filter.criteria );
3734//
3735//          if( result && bothSides && (!filter ||
3736//                                      !filter.criteria ||
3737//                                      !filter.criteria.format) )
3738//          {
3739//            var newResult = [];
3740//         
3741//            for( var i = 0; i < result.length; i++ )
3742//                newResult[i] = $.extend( {}, result[i] );
3743//
3744//            this.put( concept, id, newResult, false );
3745//          }
3746//      }
3747//
3748//      if( /*result &&*/ encoder )
3749//          result = this.encode( encoder, result, filter ); //TODO: retirar o filtro no método encode
3750//
3751//      return( result );
3752//     },
3753//     
3754//     filter: function( base, filter, criteria ){
3755//       
3756//      var filtered = [];
3757//       
3758//      for( var key in base )
3759//      {
3760// //       if( !noGroup )
3761// //           for( var i = 0, current = original; i < filter.length && ( current === original ); i++ )
3762// //               current = this.compare( operator, current, this.compare( base[key], filter[i] ) );
3763//
3764//          if( this.storage.filter( base[key], filter ) )
3765//              filtered[ filtered.length ] = key;
3766//      }
3767//
3768//      return( filtered );
3769//     },
3770//     
3771//     compare: function( operator, base, test ){
3772//       
3773//       switch( operator )
3774//       {
3775//        case '*':  return RegExp( ".*" + test + ".*" ).test( base );
3776//        case '^':  return RegExp( "^" + test +  ".*" ).test( base );
3777//        case '$':  return RegExp( ".*"  + test + "$" ).test( base );
3778//
3779//        case '&':  return ( base && test );
3780//        case '|':  return ( base || test );
3781//
3782//        case '=':  return ( base == test );
3783//        case '<=': return ( base <= test );
3784//        case '>=': return ( base >= test );
3785//        case '>':  return ( base <  test );
3786//        case '<':  return ( base >  test );
3787//       }
3788//       
3789//     },
3790//     
3791// //     clone: function( object ){
3792// //
3793// //   new { prototype: object };
3794// //
3795// //     },
3796//
3797//     check: function( namespace, keys ){
3798//
3799//      if( !namespace )
3800//          return( false );
3801//
3802//      var result = this.storage.get( namespace );
3803//
3804//      if( !keys || !result )
3805//        return( result || false );
3806//
3807//      if( notArray = $.type(keys) === "string" )
3808//          keys = [ keys ];
3809//      else if( $.type(keys) !== "array" )
3810//          keys = this.filter( result, keys.filter, keys.criteria );
3811//
3812//      var res = [];
3813//
3814//      for( var i = 0; i < keys.length; i++ )
3815//          res[ res.length ] = result[keys[i]];
3816//
3817//      return( notArray ? res[0] || false : res.length ? res : false );
3818//     },
3819//
3820//     storage: {
3821//       
3822//      cache: {},
3823//       
3824//      set: function( key, value ){
3825//
3826//          this.cache[key] = value;
3827//
3828//      },
3829//      get: function( key ){
3830//
3831//          return DataLayer.copy( this.cache[key] );
3832//
3833//      },
3834//      del: function( key ){
3835//
3836//          delete this.cache[key];
3837//
3838//      },
3839//     
3840//      filter: function( base, filter ){
3841//       
3842//          var bool, op = filter.shift();
3843//
3844//          switch( op )
3845//          {
3846//              case 'IN':
3847//                for( var i = 0, f = []; i < filter[1].length || !(filter = f); i++ )
3848//                    f[i] = [ '=', filter[0], filter[1][i] ];
3849//              case 'OR':
3850//                  op = '|';
3851//                  bool = false;
3852//              break;
3853//              case 'AND':
3854//                  op = '&';
3855//                  bool = true;
3856//              break;
3857//              default : return DataLayer.compare( op, base[ filter[0] ], filter[1] );
3858//          }
3859//         
3860//          for( var strict = bool;
3861//
3862//              filter.length && ( strict ? bool : !bool );
3863//         
3864//              bool = DataLayer.compare( op, bool, this.filter( base, filter.shift() ) ) );
3865//
3866//          return( bool );
3867//      }
3868//     },
3869//
3870//     flush: function(){
3871//
3872//     },
3873//     
3874//     restore: function(){
3875//       
3876//     },
3877//
3878//     store: function( namespace, key, data ){
3879//
3880//      if( !data )
3881//        return this.storage.set( namespace, key );
3882//
3883//      var res = this.check( namespace ) || {};
3884//
3885//      res[key] = data;
3886//
3887//      return this.storage.set( namespace, res );
3888//     },
3889//
3890//     del: function( namespace, key ){
3891//       
3892//      if( !key )
3893//        return this.storage.del( namespace );
3894//
3895//      var res = this.check( namespace ) || {};
3896//
3897//      delete res[key];
3898//
3899//      return this.storage.set( namespace, res );
3900//       
3901//     },
3902//     
3903//      move: function( concept, oldId, newId ){
3904//
3905//      this.put( concept, newId, this.check( concept, oldId ), false );
3906//
3907//      this.remove( concept, oldId, false );
3908//     },
3909//     
3910//
3911//     
3912//     
3913//     
3914//     request: function( concept, filter, criteria ){
3915//
3916//       var id = false, criteria = criteria || {};
3917//
3918//       if( $.type(filter) === "string" )
3919//       {
3920//        id = filter;
3921//        filter = false;
3922//       }
3923//
3924//       return this.dispatch( "request", {
3925//
3926//        concept: concept || '',
3927//        id: id || '',
3928//        filter: filter || '',
3929//        criteria: criteria || '',
3930//        service: criteria.service || '',
3931//        properties: criteria.properties || ''
3932//
3933//       } );
3934//     },
3935//
3936//     
3937//     //         sync: function( data, callback ){
3938// //
3939// //   if( !data || $.isEmptyObject( data ) )
3940// //       return;
3941// //       
3942// //   this.send( "Sync", data, function( data, status, jqXHR ){
3943// //
3944// // //            switch( status )
3945// // //            {
3946// // //              case "error":
3947// // //              case "parsererror":
3948// // //                return DataLayer.rollback( concept, URI );
3949// // //              case "success":
3950// // //                return DataLayer.commit();
3951// // //              case "timeout":
3952// // //              case "notmodified":
3953// // //            }
3954// //
3955// //       if( callback )
3956// //       {
3957// //           var result = callback( data, status, jqXHR );
3958// //
3959// //           if( result === false )
3960// //               return;
3961// //           else if( typeof result != "undefined" )
3962// //               data = result;
3963// //       }
3964// //
3965// //       for( var URI in data )
3966// //       {
3967// //           var parsed = DataLayer.parseURI( URI ),
3968// //   
3969// //           concept = parsed[1], /*URI = parsed[3],*/
3970// //
3971// //           links = DataLayer.links( concept );
3972// //
3973// //           for( var linkName in links )
3974// //           {
3975// //               var subURI = data[URI][linkName];
3976// //
3977// //               if( subURI && data[subURI] )
3978// //               {
3979// //                   data[URI][linkName] = DataLayer.put( linkName, subURI, data[subURI], false );
3980// //
3981// //                   delete( data[subURI] );
3982// //               }
3983// //           }
3984// //
3985// //           DataLayer.put( concept, URI, data[URI], false );
3986// //       }
3987// //   }, true );
3988// //
3989// //     },
3990//
3991// //     report: function( concept, URI, data, sync )
3992// //     {
3993// //   var current = this.dequeue( 'current', concept, URI );
3994// //
3995// //   if( !current )
3996// //       this.enqueue( 'current', concept, URI, ( current = this.check( concept, URI ) || {} ) );
3997// //
3998// //   var diff = this.diff( current, data );
3999// //
4000// //   if( !diff )
4001// //       this.dequeue( 'current', concept, URI, true );
4002// //   else
4003// //       this.enqueue( 'diff', concept, URI, diff );
4004// //   
4005// //   if( sync )
4006// //       this.commit( concept, URI, function(){
4007// //
4008// //           DataLayer.set( concept, URI, data, false );
4009// //
4010// //       });
4011// //     },
4012//     
4013// //     enqueue: function( type, concept, URI, obj ){
4014// //       
4015// //   //var newURI = this.URI( concept, URI );
4016// //   
4017// //   if( !this.queue[type] )
4018// //       this.queue[type] = {};
4019// //
4020// //   if( !this.queue['all'] )
4021// //       this.queue['all'] = {};
4022// //   
4023// //   if( !this.queue[type][concept] )
4024// //       this.queue[type][concept] = {};
4025// //   
4026// //   if( !this.queue['all'][type] )
4027// //       this.queue['all'][type] = {};
4028// //   
4029// //   if( !this.queue['all'][type][/*new*/URI] )
4030// //       this.queue[type][concept][URI] = this.queue['all'][type][/*new*/URI] = obj;
4031// //
4032// //   this.store( ':queue', this.queue );
4033// //     },
4034// //     
4035// //     dequeue: function( type, concept, URI, remove ){
4036// //       
4037// //       ///////////////////////////// normalize ////////////////////////////////
4038// //   if( arguments.length < 4 && $.type(URI) === 'boolean' )
4039// //   {
4040// //       remove = URI;
4041// //       URI = false;
4042// //   }
4043// //   if( arguments.length < 3 && $.type(concept) === 'boolean' )
4044// //   {
4045// //       remove = concept;
4046// //       concept = false;
4047// //   }
4048// //       //////////////////////////////////////////////////////////////////////////
4049// //       
4050// //   if( !this.queue[type] || !this.queue['all'] )
4051// //       return( false );
4052// //   
4053// //   if( !concept )
4054// //   {
4055// //       var obj = this.queue['all'][type];
4056// //       
4057// //       if( remove )
4058// //       {
4059// //           delete this.queue['all'][type];
4060// //           delete this.queue[type];
4061// //       }
4062// //
4063// //       this.store( ':queue', this.queue );
4064// //       return( obj );
4065// //   }
4066// //
4067// //   if( !this.queue[type][concept] )
4068// //       return( false );
4069// //   
4070// //   if( !URI )
4071// //   {
4072// //       var obj = this.queue[type][concept];
4073// //
4074// //       if( remove )
4075// //       {
4076// //           var URIs = this.queue[type][concept];
4077// //
4078// //           for( var subURI in URIs )
4079// //                delete this.queue['all'][type][subURI];
4080// //
4081// //           delete this.queue[type][concept];
4082// //       }
4083// //
4084// //       this.store( ':queue', this.queue );
4085// //       return( obj );
4086// //   }
4087// //
4088// // //        var newURI = URI ? this.URI( concept, URI ) : concept;
4089// //   
4090// //   var obj = this.queue['all'][type][/*new*/URI];
4091// //   
4092// //   if( remove )
4093// //   {
4094// //       delete this.queue['all'][type][/*new*/URI];
4095// //       delete this.queue[type][concept][URI];
4096// //   }
4097// //
4098// //   this.store( ':queue', this.queue );
4099// //   return( obj );
4100// //     },
4101//     
4102//            //TODO: definir a 'usage' desta função e refatora-la
4103// //     set: function( concept, filter, data, oneSide ){
4104// //
4105// //   ///////////////////////////// normalize ////////////////////////////////
4106// //   if( arguments.length == 2 )
4107// //   {
4108// //       data = filter;
4109// //       filter = false;
4110// //   }
4111// //   if( $.type(data) === "boolean" )
4112// //   {
4113// //       oneSide = data;
4114// //       data = filter;
4115// //       filter = false;
4116// //   }
4117// //   
4118// //   if( !concept || !data )
4119// //       return( false );
4120// //
4121// //   var decoder = "", URI = false, bothSides = (typeof oneSide === "undefined");
4122// //   
4123// //   if( $.type(filter) === "string" )
4124// //   {
4125// //       URI = filter;
4126// //       filter = false;
4127// //   }
4128// //
4129// //   if( res = internalUrl.exec( concept ) )
4130// //   {
4131// //       //TODO: verificar se a decodificaçao deve ser feita em cada item do array
4132// //       data = this.decode( concept, data );
4133// //       concept = res[1];
4134// //       decoder = res[2];
4135// //   }
4136// //   ///////////////////////////////////////////////////////////////////////////
4137// //
4138// //   if( bothSides || oneSide )
4139// //       this.report( concept, URI, data, !bothSides );
4140// //
4141// //   if( bothSides || !oneSide )
4142// //   {
4143// //       if( URI )
4144// //       {
4145// //         var helper = {};
4146// //         helper[URI] = data;
4147// //         data = helper;
4148// //       }
4149// //
4150// //       for( var URI in data )
4151// //       {
4152// //           var current = this.check( concept, URI ) || {};
4153// //
4154// //           data[URI] = this.merge( current, data[URI] );
4155// //
4156// //           this.store( concept, URI, data[URI] );
4157// //       }
4158// //
4159// //   }
4160// //
4161// //   this.broadcast( concept, oneSide ? 'client' : 'server' );
4162// //
4163// //   return( true );
4164// //     },
4165// //     put: function( concept, URI, data, oneSide ){
4166// //       
4167// //       ///////////////////////////// normalize ////////////////////////////////
4168// //   if( $.type(URI) !== "string" && arguments.length < 4 )
4169// //   {
4170// //       oneSide = data;
4171// //       data = URI;
4172// //       URI = false;
4173// //   }
4174// //       ////////////////////////////////////////////////////////////////////////
4175// //       
4176// //       ////////////////////////////// linkage /////////////////////////////////
4177// //   var result = false, links = this.links( concept );
4178// //
4179// //   for( var link in links )
4180// //   {
4181// //       if( data[link] )
4182// //       {
4183// //           if( $.isArray( data[link] ) )
4184// //           {
4185// //               data[link] = this.put( links[link], data[link].URI, data[link], oneSide );
4186// //           }
4187// //           else if( $.isObject( data[link] ) )
4188// //           {
4189// //               $.each( data[link], function( i, el ){
4190// //
4191// //                     data[link][i] = this.put( links[link], el.URI, el, oneSide );
4192// //
4193// //               });
4194// //           }
4195// //       }
4196// //   }
4197// //       //////////////////////////////////////////////////////////////////////////
4198// //     
4199// //   if( typeof data.URI === "undefined" )
4200// //   {
4201// //       URI = this.add( concept, data, oneSide );
4202// //   }
4203// //   else if( data.URI === false )
4204// //   {
4205// //       status = this.remove( concept, URI, oneSide );
4206// //   }
4207// //   else
4208// //   {
4209// //       status = this.set( concept, URI, data, oneSide );
4210// //   }
4211// //
4212// //   if( URI && data.URI && URI !== data.URI )
4213// //       this.move( concept, URI, data.URI );
4214// //
4215// //   return( data.URI || URI );
4216// //
4217// //     },
4218//     
4219//     //     add: function( concept, data, oneSide ){
4220// //       
4221// //       ///////////////////////////// normalize ////////////////////////////////
4222// //   if( !concept || !data )
4223// //       return( false );
4224// //
4225// //   if( res = internalUrl.exec( concept ) )
4226// //   {
4227// //       //TODO: verificar se a decodificaᅵᅵo deve ser feita em cada item do array
4228// //       data = this.decode( concept, data );
4229// //       concept = res[1];
4230// //       decoder = res[2];
4231// //   }
4232// //
4233// //   var bothSides = (typeof oneSide === "undefined"), uris = [];
4234// //
4235// //   if( notArray = $.type(data) !== "array" )
4236// //       data = [ data ];
4237// //       //////////////////////////////////////////////////////////////////////////
4238// //
4239// //   for( var i = 0; i < data.length; i++ )
4240// //   {
4241// //       var URI = uris[i] = this.generateURI( concept );
4242// //
4243// //       this.set( concept, URI, data[i], oneSide );
4244// //   }
4245// //
4246// //   return( notArray ? uris[0] : uris );
4247// //     },
4248// //      put: function( concept, data ){
4249// //
4250// //   var decoder = "";
4251// //
4252// //   if( res = internalUrl.exec( concept ) )
4253// //   {
4254// //       data = this.decode( concept, data );
4255// //       concept = res[1];
4256// //       decoder = res[2];
4257// //   }
4258// //
4259// //   var New = [], Update = [], uris = [];
4260// //
4261// //   if( notArray = $.type(data) !== "array" )
4262// //       data = [ data ];
4263// //   
4264// //   for( var i = 0; i < data.length; i++ )
4265// //   {
4266// //       if( !data[i].URI )
4267// //       {
4268// //           uris[ uris.length ] = data[i].URI = this.create( concept, data[i] );
4269// //           New[ New.length ] = data[i];
4270// //           continue;
4271// //       }
4272// //
4273// //       for( var key in data[i] )
4274// //           if( klass = this.isReference( concept, key, data[i][key] ) )
4275// //                 data[i][key] = this.put( klass + decoder, data[i][key] );
4276// //
4277// //       Update[ Update.length ] = this.update( concept, data[i].URI, data[i] );
4278// //   }
4279// //
4280// //   this.report( concept, { "created": New, "updated": Update });
4281// //
4282// //   return( notArray ? uris[0] : uris );
4283// //     },
4284// //     merge: function( concept, current, data ){
4285// //
4286// //   current = current || {};
4287// //
4288// //   for( var key in data )
4289// //       current[key] = (klass = this.isReference( concept, key, data[key] )) ?
4290// //                      this.merge( klass, current[key], data[key] ) : data[key];
4291// //
4292// //   return( current );
4293// //     },
4294// //
4295// //     isReference: function( concept, key, value ){
4296// //
4297// //       return( ($.type(value) === "object" ||
4298// //          $.type(value) === "array" )? this.links[concept][key] : false );
4299// //
4300// //     },
4301// //     
4302// //     set: function( concept, data, URI, mergeable ){
4303// //   
4304// //   if( URI )
4305// //   {
4306// //       var res = this.get( concept, true ) || {};
4307// //       
4308// //       if( mergeable )
4309// //           data = this.merge( res[URI] || {}, data );
4310// //
4311// //       res[URI] = data;
4312// //
4313// //       data = res;
4314// //   }
4315// //
4316// //   return this.store( concept, data );
4317// //     },   
4318// //
4319// //     create: function( concept, data ){
4320// //
4321// //       if( notArray = ($.type(data) !== "array") )
4322// //       data = [ data ];
4323// //
4324// //       var uris = [];
4325// //
4326// //       for( var i = 0; i < data.length; i++ )
4327// //       {
4328// //     uris[ uris.length ] = data[i].URI = "javascript://" + (this.counter + i);
4329// //
4330// //     this.set( concept, data[i], data[i].URI );
4331// //       }
4332// // 
4333// //       this.set( ":counter", (this.counter += data.length) );
4334// //
4335// //       return notArray ? uris[0] : uris;
4336// //     },
4337// //
4338// //     update: function( concept, URI, data )
4339// //     {
4340// //   var target = this.check( concept, URI ) || {};
4341// //
4342// //   target = this.merge( concept, target, data );
4343// //
4344// //   if( target.URI !== URI )
4345// //       this.remove( concept, URI );
4346// //
4347// //   this.set( concept, target, target.URI );
4348// //
4349// //   return( target );
4350// //     },
4351// //
4352// //     remove: function( concept, URI ){
4353// //
4354// //   if( !URI )
4355// //       return this.storage.del( concept );
4356// //
4357// //   var res = this.check( concept );
4358// //
4359// //   delete res[URI];
4360// //   
4361// //   this.set( concept, res );
4362// //     },
4363// //
4364// //     del: function( concept, URI ){
4365// //
4366// //   this.remove( concept, URI );
4367// //
4368// //   this.report( concept, { "deleted": { 'URI': URI } });
4369// //     },
4370// //
4371// //     report: function( concept, changes ){
4372// //
4373// //       this.broadcast( concept, changes.created, changes.updated, changes.deleted );
4374// //
4375// //   if( changes.created )
4376// //       this.sync( concept, changes.created, 'create' );
4377// //   if( changes.updated )
4378// //       this.sync( concept, changes.updated, 'update' );
4379// //   if( changes.deleted )
4380// //       this.sync( concept, changes.deleted, 'delete' );
4381// //
4382// //     },
4383// //
4384// //
4385// //    sync: function( concept, data, type ){
4386// //
4387// //   if( $.type(data) !== "array" )
4388// //       data = [ data ];
4389// //
4390// //   $.each( data, function( i, el ){
4391// //
4392// //      DataLayer.send( concept, el, type );
4393// //
4394// //   });
4395// //
4396// //     },
4397// //     
4398// //     
4399// //     
4400// //     
4401// //
4402// //     request: function( concept, URI, filter ){
4403// //
4404// // //       if( startsDoubleDot.test(concept) )
4405// // //          return( false );
4406// //
4407// //       filter = filter || {};
4408// //
4409// //       if( URI )
4410// //   filter.URI = URI;
4411// //
4412// //       return this.send( concept, filter, "read", true );
4413// //
4414// //     },
4415// //
4416// //     send: function( concept, data, type, wait ){
4417// //
4418// //       switch( type )
4419// //       {
4420// //   case "create": type = "POST"; break;
4421// //   case "update": type = "PUT"; break;
4422// //   case "delete": type = "DELETE"; break;
4423// //   case "read": type = "GET"; break;
4424// //       }
4425// //
4426// //       var url = this.basePath + concept;
4427// //
4428// //       var result = [], notArray = false;
4429// //
4430// // //      alert( data.URI );
4431// //
4432// //       if( data.URI && data.URI.indexOf("javascript://") !== 0 )
4433// //     url += "/" + data.URI;
4434// //
4435// //       var callback = function( dt, textStatus, jqXHR ){
4436// //
4437// //       if( notArray = (!$.isArray( dt )) )
4438// //           dt = [ dt ];
4439// //
4440// //       $.each( dt, function( i, el ){
4441// //
4442// //           if( !el || !el.URI )
4443// //               return;
4444// //
4445// //           if( data.URI )
4446// //               el = DataLayer.update( concept, data.URI, el );
4447// //           else
4448// //               DataLayer.set( concept, el, el.URI );
4449// //
4450// //           result[ result.length ] = el;
4451// //           DataLayer.broadcast( concept );
4452// //     });
4453// //       };
4454// //
4455// //       $.ajax({
4456// //         'async': ( !wait ),
4457// //         'url': url,
4458// //         'type': type,
4459// //         'success': callback,
4460// //         'dataType': 'json',
4461// //         'data': data/*,
4462// //         'processData': false*/
4463// //     });
4464// //
4465// //       return( notArray ? result[0] || false : result );
4466// //     },
4467//     
4468//     
4469//     generateURI: function( concept ){
4470//       
4471//      return this.URI( concept, this.generateId( concept ), "javascript" );
4472//
4473//     },
4474//     
4475//
4476//     broadcast: function( concept, status, diff ){
4477//
4478//      if( this.listeners[ concept ] )
4479//          for( var i = 0;
4480//              i < this.listeners[ concept ].length;
4481//              this.listeners[ concept ][ i++ ]( status, diff ) );
4482//     },
4483//
4484//     listen: function( concept, listener ){
4485//
4486//      this.register( "listeners", concept, listener );
4487//
4488//     },
4489//
4490//     codec: function( concept, namespace, codec ){
4491//
4492//      if( codec.encoder )
4493//          this.encoder( concept, namespace, codec.encoder );
4494//      if( codec.decoder )
4495//          this.decoder( concept, namespace, codec.decoder );
4496//      if( codec.criteria )
4497//          this.register( "criterias", concept + ":" + namespace, codec.criteria );
4498//
4499//     },
4500//
4501//     encoder: function( concept, namespace, encoder ){
4502//
4503//      this.register( "encoders", concept + ":" + namespace, encoder );
4504//
4505//     },
4506//
4507//     encode: function( encoder, data, filter ){
4508//
4509//      if( this.encoders[ encoder ] )
4510//          for( var i = 0;
4511//              i < this.encoders[ encoder ].length;
4512//              data = this.encoders[ encoder ][ i++ ]( data, filter ) );
4513//
4514//      return( data );
4515//     },
4516//
4517//     decoder: function( concept, namespace, decoder ){
4518//
4519//      this.register( "decoders", concept + ":" + namespace, decoder );
4520//
4521//     },
4522//
4523//     decode: function( decoder, data ){
4524//
4525//      if( this.decoders[ decoder ] )
4526//          for( var i = 0;
4527//              i < this.decoders[ decoder ].length;
4528//              data = this.decoders[ decoder ][ i++ ]( data ) );
4529//
4530//      return( data );
4531//     },
4532//
4533//     criteria: function( codec, filter ){
4534//
4535//      if( this.criterias[ codec ] )
4536//          for( var i = 0;
4537//              i < this.criterias[ codec ].length;
4538//              filter = this.criterias[ codec ][ i++ ]( filter ) );
4539//
4540//      return( filter );
4541//
4542//     },
4543//
4544//     register: function( kind, concept, deployable ){
4545//
4546//       if( arguments.length < 3 )
4547//       {
4548//        deployable = concept;
4549//        concept = kind;
4550//        kind = 'global';
4551//       }
4552//
4553//       if( !this[ kind ][ concept ] )
4554//          this[ kind ][ concept ] = [];
4555//
4556//      this[ kind ][ concept ][ this[ kind ][ concept ].length ] = deployable;
4557//
4558//     },
4559//     
4560//     start: function(){
4561//
4562//      var timer = function(){
4563//
4564//            setTimeout( timer, 1 );
4565//
4566//            var now = parseInt( $.now() / 1000 );
4567//
4568//            var tasks = DataLayer.tasks[ now ];
4569//
4570//            if( !tasks ) return;
4571//
4572//            for( var i = 0; i < tasks.length; i++ )
4573//            {
4574//                var result = tasks[i].task( now );
4575//
4576//                if( tasks[i].factor )
4577//                DataLayer.schedule( tasks[i].task, tasks[i].factor );
4578//            }
4579//       
4580//            delete DataLayer.tasks[ now ];
4581//      };
4582//
4583//      setTimeout( timer, 1 );
4584//     },
4585//     
4586//     task: function( timestamp, task, factor )
4587//     {
4588//      if( !this.tasks[ timestamp ] )
4589//          this.tasks[ timestamp ] = [];
4590//
4591//      this.tasks[ timestamp ][ this.tasks[ timestamp ].length ] = { task: task, factor: factor || false };
4592//     },
4593//
4594//     schedule: function( task, time ){
4595//
4596//      time = time || 1;
4597//     
4598//      var index = parseInt( $.now() / 1000 ) + time;
4599//
4600//      this.task( index, task, time );
4601//     },
4602//     
4603//     poll: function( concept, time ){
4604//       
4605//       this.schedule( function( now ){
4606//   
4607//        DataLayer.commit( concept );
4608//
4609//      }, time || 5 );
4610//     },
4611//     
4612//     init: function(){
4613//       
4614//      this.counter = parseInt( this.get( ":counter", false ) ) || 0;
4615//
4616//      if( !this.dispatchPath )
4617//          this.dispatchPath = "../../";
4618//
4619//      if( !this.templatePath )
4620//          this.templatePath = "";
4621//
4622//      if( !this.basePath )
4623//          this.basePath = this.dispatchPath + "REST.php?q=";
4624//
4625//      this.schedule( function( now ){
4626//
4627//          DataLayer.flush();
4628//
4629//      });
4630//
4631//      this.start();
4632//     }
4633// }
4634//
4635// // the re-usable constructor function used by clone().
4636// function Clone() {}
4637//
4638// //Recursion Helper
4639// function RecursionHelper(){ this.clear(); };
4640//
4641// RecursionHelper.prototype = {
4642//   
4643//      constructor: RecursionHelper,
4644//
4645//      // copiedObjects keeps track of objects already copied by this
4646//      // deepCopy operation, so we can correctly handle cyclic references.
4647//      copiedObjects: [],
4648//
4649//      depth: 0,
4650//
4651//      maxDepth: 256,
4652//
4653//      //reset the recursion helper cache
4654//      clear: function(){
4655//              this.copiedObjects = [];
4656//              this.depth = 0;
4657//      },
4658//
4659//      // add an object to the cache.  No attempt is made to filter duplicates;
4660//      // we always check getCachedResult() before calling it.
4661//      cacheResult: function(source, result) {
4662//              this.copiedObjects.push([source, result]);
4663//      },
4664//
4665//      // Returns the cached copy of a given object, or undefined if it's an
4666//      // object we haven't seen before.
4667//      getCachedResult: function(source) {
4668//
4669//              for ( var i=0; i<this.copiedObjects.length; i++ ) {
4670//                      if ( this.copiedObjects[i][0] === source ) {
4671//                              return this.copiedObjects[i][1];
4672//                      }
4673//              }
4674//
4675//              return undefined;
4676//      }
4677// };
4678//
4679// // Generic Object copier
4680// // the ultimate fallback DeepCopier, which tries to handle the generic case.  This
4681// // should work for base Objects and many user-defined classes.
4682// DataLayer.registerComparator({
4683//      can: function(source) { return true; },
4684//
4685//      create: function(source) {
4686//              if ( source instanceof source.constructor ) {
4687//                      return DataLayer.clone(source.constructor.prototype);
4688//              } else {
4689//                      return {};
4690//              }
4691//      },
4692//
4693//      populate: function(deepCopy, source, result) {
4694//              for ( var key in source ) {
4695//                      if ( source.hasOwnProperty(key) ) {
4696//                              result[key] = deepCopy(source[key], result[key]);
4697//                      }
4698//              }
4699//              return result;
4700//      }
4701// });
4702//
4703// // Array copier
4704// DataLayer.registerComparator({
4705//      can: function(source) {
4706//              return ( source instanceof Array );
4707//      },
4708//
4709//      create: function(source) {
4710//              return new source.constructor();
4711//      },
4712//
4713//      populate: function(deepCopy, source, result) {
4714//              for ( var i=0; i<source.length; i++) {
4715//                      result.push( deepCopy(source[i], result[i]) );
4716//              }
4717//              result =  DataLayer.unique( result )
4718//              return result;
4719//      }
4720// });
4721//
4722// // Date copier
4723// DataLayer.registerComparator({
4724//      can: function(source) {
4725//              return ( source instanceof Date );
4726//      },
4727//
4728//      create: function(source) {
4729//              return new Date(source);
4730//      }
4731// });
4732//
4733// // HTML DOM Node copier
4734// DataLayer.registerComparator({
4735//
4736//      // function to detect Nodes.  In particular, we're looking
4737//      // for the cloneNode method.  The global document is also defined to
4738//      // be a Node, but is a special case in many ways.
4739//      can: function(source) {
4740//       
4741//        if ( window.Node ) {
4742//                return source instanceof Node;
4743//        } else {
4744//                // the document is a special Node and doesn't have many of
4745//                // the common properties so we use an identity check instead.
4746//                if ( source === document ) return true;
4747//                return (
4748//                        typeof source.nodeType === 'number' &&
4749//                        source.attributes &&
4750//                        source.childNodes &&
4751//                        source.cloneNode
4752//                );
4753//        }
4754//       },
4755//
4756//       create: function(source) {
4757//            // there can only be one (document).
4758//            if ( source === document ) return document;
4759//
4760//            // start with a shallow copy.  We'll handle the deep copy of
4761//            // its children ourselves.
4762//            return source.cloneNode(false);
4763//       },
4764//       
4765//       diff: function(base, source){
4766//     
4767//       },
4768//
4769//       populate: function(deepCopy, source, result) {
4770//            // we're not copying the global document, so don't have to populate it either.
4771//            if ( source === document ) return document;
4772//
4773//            // if this Node has children, deep copy them one-by-one.
4774//            if ( source.childNodes && source.childNodes.length ) {
4775//                    for ( var i=0; i<source.childNodes.length; i++ ) {
4776//                            var childCopy = deepCopy(source.childNodes[i], result.childNodes[i] || false );
4777//                            result.appendChild(childCopy);
4778//                    }
4779//            }
4780//              return result;
4781//       }
4782// });
4783//
4784// DataLayer.init();
4785//
4786// // setTimeout(function(){
4787// // 
4788// //     
4789// //
4790// // }, 1000 );
4791//
4792// // var DataLayer = {
4793// //
4794// //     get: function( concept, filter ){
4795// //
4796// //   var data = this.storage.get( concept );
4797// //
4798// //   if( !filter )
4799// //       return( data );
4800// //
4801// //   return this.filter( data, filter );
4802// //     },
4803// //     
4804// //     filter:function( data, filter ){
4805// //       
4806// //   if( filter.charAt )
4807// //       filter = { URI: filter };
4808// //   
4809// //   var filtered = [];
4810// //
4811// //   $.each(data, function(i, obj){
4812// //     
4813// //       for( var attr in filter )
4814// //           if( filter[attr] !== obj[attr] )
4815// //               return( true );
4816// //
4817// //       filtered[i] = obj;
4818// //   });
4819// //
4820// //   return( filtered );
4821// //     },
4822// //
4823// //     find: function( concept, filter, callback ){
4824// //
4825// //   var data = this.get( concept, filter );
4826// //
4827// //   if( data )
4828// //       return callback( data );
4829// //
4830// //   //TODO: register callback like a weak listener
4831// //
4832// // //        $.ajax({
4833// // //              type: 'GET',
4834// // //              data: $.param( filter ),
4835// // //              success: callback, 
4836// // //              url: BASE_PATH + filter.URI || concept
4837// // //        });
4838// //   this.report( concept, filter );
4839// //     },
4840// //
4841// //     put: function( concept, data, filter ){
4842// //
4843// //   var beforeDiff = this.store( concept, $.extend({},data) );
4844// //
4845// //   this.report( concept, data, filter, beforeDiff );
4846// //     },
4847// //     
4848// //     
4849// //     /*var data = {
4850// //                   startTime: $.now(),
4851// //                   endTime: $.now() + 1800000,
4852// //                   summary: "meu querido evento",
4853// //                   description: "desc do evento",
4854// //                   location: "prognus software livre",
4855// //                   class: 1,
4856// //                   calendar: 1,
4857// //                   category: 1,
4858// //                   participants: [ {
4859// //                                      user: { isExternal: true, mail: "user7@prognus.org", name: "user7" }
4860// //                                 },{
4861// //                                      user: "1003"
4862// //                                 } ]
4863// //
4864// //             };*/
4865// //     
4866// //
4867// //     merge:function( data, target ){
4868// //       
4869// //   var diff = { New: {}, Update:{}, Delete: {} };
4870// //       
4871// //   for( var key in data )
4872// //   {
4873// //       if( !target[ key ] )
4874// //           diff.New[ key ] = target[ key ] = data[ key ];
4875// //
4876// //       
4877// //     
4878// //   }
4879// //       
4880// //     }
4881// //
4882// //     store: function( concept, data, filter ){
4883// //
4884// //   if( !data.spline )
4885// //       data = [ data ];
4886// //
4887// //   var target = this.storage.get( concept );
4888// //   
4889// //   var diff = { New: {}, Update:{}, Delete: {} };
4890// //
4891// //   for( var i = 0; i < data.length; i++ )
4892// //   {
4893// //       if( data[i].URI && target[ data[i].URI ] )
4894// //       {
4895// //           diff.Update[ data[i].URI ] = this.merge( target[ data[i].URI ], data[i] );
4896// //       }
4897// //       else
4898// //       {
4899// //           diff.New[] = data[i];
4900// //       }
4901// //   }
4902// //
4903// //   
4904// //
4905// //   this.broadcast( concept, data );
4906// //
4907// //   if( filter )
4908// //       target = this.filter( target, filter );
4909// //
4910// //   if( target )
4911// //       data = $.extend( target, data );
4912// //
4913// //   this.storage.set( concept, data );
4914// //
4915// // //        return;
4916// //     },
4917// //     
4918// //     set: function( concept, data, filter ){
4919// //
4920// //       
4921// //
4922// //     },
4923// //
4924// //     post: function( concept, data, filter, isNew ){
4925// //
4926// //   var callback = function(  ){ DataLayer.store( concept, data, filter ) };
4927// //
4928// //   //TODO: register callback like a weak listener
4929// //
4930// //   this.report( concept, data, filter, isNew );
4931// //     },
4932// //     
4933// //     report: function( concept, filter, postData, isNew ){
4934// //       
4935// //   $.ajax({
4936// //           type: postData ? isNew ? 'POST' : 'PUT' : 'GET',
4937// //           data: postData || $.param( filter ),
4938// //           success: function( data ){ DataLayer.broadcast( concept ) },
4939// //           url: BASE_PATH + filter.URI || concept
4940// //     });
4941// //     },
4942// //     
4943// //     del:function( concept, filter ){
4944// //
4945// //       
4946// //
4947// //     }
4948// //     
4949// //     broadcast: function( concept, data ){
4950// //
4951// //   
4952// //
4953// //     },
4954// //
4955// //     pool: function(){
4956// //       
4957// //     },
4958// //
4959// //     refresh: function(){
4960// //       
4961// //     }
4962// // };
4963//
4964// //
4965// // DataLayer = {
4966// //   
4967// //     get: function( concept, filter ){
4968// //
4969// //   var data = this.storage.get( concept );
4970// //
4971// //   if( !filter )
4972// //       return( data );
4973// //
4974// //   if( filter.charAt )
4975// //       filter = { URI: filter };
4976// //   
4977// //   var filtered = [];
4978// //
4979// //   $.each(data, function(i, obj){
4980// //     
4981// //       for( var attr in filter )
4982// //           if( filter[attr] !== obj[attr] )
4983// //               return( true );
4984// //
4985// //       filtered[i] = obj;
4986// //   });
4987// //
4988// //   return( filtered );
4989// //     },
4990// //
4991// //     find: function( concept, filter, callback ){
4992// //
4993// //   var data = this.get( concept, filter );
4994// //
4995// //   if( data )
4996// //       return callback( data );
4997// //
4998// //    $.ajax({
4999// //         type: 'GET',
5000// //         data: $.param( filter ),
5001// //         success: callback, 
5002// //         url: filter.URI || concept
5003// //   });
5004// //     },
5005// //
5006// //     put: function( concept, data, filter ){
5007// //
5008// //   var target = this.get( concept, filter );
5009// //
5010// //   if( target )
5011// //       data = $.extend( target, data );
5012// //       
5013// //   this.storage.set( concept, data );
5014// //   
5015// //   //diff
5016// //     },
5017// //     
5018// //     post: function( concept, data, filter ){
5019// //
5020// //   
5021// //
5022// //     },
5023// //     
5024// //     pool: function(){
5025// //       
5026// //     },
5027// //     
5028// //     queue: function(){
5029// //       
5030// //     },
5031// //     
5032// //     dequeue: function(){
5033// //       
5034// //     },
5035// //     
5036// //     refresh: function(){
5037// //       
5038// //     }
5039// // }
5040//
5041// // var DataLayer = {
5042//   
5043// //       cache: {},
5044//   
5045// //       get: function( concept, location ){
5046//     
5047//         /* if( location )
5048//          {*/
5049// //           var schema = $.data( this.cache, concept + ':schema' );
5050// //           var uri = [];
5051// //
5052// //           $.each( schema, function( i, addrs ){
5053// //                 uri[ uri.length ] = location[addrs];
5054// //           });
5055//
5056//              /*var filter = [], result = false;
5057//
5058//              while( !(result = $.data( this.cache, uri.join( '.' ) )) || !(uri = uri.join('.')) )
5059//                filter[ filter.length ] = uri.pop();
5060//   
5061//              if( !filter.length )
5062//              {
5063//                  var indexes = $.data( this.cache, uri + ':indexes' );
5064//
5065//                  if( indexes )
5066//                      Array.prototype.concat.apply( result, indexes );
5067//                 
5068//                  return( result );
5069//              }
5070//
5071//              for( var i = 0; i < result.length; i++ )
5072//              {
5073//                 
5074//              }
5075//
5076//              if( result.length )
5077//                  return( result );
5078//          }*/
5079//
5080// //       var data = $.data( this.cache, concept );
5081//
5082// //       if( !data )
5083// //           $.ajax( );
5084//
5085// //       return( data );
5086// //       },
5087//       
5088// //       data: function(){
5089// //
5090// //     
5091// //
5092// //       }
5093// //       
5094// //       search: function( concept, filter ){
5095// //
5096// //     var schema = $.data( this.cache, concept + ':schema' );
5097// //     var uri = [];
5098// //
5099// //     $.each( schema, function( i, addrs ){
5100// //           uri[ uri.length ] = location[addrs];
5101// //     });
5102// //       }
5103// //       put: function( concept, data, location ){
5104//
5105// //       if( location )
5106// //       {
5107// //           var schema = $.data( this.cache, concept + ':schema');
5108// //           var uri = [];
5109//
5110// //           $.each( schema, function( i, addrs ){
5111// //                 uri[ uri.length ] = location[addrs];
5112// //           });
5113//
5114// //           var result = false, filter = [];
5115//
5116// //           while( !(result = $.data( this.cache, uri.join('.')) )
5117// //               filter[ filter.length ] = uri.pop();
5118//
5119// //           $.data( this.cache, '
5120//
5121// //       }
5122//
5123// //           var model = this.storage.get( concept );
5124// //
5125// //           $.each( model, function( i, o ){
5126// //               $.each( location, function( ii, attr ){
5127// //                    if( o[ii] === attr )
5128// //                       return( false );
5129// //               });
5130// //           });
5131//
5132// //       return $.data( this.cache, concept, data );
5133//
5134// //       },
5135// //       del: function( concept, location ){
5136// //
5137// //       if( location )
5138// //       {
5139// //           var schema = $.data( this.cache, 'concepts', concept );
5140// //           var uri = [];
5141// //
5142// //           $.each( schema, function( i, addrs ){
5143// //                 uri[ uri.length ] = location[addrs];
5144// //           });
5145// //
5146// //           concept = uri.join( '.' );
5147//
5148// //           var model = this.storage.get( concept );
5149// //
5150// //           $.each( model, function( i, o ){
5151// //               $.each( location, function( ii, attr ){
5152// //                    if( o[ii] === attr )
5153// //                       return( false );
5154// //               });
5155// //           });
5156// //       }
5157// //       
5158// //   
5159// //       $.removeData( this.cache, concept );
5160// //       }
5161// // }
Note: See TracBrowser for help on using the repository browser.