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

Revision 6351, 127.8 KB checked in by gustavo, 12 years ago (diff)

Ticket #2768 - Melhorias na inserção de destinatários na criacao de mensagem

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