= Manual para desenvolvedores do pSync = [[PageOutline(1-3, Conteúdo)]] O pSync foi totalmente baseado no Foundation, um connector de exemplo disponibilizado pelo Funambol. == Estrutura == Para compilação e geração do plugin pelo ant (http://ant.apache.org): * '''/build''': Estão os ant-files responsáveis pela "compilação" do plugin; * '''/lib''': Estão as bibliotecas necessárias para a "compilação" do plugin; Para compilação e geração do plugin pelo maven (http://maven.apache.org): * '''pom.xml''': O arquivo que contém as propriedades do projeto Obs: No maven é melhor gerenciado as dependências do projeto, pois permite uso de vários repositórios não dependendo da pasta lib, permite controle das versões, assim como muitas outras integrações que o maven permite, como criar um projeto no Eclipse. Gera o plugin, sem precisar de IDE, na pasta target que o maven cria. O módulo está dividido em vários diretórios: * '''/src''': O código fonte do plugin; * '''/src/main/java/br/com/prognus/psync/''': Dentro desse diretório devem estar os seguintes pacotes: * admin: São os códigos da interface gráfica, utilizadas na ferramenta de administração do Funambol. Por meio destas é possível criar os !SyncSources utilizados pelos clientes (dispositivos); * engine/source: Estão as classes que serão invocadas pelo servidor e que são responsáveis pelo tratamento dos dados a serem sincronizados. Dentro de ''engine'' ficam os demais pacotes e classes utilizados pelas classes que estão dentro de ''source''; * '''/src/main/sql''': Estão contidos os scripts de inicialização dos banco de dados, tanto para o Expresso quanto para o Funambol. Os scripts de cada banco devem estar separados em diretórios com o nome do banco usado; * '''/src/main/config''': Estão contidos os scripts de configuração utilizados pelo Funambol para injeção de valores nos atributos; Foi convencionado que os arquivos desses diretórios sejam nomeados da seguinte forma: Para as interfaces gráficas: * '''!SyncSourceConfigPanel.java'''; Para os sources: * '''!SyncSource.java'''; Para os scripts: * '''create_engine.sql'''; * '''drop_engine.sql'''; * '''init_engine.sql'''; As classes ''!SyncSourceConfigPanel'' derivam do pacote ''funambol-admin'', neste pacote encontram-se as classes usadas na criação da interface de configuração do módulo. As classes ''!SyncSource'' derivam do pacote ''funambol-framework'', neste pacote encontram-se as classes necessárias para manipular os dados durante a sincronia. == funambol.framework == Este pacote contém os serviços e abstrações usadas em diferentes camadas para implementar o componente. Os serviços mais importantes fornecidos pelo framework são: * '''core''': Classes usadas para fazer a tradução de XML para uma arvore de objetos e de uma arvore de objetos para XML; * '''protocol''': A comunicação SyncML é uma seqüencia de mensagens correlacionadas seguindo regras adicionais especificadas pelo protocolo SyncML. Este pacote processas as mensagens para assegurar a consistência com o protocolo; * '''logging''' e '''security''': Implementam os serviços de log segurança; * '''engine''': Provê a lógica para o servidor de sincronização, incluindo: * Identificar a fonte e o destino dos dados a serem sincronizados; * Identificar que dados precisam ser atualizados, adicionados ou removidos; * Determinar quantas atualizações devem ser feitas; * Detectar e resolver conflitos; == !SyncSourceConfigPanel.java == Classes responsáveis pela interface para o gerenciamento das configurações dos !SyncSources.[[br]] Os !SyncSources são os arquivos de configuração responsáveis por indicar quais tabelas serão sincronizadas, os tipos de sincronia permitidos e outras informações. === !SyncSource.java === Essas classes são responsáveis por manipular os dados a serem sincronizados, são as classes que fazem a interface entre o servidor Funambol e o banco de dados. == Mapeamento das informações no Expresso Livre == Este wiki tem como finalidade fazer um mapeamento mais detalhado das tabelas utilizadas para armazenar contatos e eventos no banco de dados do Expresso Livre. === Contatos === Os dados dos contatos estão dividos em 25 tabelas, mas em 2 tabelas se encontram todos os dados necessários para o contato. Os dados que poderão ser utilizados no padrão [http://www.w3.org/2002/12/cal/rfc2426 vCard] são os seguintes: Tabela: '''phpgw_cc_contact''' ||'''Campo'''||'''Tipo'''||'''Descrição'''|| ||id_contact||int8('''''NOT NULL''''')[pk]||Numero de identificação do contato.|| ||id_owner||int8('''''NOT NULL''''')||Numero de identificação do dono do contato.|| ||id_status||int4||Numero de identificação para contato completo ou simples.|| ||photo||bytea||Valor binário da imagem de exibição do contato.|| ||alias||varchar(30)||Guarda o nome de exibição do contato.|| ||id_prefix||int4||NULL ( Nenhum dos exemplos criados chegaram a ocupar esse espaço)|| ||given_names||varchar(100)||Guarda o primeiro nome do contato.|| ||family_names||varchar(100)||Guarda o sobre-nome do contato.|| ||names_ordered||varchar(100)||Guarda o nome completo do contato.|| ||id_suffix||int4||NULL ( Nenhum dos exemplos criados chegaram a ocupar esse espaço)|| ||birthdate||date||Guarda a data de aniversário do contato.|| ||sex||char(1)||Caracter que indentifica o sexo do contato.(nenhum dos exemplos ocupou esse campo, nem havia onde registrar-lo)|| ||pgp_key||text||Chave publica pgp do contato para criptografia das mensagens.|| ||notes||text||Notas sobre o contato.|| ||is_global||bool||Flag que define se o contato é publico ou privado.|| ---- Tabela: '''phpgw_cc_connections''' ||'''Campo'''||'''Tipo'''||'''Descrição'''|| ||id_connection||int8('''''NOT NULL''''')[pk]||Numero de identificação da ligação com o contato|| ||connection_name||varchar(50)||Guarda o nome do endereço de e-mail ou telefone do contato.[[BR]]Principal : Para o e-mail principal do contato[[BR]]Alternativo : para o e-mail alternativo do contato[[BR]]Residencial : Para o telefone Residencial do contato[[BR]]Celular : Para o telefone Celular do contato[[BR]]Comercial : Para o telefone Comercial do contato[[BR]]Fax : Para o telefone Fax do contato[[BR]]Pager : Para o telefone Pager do contato|| ||connection_value||varchar(50)||Guarda o valor do e-mail ou telefone do contato.|| ||connection_is_default||bool||Define se o endereço ou e-mail é o padrão do contato.|| ---- Tabela: '''phpgw_cc_addresses''' ||'''Campo'''||'''Tipo'''||'''Descrição'''|| ||id_address||int8('''''NOT NULL''''')[pk]||Numero de identificação do endereço|| ||id_city||int8||Numero de identificação da cidade|| ||id_state||int8||Numero de identificação do estado|| ||id_country||bpchar(2)('''''NOT NULL''''')||Numero de identificação do pais|| ||address1||varchar(60)||Endereço principal|| ||address2||varchar(60)||Endereço secundário|| ||complement||varchar(30)||Complemento|| ||address_other||varchar(60)||Outro endereço|| ||postal_code||varchar(15)||CEP|| ||po_box||varchar(30)||Caixa Postal|| ||address_is_default||boolean||Endereço é padrão?|| ---- As tabelas '''phpgw_cc_contact''' e '''phpgw_cc_connections''' estão ligadas num relacionamento de 1/N através dessa tabela:[[BR]] Tabela: '''phpgw_cc_contact_conns''' ||'''Campo'''||'''Tipo'''||'''Descrição'''|| ||id_contact||int8[pk]||Guarda a identificação do contato|| ||id_connection||int8[pk]||Guarda a identificação da conexão do contato|| ||id_typeof_contact_connection||int4||Guarda o tipo de conexao com o contato:[[BR]]1: Para e-mail[[BR]]2: Para Telefone|| ---- As tabelas '''phpgw_cc_contact''' e '''phpgw_cc_addresses''' estão ligadas num relacionamento de 1/N através dessa tabela:[[BR]] Tabela: '''phpgw_cc_contact_addrs''' ||'''Campo'''||'''Tipo'''||'''Descrição'''|| ||id_contact||int8[pk]||Numero de identificação do contato|| ||id_address||int8[pk]||Numero de identificação do endereço|| ||id_typeof_contact_address||int4||Numero de identificação do tipo de endereço:[[BR]]1 : Para endereço comercial[[BR]]2 : Para endereço residencial|| ---- === Calendário === Os dados do calendário estão divididos em 5 tabelas, mas em 2 tabelas podem ser encontradas todas as informações relativas aos eventos. Tabela: '''phpgw_cal''' ||'''Campo'''||'''Tipo'''||'''Descrição'''|| ||cal_id||int4('''''NOT NULL''''')[pk]||Numero de identificação do evento.[[BR]]O valor padrão é dado pela seqüencia ''nextval(('seq_phpgw_cal'::text)::regclass)''|| ||uid||varchar(255)('''''NOT NULL''''')||Guarda o dominio onde o usuario está inserido ( ex. -@servidor.com.br , joao@servidor.com.br )|| ||owner||int8('''''NOT NULL''''')||Numero de identificação do dono do evento|| ||category||varchar(30)||Define se o evento está em alguma categoria.[[BR]]1 : Para evento com categoria[[BR]]' ': Para evento sem categoria|| ||groups||varchar(255)||NULL (todos os eventos que foram criados ficaram com esse valor)|| ||datetime||int8||Guarda, em microtime, a data e hora em que o evento irá acontecer.|| ||mdatetime||int8||Guarda, em microtime, a data e hora em que o evento foi criado.|| ||edatetime||int8||Guarda, em microtime, a data e hora em que o evento irá terminar.|| ||priority||int8('''''NOT NULL''''')||Define a prioridade do evento.[[BR]]0 : Para evento sem prioridade[[BR]]1 : Para evento com prioridade baixa[[BR]]2 : Para evento com prioridade média[[BR]]3 : Para evento com prioridade alta|| ||cal_type||varchar(10)||Define se o evento será repetido.[[BR]]E : Para evento unico[[BR]]M : Para evento com repetição|| ||is_public||int8('''''NOT NULL''''')||Define se o evento será publico.[[BR]]0 : Para evento particular[[BR]]1 : Para evento público|| ||title||varchar(80)('''''NOT NULL''''')||Guarda o titulo do evento.|| ||description||text||Guarda a descrição do evento.|| ||location||varchar(255)||Guarda o local onde o evento irá ocorrer.|| ||reference||int8('''''NOT NULL''''')||Quando um evento de um evento recursivo é editado, esse campo recebe o cal_id referente ao evento que foi editado.|| ||ex_participants||text||Guarda os e-mails dos participantes que não estão em nenhum grupo.[[BR]]Os participantes estão separados por virgulas.|| ---- Essas tabelas tem um relacionamento de 1/1, onde o campo ''cal_type'' deve estar com o valor '''m''' para que haja uma entrada na tabela abaixo.[[BR]] Tabela: '''phpgw_cal_repeats''' ||'''Campo'''||'''Tipo'''||'''Descrição'''|| ||cal_id||int8('''''NOT NULL''''')||Numero de identificação do evento.|| ||recur_type||varchar(30)('''''NOT NULL''''')||Define o tipo de repetição do evento.[[BR]]1 : Para evento diário[[BR]]2 : Para evento semanal[[BR]]4 : Para evento mensal por dia[[BR]]3 : Para evento mensal por data[[BR]]5 : Para evento anual|| ||recur_use_end||int8||0 (Todos os eventos ficaram com esse valor)|| ||recur_enddate||int8||Guarda, em microtime, a data em que a repetição do evento irá terminar.|| ||recur_interval||int8||Guarda o intervalo em que o evento ira ocorrer. [[BR]] 0 : Para um evento unico [[BR]] 1 : Para um evento diario ou semanal ou mensal ( passo de 1 ) [[BR]] 2 : Para eventos a cada 2 dias, 2 semanas 2 meses [[BR]] e assim por diante.|| ||recur_data||int8||Guarda quais dias da semana o evento irá acontecer, a somatória desses valores indicará os dias que foram marcados[[BR]]1 : Domingo[[BR]]2 : Segunda[[BR]]4 : Terça[[BR]]8 : Quarta[[BR]]16 : Quinta[[BR]]32 : Sexta[[BR]]64 : Sabado[[BR]](Ex.: 42 = Segunda(2), Quarta(8) e Sexta(32))|| ||recur_exception||varchar(255)||Guarda, em microtime, os dias em que não haverá o evento.[[BR]]Esses dias são separados por virgula.|| ---- O evento somente será exibido se houver uma entrada nesta tabela indicando a ''ID'' do evento e a ''ID'' do dono. Tabela: '''phpgw_cal_user''' ||'''Campo'''||'''Tipo'''||'''Descrição'''|| ||cal_id||int8('''''NOT NULL''''')||Numero de identificação do evento.|| ||cal_login||int8('''''NOT NULL''''')||Numero de identificação do dono do evento.|| ||cal_status||char(1)||Define se o usuário aceitou ou não participar do evento.[[BR]]A : Se aceitou participar[[BR]]U : Se não aceitou participar|| ||cal_type||varchar(1)('''''NOT NULL''''')||Guarda algum tipo de informação que ainda não foi possível descobrir|| == Alterações no código e banco de dados do Expresso Livre == Como a solução já está em produção há um bom tempo, as alterações já fazem parte do código do Expresso Livre. De qualquer forma, as alterações do contactcenter estão descritas no ticket #150 e revisão [203], juntamente com outras alterações de internacionalização. Já as alterações do calendar não estão registradas no svn, mas como são poucas alterações, vou colocá-las aqui mesmo: {{{ diff -Naur old/calendar/inc/class.socalendar_sql.inc.php new/calendar/inc/class.socalendar_sql.inc.php --- old/calendar/inc/class.socalendar_sql.inc.php 2007-03-22 16:58:17.000000000 -0300 +++ new/calendar/inc/class.socalendar_sql.inc.php 2007-10-02 17:12:09.000000000 -0300 @@ -606,6 +606,7 @@ . "',".(int)$event['owner'].','.(int)$event['priority'].','.(int)$event['public'].",'" . $event['category']."')",__LINE__,__FILE__); $event['id'] = $this->stream->get_last_insert_id('phpgw_cal','cal_id'); + $last_status = true; } $date = $this->maketime($event['start']) - $GLOBALS['phpgw']->datetime->tz_offset; @@ -636,6 +637,7 @@ . "location='".$this->stream->db_addslashes($event['location'])."', " . ($event['groups']?"groups='".(count($event['groups'])>1?implode(',',$event['groups']):','.$event['groups'][0].',')."', ":'') . 'reference='.(int)$event['reference'].' ' + . ',last_status = '.($last_status ? "'N'" : "'U'").',last_update = '.time()."000". ' ' . 'WHERE cal_id='.(int)$event['id']; $this->stream->query($sql,__LINE__,__FILE__); }}} Quanto ao banco de dados, foi necessário realizar algumas alterações conforme os comandos: {{{ ALTER TABLE phpgw_cal ADD COLUMN last_status char(1) DEFAULT 'N'::bpchar; ALTER TABLE phpgw_cal ADD COLUMN last_update int8 DEFAULT (date_part('epoch'::text, ('now'::text)::timestamp(3) with time zone) * (1000)::double precision); ALTER TABLE phpgw_cc_contact ADD COLUMN last_status char(1) DEFAULT 'N'::bpchar; ALTER TABLE phpgw_cc_contact ADD COLUMN last_update int8 DEFAULT (date_part('epoch'::text, ('now'::text)::timestamp(3) with time zone) * (1000)::double precision); ALTER TABLE phpgw_cc_contact ADD COLUMN category character varying(20); }}}