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

Revision 6361, 128.3 KB checked in by gustavo, 12 years ago (diff)

Ticket #2768 - Melhorias na criação de mensagens

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