logo
  • Home
  • Acerca
  • Autores
  • Faq
  • Rede
  Twitter   Feed-me! RSS!
Dez 27

Flex com PHP usando ZendAMF – Zend_Db

Escrito por Leonardo França em .NET, 1, 2.0, 2009, 4, abas, action, Actionscript, Actionscript 3.0, Actionscript3, Adobe, Adobe Flex, AMF, amfphp, AR, Artigo, Banco de Dados, C#, catch, class, classe, classes, dados, email, exemplo, filter, Flex, framework, function, Google, handle, html, if, image, int, Java, lista, live, mg, mysql, O, on, Password, PHP, pt, Ria’s Geral, S+S, server, site, TAT, Tema, try, UI, uint, update, Ved, zend, Zend Amf, zendAMF, zendFramework @ 12 27th, 2011 | via http://www.leonardofranca.com.br | Sem comentários
Leonardo França
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

O artigo Adobe Flex com PHP usando ZendAMF – primeiros passos teve como objetivo exemplificar a integração do Flex com PHP para quem já tinha sistemas desenvolvidos usando o AMFPHP, por isso não usei as classes para acesso a banco de dados do ZendFramework. Neste artigo mostrarei o mesmo exemplo mas usando exclusivamente ZendFramework.

Pegarei o mesmo exemplo utilizado no artigo anterior, só modificando a classe PHP para usar as classes de abstração de banco de dados do ZendFramework. Começaremos com nosso gateway.php

PLAIN TEXT
PHP:

  1. require_once ‘Zend/Config.php’;
  2. require_once ‘Zend/Db.php’;
  3. require_once ‘Zend/Amf/Server.php’;
  4. require_once ‘Zend/Amf/Exception.php’;
  5. require_once ‘Zend/Amf/Server.php’;
  6. $server = new Zend_Amf_Server();
  7. $server->setProduction(false);
  8. $server->setClass(‘Contato’);
  9. echo($server->handle());
  10. ?>

Executando o link no seu navegador, deve aparecer a seguinte mensagem:

Zend Amf Endpoint

Em seguida, modificaremos em nossa classe principal, que efetuará as operações de listar, inserir, apagar e atualizar os dados do nosso banco:

PLAIN TEXT
PHP:

  1. /*
  2. * author Leonardo França
  3. * site http://www.leonardofranca.com.br
  4. */
  5. class Contatos
  6. private $db;
  7. private $config;
  8. private $select;
  9. private $stmt;
  10. function __construct()
  11. $params['host'] = ‘localhost’;
  12. $params['dbname'] = ‘java’;
  13. $params['username'] = ‘root’;
  14. $params['password'] = ”;
  15. $database['adapter'] = ‘Mysqli’;
  16. $database['params'] = $params;
  17. $data['database'] = $database;
  18. $this->config = new Zend_Config($data);
  19. $this->db = Zend_Db::factory($this->config->database);
  20. public function getData()
  21. try
  22. $this->select = $this->db->select();
  23. $this->select->from(‘tabela’,array(‘id’,‘nome’,‘email’));
  24. $this->stmt = $this->select->query();
  25. $result = $this->stmt->fetchAll();
  26. return $result;
  27. catch (Exception $e)
  28. throw new Exception($e->getMessage());
  29. }
  30. public function insertData($data=array())
  31. try
  32. $dados = array(
  33. ‘nome’ => $data['nome'],
  34. ‘email’ => $data['email']
  35. );
  36. $retorno = $this->db->insert(‘tabela’, $dados);
  37. return $retorno;
  38. catch (Exception $e)
  39. throw new Exception($e->getMessage());
  40. }
  41. public function deleteData($data=array())
  42. try
  43. $retorno = $this->db->delete(‘tabela’, ‘id = ‘.$data['id']);
  44. return $retorno;
  45. catch (Exception $e)
  46. throw new Exception($e->getMessage());
  47. }
  48. public function updateData($data=array())
  49. try
  50. $dados = array(
  51. ‘nome’ => $data['nome'],
  52. ‘email’ => $data['email']
  53. );
  54. $where['id = ?'] = $data['id '];
  55. return $this->db->update(‘tabela’, $dados, $where);
  56. catch (Exception $e)
  57. throw new Exception($e->getMessage());
  58. }
  59. }
  60. ?>

No ActionScript só precisaremos mudar o que será passado para o PHP, ao inves de VOs, mandaremos Arrays:

PLAIN TEXT
ACTIONSCRIPT3:

  1. public function insertData():void
  2. var contatosVO:Array = [];
  3. contatosVO['nome']= input_nome.text;
  4. contatosVO['email'] = input_email.text;
  5. ro.insertData(contatosVO);

Referências:
http://framework.zend.com/manual/en/zend.db.adapter.html

Dez 14

Testes Unitários com JUnit – De volta ao básico

Escrito por DClick Team em 1, 2.0, 4, 6, Air, AR, arte, C#, case, class, classe, classes, cliente, código, comparação, demo, Desenvolvimento, Design, Download, Eclipse, err, erro, exemplo, falha, Ferramenta, Flex, for, framework, Google, ide, IE, if, int, Introdução, Java, NaN, O, on, Opinião, Outros, padrão, Plugin, print, rest, RIA, Ria’s Geral, S+S, Sem categoria, site, string, Sun, super(), TAT, Tema, Teste, Twitter, UI, uint @ 12 14th, 2011 | via http://blog.dclick.com.br/pt/ | Sem comentários
DClick Team
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Twitter!

Já que ultimamente estamos falando bastante de testes unitários, principalmente aqui na DClick, vamos revisar uma das ferramentas essenciais para executar essa tarefa: JUnit. Mais especificamente, vamos fazer alguns testes com o JUnit 4.8.1, que pode ser encontrado para download no site do projeto, ou até mesmo no repositório do maven.
A proposta desse post é apresentar a ferramenta para quem ainda não conhece, e relembrar ou até mesmo mostrar algumas funcionalidades muito úteis para nosso dia a dia de desenvolvimento.


Um pouco sobre a nova versão

Nas versões anteriores do JUnit, da 3.* pra baixo para ser mais exato, era necessário criar as classes de testes seguindo uma hierarquia pré-definida do JUnit para que os testes fossem executados. Era necessário extender uma das classes de Test Case do JUnit, e seus métodos precisavam seguir um padrão de nome específico definido pelo framework.
Com a versão 4.* e a introdução ao suporte a Java 5, agora todas as configurações de testes unitários em JUnit são feitas via anotações, o que na minha opinião é muito mais rápido e fácil, tornando muito mais agradável e flexível escrever testes unitários. Agora é possível definir umahierarquia específica para os testes do projeto, podendo abstrair muitas inicializações e padrões do sistema, facilitando o reaproveitamento e aumentando a velocidade de desenvolvimento. Afinal a maior parte do tempo gasto em desenvolvimento é com os testes.
Porém, com anotações, perdemos o acesso direto aos métodos de asserção de valores que as super classes definiam. A solução adotada foi tornar todos esses métodos estáticos e públicos, em uma classe específica para guardá-los: org.junit.Assert.
Pode parecer uma solução não muito elegante do ponto de vista de código, e de fato não é quando consideramos código que será distribuído e deploiado, porém é uma solução que faz total sentido no escopo dos testes unitários, tornando fácil o uso e acesso a tais funcionalidades.

Asserções



Para testar nosso código, o JUnit fornece os métodos de assert. O conceito é muito simples, todo método de asserção recebe um valor que é o correto esperado pelo teste, e o outro valor que é o devolvido pelo seu código. A comparação é executada, e o teste falha caso sejam diferentes e passa caso sejam iguais. Apenas com esse conceito é possível testar todo o código, basta saber quais são os valores que devem ser testados para garantir o funcionamento do código.
A chave para escrever um teste unitário que cobre muito bem o seu código, é colocar as asserções nos valores realmente relevantes ao funcionamento do sistema. Algumas vezes por exemplo, não é preciso testar um valor intermediário gerado pelo código, apenas o resultado final, outras vezes esse valor intermediário gerado é crucial para o resultado final, e portanto deve ser verificado também.
Quando eu menciono ‘valores’, entenda que um valor pode ser qualquer objeto Java, portanto é muito importante implementar o equals e hashcode de seus objetos de resposta que serão testados pelo JUnit.

Exemplo Prático



Vamos criar um exemplo de classe de testes com o JUnit 4 para vermos como funciona na prática a execução de testes unitários.
Se você utiliza o Eclipse, você já possui instalado o plugin de execução de testes do JUnit, caso você não tenha tal plugin, recomendo que instale posi facilita muito a execução e depuração dos testes.
Vamos criar uma classe de testes:

1
2
3
public class JUnitTestCase



Repare que apesar do nome parecer que segue algum padrão, não é necessário que a classe tenha nenhuma dessas palavras em seu nome. Porém esta classe ainda não é uma classe de testes do JUnit. Para torná-la um teste, crie um método da seguinte forma:

1
2
3
4
@Test
public void metodoQualquer()



Repare na anotação org.junit.Test. Essa anotação diz que nosso método ‘metodoQualquer’ é um teste do JUnit. Perceba também que seu retorno é ‘void’ e ele não recebe nenhum argumento. Agora nossa classe é um teste propriamente dito. Simples assim. Vamos adicionar uma asserção agora para ver o funcionamento da mesma. Dentro do método que acabamos de criar, adicione a seguinte chamada:

1
Assert.assertEquals(“2 dividido por 2 deveria ser 1.”, 1, 2 / 2);



Repare que o primeiro argumento do método, é a mensagem que vai aparecer caso o método falhe. Mude o valor obtido (último argumento) para ver a mensagem de erro.
Esse é o básico de execução de testes. Por mais simples que possa parecer, esse é o ponto de partida. Agora existem outras funcionalidades qua ajudam a escrever testes mais complexos, por exemplo, se precisarmos criar um objeto mais complexo para nossos testes, fazemos o seguinte, adicione o seguinte código em nossa classe de testes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private String stringLocal;

@Before
public void inicializaLocal()
System.out.println(“Inicializou.”);
this.stringLocal = “inicializada”;

@Test
public void testInicializadaLocal1()
Assert.assertEquals(“A String deveria estar inicializada.”, “inicializada”,
this.stringLocal);

@Test
public void testInicializadaLocal2()
Assert.assertEquals(“A String deveria estar inicializada.”, “inicializada”,
this.stringLocal);

@After
public void setaNull()
System.out.println(“Setou nulo.”);
this.stringLocal = null;



Rode o teste e veja o que aparece no console.
Repare que a String é inicializada e setada novamente pra ‘null’ 3 vezes. Isso porque nossa classe possui 3 métodos de testes, e os métodosanotados com @Before rodam sempre antes de todos os métodos de teste. O mesmo vale para os métodos anotados com @After, só que estes rodam depois de executar os métodos de teste.
Só com essas duas anotações é possível criar cenários que estão sempre ‘zerados’ e corretamente incializados para cada teste que será executado em sua classe. Perceba que com isso é possível separa melhor as asserções em suas classes em mais métodos, deixando mais específico e focado cada método de teste.
Porém algumas vezes queremos inicializar algum objeto para o teste todo, sem precisar de algo específico para cada execução. Nesse caso existem duas outras anotações que podem ser úteis. Adicione o seguinte trecho em nossa classe de testes:

1
2
3
4
5
6
7
8
9
@BeforeClass
public static void antesDeTudo()
System.out.println(“Executado Antes.”);

@AfterClass
public static void depoisDeTudo()
System.out.println(“Executado Depois.”);



Só existe um restrição com essa abordagem, e acho que está claro no código qual que é: o escopo dessas chamadas é estático. Repare que os métodos precisam ser estáticos, e portanto as incializações só servirão para propriedades que são estáticas em sua classe de testes.
Essa funcionalidade possui esse comportamento porque o JUnit instancia um novo objeto da sua classe de testes para cada método que será rodado, dessa forma ele garante um melhor isolamento dos testes, tornando-os mais unitários por assim dizer. Dessa forma somente métodos estáticos são garantia de execução antes de todos os outros métodos.
Rode o teste e veja a ordem das mensagens em seu console.

Próximos passos



Essa foi uma introdução muito simples do JUnit e testes unitários. Acho que já passou pela sua cabeça muitas formas de inicializar, integrar e rodar testes em sua aplicação usando JUnit, o que é ótimo, mas ainda existem boas práticas para criar testes assim como existem boas práticas para escrever código, afinal testes são linhas de código também.
O segredo de um bom teste unitário é o quanto ele consegue cobrir do funcionamento do código, sem que seja necessário escrever um teste extremamente detalhado que deixe o código acoplado demais, e não permita muita mudança no código original. Se você investir tempo demais testando TODOS os valores possíveis de suas classes de maneira extremamente detalhada, quando o cliente pedir que um requisito mude, você com certeza vai ter a sensação de trabalho jogado fora, e desânimo por ter que escrever tudo novamente. A idéia é utilizar padrões de design para testes unitários, de forma que se mantenha a cobertura de código no 85%+ e ainda deixe os testes bem flexíveis a mudança. Difícil mas não impossível, e sim, é muito mais difícil e trabalhosos escrever testes realmente bons, do que escrever o código que será testado.

Por @Gust4v0_H4xx0r

Dez 12

Vídeo Wall para KF Carnes

Escrito por Igor Musardo em 1, 2.0, 4, 6, Adobe Flex, AR, BI, busca, C#, class, classe, classes, cliente, consultoria, Curitiba, ide, IE, if, image, int, mg, monitor, O, on, PHP, Projetos, RIA, Ria’s Geral, S+S, Software, tag, TAT, Tema, tv, UI, Vídeo @ 12 12th, 2011 | via http://www.igormusardo.com.br | Sem comentários
Igor Musardo
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Em parceria com a TVD Plus desenvolvi um sistema de tabela de pre?os para exibi??o em solu??es de V?deo Wall.

V?deo Wall consiste em m?tliplos monitores, projetores ou televisores colocados um ao lado do outro servindo como uma grande ?nica tela.

A KF Carnes, a?ougue tradicional de Curitiba, atende o p?blico das classes A e B com carnes de alto padr?o de qualidade e alto valor agregado.

Em busca de melhorar o ambiente de atendimento ? clientes e modernizar a casa de carnes, a KF foi atr?s de uma solu??o de V?deo Wall para substituir a antiga tabela de pre?os.

A solu??o da TVD Plus para a KF Carnes foi a instala??o de 4 televisores de 42″ ligados a um ?nico computador onde estaria rodando v?deos institucionais da casa intercalados com a tabela de pre?os.

A exig?ncia do projeto era permitir a atualiza??o da tabela de pre?os ao mesmo tempo que as balan?as sofriam atualiza??es, evitando assim transtornos com diferen?as de pre?os entre a tabela para os clientes e o pre?o na balan?a, e com isso evitar o retrabalho de atualizar na balan?a e manualmente atualizar pre?o a pre?o na tabela para os clientes.

Com a constante varia??o do dolar, moeda base para o pre?o da arroba do boi, era de extrema import?ncia que o sotware suportasse v?rias atualiza??es de pre?o durante o dia.

O projeto todo teve dura??o de 20 dias desde a sua concep??o ? sua instala??o e homologa??o.

Hoje com os televisores instalados e com o software em produ??o, a KF Carnes oferece ? seus clientes um ambiente ainda mais agrad?vel e moderno, mantendo-se ? frente de seus concorrentes.

O seu estabelecimento continua mostrando o seu card?pio / tabela de pre?os com fotos embassadas e com pre?os fixos? Entre em contato comigo.

Dez 6

JodaTime – Java Date que funciona!

Escrito por DClick Team em .NET, 1, 2.0, 4, 6, api, AR, bar, BI, blog, C#, camp, class, classe, classes, código, control, Curso, Cursos, Design, Design Pattern, Diversos, Documentação, efeito, err, exemplo, Exemplos, falha, for, Google, Hibernate, html, ide, IE, if, image, int, interface, internet, Java, lógica, map, mg, O, on, online, Opinião, padrão, pattern, print, problema, RIA, Ria’s Geral, S+S, Sem categoria, singleton, string, Sun, TAT, Tema, Teste, try, Twitter, UI, uint, Vários, XP, zend @ 12 6th, 2011 | via http://blog.dclick.com.br/pt/ | Sem comentários
DClick Team
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Twitter!


JodaTime



Não existe segredo quando se fala da implementação de datas no Java: é ruim de usar. Alguns chegam a dizer que é errado usar inclusive, mas não serei tão extremo.
A API de datas do Java é ruim por vários motivos, como por exemplo, é mal documentada, não é Thread Safe, é difícil de manipular datas, e o comportamento nem sempre é o esperado.
Vamos ver como susbtituir a API de datas que vem Out of the Box no Java, por uma mais efetiva, amigável e confiável: JodaTime.


Lembrando do Calendar



Todo programador Java conhece o Calendar, e sabe que para usá-lo, basta seguir o Design Pattern singleton, ou seja, basta chamar o método de classe em Calendar que devolve a instância única do sistema para o Calendar.


Problema: não funciona.


Não funciona porque se a instância é singleton, e não utiliza threadlocking no código, então não é uma instância ThreadSafe. Logo toda vez que chamamos o getInstance() do Calendar, obtemos uma nova instância. Para ilustrar, crie um teste em JUnit 4 com o seguinte código:

1
2
3
4
5
6
7
Calendar calendar = Calendar.getInstance();

System.out.println(calendar.getTime());

Calendar calendar2 = Calendar.getInstance();

Assert.assertTrue(calendar == calendar2);



Rode o teste e veja a barra do JUnit ficar vermelha. O comparador ‘==’ usado em objetos, compara pelo endereço de memória, o que deveria ser o mesmo se fosse seguido o padrão singleton de verdade.
Pra piorar, todos os métodos que alteram as intâncias do Date estão expostos (por mais que estejam depreciados) para mantêr compatibilidade com versões anteriores da VM. Portanto o Date também não é ThreadSafe, pois não existe controle de concorrência em sua implementação.
Agora vamos deixar o Date e o Calendar de lado, e vamos ao JodaTime.

DateTime



O JodaTime diferencia muito bem os conceitos de data, instante de tempo, período, etc. A classe mais básica (interface no caso) é a ReadableInstant. Não precisa dizer que todas as modelagens de data implementam essa interface, permitindo comparar todos os tipos de modelagem de tempo pontuais. Um período não descreve um único instante ou ponto no tempo, por exemplo.
DateTime é talvez o ReadableInstant mais conhecido, e funciona muito parecido com o Date do Java.
Fatores que tornam o DateTime mais amigável são: é ThreadSafe pois é imutável, é muito bem documentado, e é muto fácil realizar operações com data. Vamos escrever um pouco de código para entender o que se passa.
Comece criando um DateTime. Como no Java, este DateTime criado possui o instante atual do sistema. Em seguida para efeito de teste (o teste pode falhar dependendo de quando for executado), adicione um dia na data criada, e verifique que o novo date aponta para amanhã:

1
2
3
4
5
DateTime date = new DateTime();

date = date.plusDays(1);

Assert.assertEquals(new DateTime().getDayOfYear() + 1, date.getDayOfYear());



Repare que tive que reassociar o date para que ele pudesse ser alterado, afinal DateTime é imutável, o mesmo comportamento que o BinInteger possui. Repare também que pra adicionar um dia, basta chamar plusDays. Este método já se encarrega de fazer toda a lógica de adicionar um dia na data, como por exemplo mudar o mês ou ano se for preciso, por isso se esse teste for rodado no dia 31 de dezembro, ele irá falhar pois o DateTime irá adicionar mais um dia a data, e perceberá que se trata do ano seguinte, e portanto getDayOfYear irá devolver ’1′, e não ’366′ ou ’365′ como esperado.
O JodaTime também trata anos bissestos e horário de verão se for selecionado o fuzo correto.
Existe uma API bem completa em DateTime para manipular todos os campos possíveis da data, sendo assim fica muito mais fácil iterar ao longo dos dias, sem precisar delegar pro Calendar a tarefa, e depois recuperar o resultado.
Não vou abordar muito da API do JodaTime, pois está muito bem documentada e existem muitos exemplos nas internet. O objetivo desse post é tratar do assunto do próximo tópico.

JodaTime e Hibernate



Pior que manipular datas, é persistir datas. Cada banco persiste data do seu próprio jeito, e cada implementação de ORM trata o Date do seu próprio jeito. Mas se você está utilizando o Hibernate, o JodaTime tem uma solução de padronização pra você: JodaTime Hibernate.
Com o JodaTime Hibernate é possível mapear diversos tipos de representação de data em suas classes Java, com ou sem TimeZone, como String ou bigint, como período ou duração, etc.
Para se ter uma idéia do que é possível, basta verificar a documentação online.
E para utiliza é muito fácil. Imagine que você tenha uma entidade com um campo DateTime, que se chama entryDate, portanto temos o getter:

1
2
3
4
@Column(nullable = false)
public DateTime getEntryDate()
return entryDate;



Para tornar este DateTime uma data que é padrão do banco que será utilizado, por exemplo, basta adicionar a seguinte anotação:

1
2
3
4
5
@Column(nullable = false)
@Type(type = “org.joda.time.contrib.hibernate.PersistentDateTime”)
public DateTime getEntryDate()
return entryDate;



Estamos falando para o hibernate utilzar o tipo de coluna descrito pelo PersistentDateTime, e utilizar o mesmo para converter a data novamente para DateTime quando for recuperado.
Caso você esteja fazendo engenharia reversa de algum banco, recomendo ler a descrição de todos os tipo disponíveis pra fazer a melhor escolha.
Com isso conseguimos obter todos os benefícios do JodaTime em nossas entidades, facilitando controlar as datas no domínio de nossas aplicações.


Espero ter despertado sua curiosidade com o JodaTime. Na minha opinião é uma das melhores bibliotecas Java disponíveis, mas não quero falar muito sobre suas funcionalidades, pois um dos pontos mais fortes da biblioteca é a facilidade de se acostumar com ela, e principalmente utilizar todos seus recursos. Quero que vocês tenham um pouco desse gostinho :) .

Por @Gust4v0_H4xx0r

Nov 16

LCCS e PHP com ZendAMF

Escrito por Leonardo França em .NET, 1, 2.0, 4, Adobe, AMF, amfphp, AR, Artigo, Artigos, C#, catch, class, classe, classes, developer, Documentação, exemplo, Exemplos, flash, Flex, Flex 4, for, framework, function, handle, image, int, Java, Javascript, live, LiveCycle, Mercado, mg, O, on, Password, PHP, player, portal, programação, pt, rest, RIA, Ria’s Geral, S+S, SDK, server, swf, Teste, try, UI, web, zend, zendAMF, zendFramework @ 11 16th, 2011 | via http://www.leonardofranca.com.br | Sem comentários
Leonardo França
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

O Adobe LiveCycle Collaboration Service possui em seu SDK, exemplos de integração com as principais linguagens de programação web do mercado como PHP, Java, Python, etc.
Na documentação da Adobe, é recomendado o uso do AMFPHP ou o PHP puro mesmo, mas nada impede de usar tranquilamente em conjunto com o ZendFramework (usando ZendAMF)
Ryan Stewart escreveu dois artigos mostrando a implementação com PHP e REST.

  • http://ria.dzone.com/articles/integrating-php-flash
  • http://ria.dzone.com/articles/php-flash-rest

Uma observação sobre o artigo de Ryan, no Flex 4, Adobe passou a usar o swfobject, então o modo de pegar os parâmetros via URL e passar para o SWF fica desse modo:

PLAIN TEXT
JAVASCRIPT:

  1. var xiSwfUrlStr = “playerProductInstall.swf”;
  2. var flashvars = ;
  3. flashvars.roomURL = swfobject.getQueryParamValue(“roomURL”);
  4. flashvars.authToken = swfobject.getQueryParamValue(“authToken”);
  5. var params = ;

No SDK do LCCS, existe um arquivo chamado lccs.php, basta copiar para o mesmo diretório em que você já usa suas classes. Em seguida, adicionar o include no arquivo gateway.php

PLAIN TEXT
PHP:

  1. require_once ‘Zend/Amf/Server.php’;
  2. require_once ‘lccs.php’;
  3. require_once ‘Test.php’;
  4. /** Bootstrap */
  5. // Instantiate server
  6. $server = new Zend_Amf_Server();
  7. $server->setProduction(false);
  8. $server->setClass(‘Test’);
  9. // Handle request
  10. echo($server->handle());
  11. ?>

E está é uma simples classe para teste chamando o método que retorna o token para autenticação.

PLAIN TEXT
PHP:

  1. class Test
  2. private $account;
  3. private $room;
  4. private $devUsername;
  5. private $devPassword;
  6. private $secret;
  7. //$accountURL = “https://collaboration.adobelivecycle.com/$account”;
  8. private $accountURL;
  9. private $roomURL;
  10. function __construct()
  11. //for LCCS
  12. $this->account = “Your SDK account username from LCCS developer portal”;
  13. $this->room = “The room you want to connect to”;
  14. $this->devUsername = “Your LCCS developer account username”;
  15. $this->devPassword = “Your LCCS developer account password”;
  16. $this->secret = “The shared secret from the LCCS developer portal”;
  17. //$accountURL = “https://collaboration.adobelivecycle.com/$account”;
  18. $this->accountURL = “http://connectnow.acrobat.com/$this->account“;
  19. $this->roomURL = “$this->accountURL/$this->room“;
  20. public function getToken($data=array())
  21. try
  22. $this->account = new RTCAccount($this->accountURL);
  23. $this->account->login($this->devUsername,$this->devPassword);
  24. $session = $this->account->getSession($data['room']);
  25. $displayName = $data['displayName'];
  26. $username = $data['username'];
  27. $role = $data['role'];
  28. $token = $session->getAuthenticationToken($this->secret, $displayName, $username, $role);
  29. return $token;
  30. catch (Exception $e)
  31. throw new Exception($e->getMessage());
  32. }
  33. }
  34. ?>
Nov 16

Spring 3.1 RC1 – @Configuration

Escrito por DClick Team em 1, 2.0, 4, 6, action, app, AR, auto, bar, BI, blog, busca, C#, case, class, classe, classes, código, components, configuração, err, erro, error, exemplo, for, framework, Google, IE, if, int, Java, lite, map, mudanças, mvc, NaN, O, on, Plugin, refresh, rest, RIA, Ria’s Geral, RoR, S+S, Sem categoria, Spring, SpringFramework, string, Sun, super(), tag, TAT, Teste, Twitter, UI, uint, web, XML @ 11 16th, 2011 | via http://blog.dclick.com.br/pt/ | Sem comentários
DClick Team
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Twitter!


Spring @Configuration


O que há de novo



Para habilitar certas funcionalidades do Spring que envolvem AOP, era preciso escrever tags XML como por exemplo context:component-scan para especificar os pacotes em que o Spring pode buscar por beans anotados com @Component, @Repository ou @Service.
Na versão 3.1 foram disponibilizadas as mesmas funcionalidades via anotação. São elas:

1
2
3
4
5
6
7
8
org.springframework.context.annotation.Configuration
org.springframework.context.annotation.ComponentScan
org.springframework.context.annotation.EnableLoadTimeWeaving
org.springframework.context.annotation.EnableAspectJAutoProxy
org.springframework.scheduling.annotation.EnableScheduling
org.springframework.scheduling.annotation.EnableAsync
org.springframework.transaction.annotation.EnableTransactionManagement
org.springframework.web.servlet.config.annotation.EnableWebMvc



Vamos abordar o caso básico, pois o resto é bem similar.


@ComponentScan



Caso você ainda não esteja familiarizado com as configurações por anotaçãoo, vamos ao básico.
Comece criando uma classe que representará seu container de beans, e a anote com @configuration:

1
2
3
4
@Configuration
public class TestConfiguration



Nesta classe estarão os beans que o container irá instanciar e deixar a nossa disposição.
Para iniciar o container vamos criar um test (JUnit 4) que instancia o contexto:

1
2
3
4
5
6
7
8
9
10
11
public class ConfigurationTestCase

@Test
public void testConfigurationBeans()

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(TestConfiguration.class);
ctx.refresh();


}



Aqui criamos um container do tipo AnnotationConfigApplicationContext e registramos nossa classe de configuração nele. Repare que é possível registrar mais classes, e portanto disponibilizar mais beans no container.
Agora vamos criar nosso bean de teste:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class GenericBean

private String testProperty;

public GenericBean(String testProperty)
super();
this.testProperty = testProperty;

public String getTestProperty()
return testProperty;

}



Vamos criar os métodos em nossa classe de configuração que instanciam nosso bean de duas maneiras diferentes:

1
2
3
4
5
6
7
8
9
@Bean(name = “testBean”)
public GenericBean genericTestBean()
return new GenericBean(“test”);

@Bean(name = “otherBean”)
public GenericBean genericOtherBean()
return new GenericBean(“other”);



Repare que a única diferença entre os dois é a String que passamos como parâmetro.
Agora que temos 2 beans diferentes em nosso container, vamos criar os testes para verificar o comportamento do Spring. Abaixo da inicialização do contexto, vamos adicionar as seguintes linhas:

1
2
3
4
5
6
7
8
9
GenericBean testBean = ctx.getBean(“testBean”, GenericBean.class);

Assert.assertNotNull(testBean);
Assert.assertEquals(“test”, testBean.getTestProperty());

GenericBean otherBean = ctx.getBean(“otherBean”, GenericBean.class);

Assert.assertNotNull(otherBean);
Assert.assertEquals(“other”, otherBean.getTestProperty());



Aqui estamos garantindo que nossos dois beans diferentes estarão no contexto como esperado.
Antes de rodar o teste, será necessário adicionar a dependência do CGLib ao seu projeto. Caso você esteja usando o maven, basta adicionar a seguinte dependência>

GeSHi Error: GeSHi could not find the language text (using path C:Program Fileswampwwwblogwp-contentpluginsig_syntax_hilitegeshi) (code 2)



Pronto, com isso temos o suficiente pra deixar a barra do JUnit verde. Vamos agora adicionar o @ComponentScan.
Em nossa classe de configuração (poderia ser qualquer outra registrada no contexto) adiciona a seguinte anotação:

1
2
3
@Configuration
@ComponentScan(“br.com.dclick.tentativas.configuration.beans”)
public class TestConfiguration



No meu caso meu bean está dentro do pacote br.com.dclick.tentativas.configuration.beans e portanto basta eu alterá-lo adicionando o seguinte código:

1
2
3
4
5
6
7
8
@Component(“componentBean”)
public class GenericBean

private String testProperty;

public GenericBean()
this.testProperty = “component”;



Dessa forma posso criar mais um teste e verificar que o bean está vindo corretamente:

1
2
3
4
GenericBean componentBean = ctx.getBean(“componentBean”, GenericBean.class);

Assert.assertNotNull(componentBean);
Assert.assertEquals(“component”, componentBean.getTestProperty());



Rode o teste e deixa o JUnit feliz.
A única coisa a se ter cuidado aqui, é que com @ComponentScan, você não pode mapear o diretório da própria classe de configuração.

Demais Configurações



Daqui em diante basta anotar suas classes de configuração com as configurações que você deseja ativar, como por exemplo @EnableAsync que permite que os beans rodem de maneira assíncrona com a anotação @Async.

Brinque um pouco com as outras anotações. Acredito que vale o esforço, pois esse tipo de configuração permite abandonar um pouco os arquivos XML e tornam mais fácil o refactor dos beans, afinal teremos erros de compilação com as mudanças de código.

Por enquanto é isso, qualquer dúvida mande nos comentários que responderei assim que possível.

Por @Gust4v0_H4xx0r

Nov 9

Conhecendo o LESS. The Dynamic Stylesheet.

Escrito por DClick Team em 1, 2.0, 4, 6, Adobe, Air, app, apple, AR, back, BI, browser, C#, class, classe, classes, código, css, css3, Curso, Cursos, custom, dados, demo, Desenvolvedor, Desenvolvimento, Desenvolvimento Web, Design, Destaque, Dica, Diversos, Documentação, dynamic, empresas, err, erro, error, Estilo, exemplo, Exemplos, for, function, gc, Google, html, html5, ide, IE, if, int, Java, Javascript, kit, layout, menu, Microsoft, MIX, NaN, O, on, Opinião, Outros, padrão, problema, problemas, programação, prova, pt, referencia, RIA, Ria’s Geral, RoR, S+S, Sem categoria, site, tag, TAT, Twitter, UI, uint, Utilidades, Ved, web, zend @ 11 9th, 2011 | via http://blog.dclick.com.br/pt/ | Sem comentários
DClick Team
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Twitter!

Como todos devem ter percebido, nos últimos meses o CSS3 e o HTML5 tem ganho um grande destaque no desenvolvimento web. Grandes empresas como o Google, Microsoft, Adobe e Apple estão apoiando fortemente o desenvolvimento web utilizando WebStandards. Caso você já conheça algo sobre CSS, provavelmente deve saber como é complicado a organização desses documentos em um projeto de médio ou grande porte. Dado esses problemas conhecidos, foram surgindo os chamados pré-processadores de CSS, que viabilizam a criação de documentos de estilo, adicionando novas funcionalidades.

Hoje vamos conhecer o LESS, The Dynamic Stylesheet Language. O objetivo dessa biblioteca em javascript é prover uma série de funcionalidades para as, usualmente criadas a mão, folhas de estilos. Recursos tais como, variáveis, mixins (Multiple Inheritance, Traits), mixins parametrizáveis, funções, namespaces, importação, etc. Vamos aprender como utilizar os principais recursos dessa biblioteca em um projeto e como aproveitar o melhor dessa biblioteca para organizar corretamente nossas folhas de estilo.

Variables

As variáveis ajudam-nos a definir valores que podem ser utilizados em diversas regras do nosso CSS. Elas possuem escopo assim como em uma linguagem de programação orientada a objetos, trocando em miúdos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Arquivo stylesheet.less
// Essa variável foi definida no escopo do arquivo, logo, todas as regras do arquivo podem acessar seu valor.
@siteBackgroundColor: #FF3300; // Laranja

h1
// A variável headingColor foi criada no escopo da regra h1, logo, apenas ela e outras regras criadas dentro
// do mesmo escopo tem acesso ao seu valor.
@headingColor: #333333; // Cinza

// Isto significa que, se criarmos uma outra regra chamada &.mainTitle
// Observe o uso do &.classe, isso copia a regra pai e associa uma classe, o output disso seria exatamente h1.mainTitle
&.mainTitle
// Como essa regra esta contida na regra h1, podemos acessar o valor da variável headingColor.
color: @headingColor;

}

h2
// Se tentarmos acessar o valor nessa regra, que não encontra-se contida na regra h1, receberemos um erro da biblioteca
// informando que a variável headingColor não encontra-se definida.
color: @headingColor; // Brrrrrr! Error.

O que é interessante no uso de variáveis é a reutilização e organização. Imagine uma design guideline onde existem RGBs específicos a serem seguidos, essas cores poderiam ser definidas em um documento chamado color_variables.less e adicionados ao nosso arquivo principal utilizando a clausula @import.

@Import – Importando outros arquivos

Quando um arquivo LESS é importado, todas as suas variáveis e mixins são adicionados ao arquivo principal. Os escopos serão mantidos e a extensão .less é opcional.

@import “lib.less”
@import “lib”

É possível utilizar pastas nas clausulas de @import:

@import “where/is/my/stylesheet.less”
@import “where/is/my/stylesheet”

Mixins

No LESS, mixis são como uma espécie de classe CSS que pode ser reutilizada em diversas outras regras. Quando utilizadas, todas as propriedades definidas no mixin são adicionadas a regra onde a mesma foi adicionada, caso um mixin mude, todas as regras que o referenciam serão também modificadas.

Imagine o conceito de mixin como classes CSS orientadas a objeto, o que é interessante do mixin é que temos aqui algo como uma herança múltipla, caso uma mesma instrução seja declarada em mixins diferentes, e esses mixins adicionados a uma regra, o mixin declarado por último terá vantagem na construção final do CSS da regra onde foi adicionado.

1
2
3
4
5
6
7
8
9
10
11
12
.bordered
border-top: dotted 1px black;
border-bottom: solid 2px black;

// Declaramos agora uma regra qualquer que fará uso do nosso mixin.
div.someDiv
.bordered; // Simples assim, adicionamos todas as propriedades contidas no mixin em nossa regra.

div.anotherDiv
.bordered; // A mesmas propriedades serão adicionadas nessa regra.

Quando modificarmos o mixin .bordered, todos os elementos que o estão utilizando serão modificados. Reutilização!
Vamos para um exemplo mais usável para exemplificar como é um mixin parametrizável.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Bordas arredondadas cross-browser.
// Observe que utilizamos algo parecido com uma função de javascript para declararmos nosso mixin.
// A notação de variável deve ser adicionada (@radius), com isso, criamos uma variável chamada “radius” no escopo
// do mixin que poderá ser utilizada apenas internamente pelo método.
// Observe também que declaramos um valor padrão para o parâmetro, de 5px.
.border-radius( @radius: 5px )

// Repare que utilizamos a mesma variável para todas as regras.
border-radius: @radius;
-moz-border-radius: @radius;
-webkit-border-radius: @radius;

// Para utilizarmos a regra, seguimos o mesmo padrão
div.someDiv
.border-radius; // Nesse caso estaremos utilizando o valor padrão de 5px.

div.anotherDiv
.border-radius(10px); // Nessa aplicação, modificamos o valor da propriedade para 10px.

É importante destacar que um mixin pode conter diversos parâmetros. Isso pode ser feito da seguinte forma:

1
2
3
4
5
6
// Declaramos um novo mixin
.border-radius-and-color( @radius: 5px, @borderColor: #000000 )

.border-radius( @radius ); // Observe que aqui reutilizei o mixin previamente definido. Composição de mixins.
border: 2px solid @borderColor; // Adicionamos agora a cor para a borda.

Nested Rules

Com o LESS você pode criar suas regras de CSS utilizando uma espécie de hierarquia. Vamos ver como isso funciona na prática.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Dado o CSS abaixo
div#header #menu
…
rules

div#header #menu li a
…
more rules

div#header #topNav
…
another rules

Com o LESS, o mesmo CSS acima poderia ser escrito da seguinte forma:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Como utilizar hierarquia com Less
div#header
#menu
ul
li


}
}

#topNav


}

Depois de processado, o CSS será exatamente igual. Você não precisa utilizar esse esquema de hierarquia caso não queira, é importante lembrar que o LESS é apenas uma extensão do CSS, se for de desejo do desenvolvedor, podemos escrever um código LESS sem usar nenhum recurso especial, como se fosse um CSS tradicional.

Operations

Com o LESS o seu CSS sabe fazer contas. Qualquer número, cor ou variável pode ser utilizada em uma operação aritmética.
Ele sabe identificar quando estamos utilizando uma cor ou um número, por exemplo:

1
2
3
4
5
6
7
@base: 5%;
@filler: @base * 2;
@other: @base + @filler;

color: #888 / 4;
background-color: @base-color + #111;
height: 100% / 2 + @filler;

Assim como no javascript, é possível também utilizar parênteses nas suas operações:

1
width: (@var + 5) * 2;

Color Functions

Na minha opinião um dos recursos mais úteis durante o desenvolvimento de uma aplicação. Podemos efetuar operações em cima de RGBs, por exemplo, imagine que o layout do seu website foi criado baseado-se em apenas uma cor, utilizando diversos tons dessa cor. Com o LESS é possível utilizar métodos pré-definidos como lighten, saturate, darken, fadein, fadeout e spin. Esses métodos retornam sempre um RGB que pode ser utilizado em seu LESS. Vejamos alguns exemplos:

1
2
3
4
5
6
7
8
9
@base: #f04615;

.class
// Saturo em 5% a cor base.
color: saturate(@base, 5%);

// Utilizo a cor base 25% mais clara
background-color: lighten(@base, 25%);

É possível também extrair informações de uma determinada cor para ser utilizada em outra.
Isso é feito a partir dos métodos hue, saturation e lightness.

1
2
3
hue(@color); // retorna o valor do canal ‘hue’ da cor @color
saturation(@color); // retorna o valor do canal ‘saturation’ da cor @color
lightness(@color); // retorna o valor do canal ‘lightness’ da cor @color

Namespaces

Em dado momento necessitamos organizar uma série de mixins e variáveis. Para isto podemos utilizar um conceito presente no LESS chamado Namespaces. Assim como em linguagens de programação orientadas a objetos, que possuem o conceito de pacotes, os namespaces fornecem encapsulação para nossas folhas de estilo. Isso pode ser implementado facilmente utilizando a mesma notação de ID do CSS tradicional. Vejamos.

1
2
3
4
5
6
7
8
9
10
11
12
#bundle

.button ()

display: block;
border: 1px solid black;
background-color: grey;
&:hover background-color: white
}
.tab …
.citation …
}

Verifique que acima, criamos um mixin chamado button dentro do namespace bundle. Para o utilizarmos devemos fazer da seguinte forma:

1
2
3
4
#header a
color: orange;
#bundle > .button; // Estamos acessando o namespace ‘bundle’ e fazendo uma chamada para o mixin ‘button’.

Uma utilização muito comum dos namespaces é na criação de pequenas bibliotecas de utilidades. Imagine que sua empresa pode possuir uma série de arquivos LESS, e em um determinado projeto você necessita de acesso a esses mixins, variáveis, etc. Organizar seus documentos com namespaces fácilita a visualização e localização de uma determinada instrução no seu documento LESS, como por exemplo, um mixin customizado que pode ser facilmente encontrado a partir da sua indicação de namespace.

1
2
3
someRule
#dclick > .border-radius(10px);

Conclusão

Como podemos ver, o LESS facilita uma série de tarefas que são praticamente impossíveis de serem efetuadas pelo CSS tradicional.
Aconselho a todos que tenham interesse em se aprofundar mais na biblioteca a conhecer o website (http://lesscss.org/). Lá você poderá encontrar a documentação com maior riqueza de informações também poderá ver alguns exemplos de código que não foram abordados nesse post.

Qualquer dúvida, sinta-se a vontade e envie-nos um comentário!
Abraço!

Out 30

Windows Phone Mango – Local Database

Escrito por Alexandre Tadashi em .NET, 1, 2.0, 4, 6, abas, AMF, Aplicativos, app, AR, Arquitetura, arte, Artigo, auto, BI, blog, Blogs, botão, C#, camp, class, classe, classes, cliente, código, collection, cultura, Curso, Cursos, dados, demo, desempenho, Desenvolvedor, Design, designer, Documentação, dotnet, DRE, err, event, Evento, exemplo, Ferramenta, for, Formação, handle, html, ide, IE, if, int, interface, layout, library, Links, linq, Linq to Sql, map, mg, Microsoft, monitor, MSDN, mudanças, O, on, Otimização, Outros, Partilha, processo, pt, rest, RIA, Ria’s Geral, S+S, SDK, server, serviço, silverlight, SQL Server, state, string, TAT, Tecnologia, Tema, template, Treinamento, UI, UX, Ved, vs, window, windows, XAML @ 10 30th, 2011 | via http://alexandretadashi.net/ | Sem comentários
Alexandre Tadashi
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Na versão Mango do Windows Phone, você pode manipular uma base de dados localmente, chamada de local database na documentação oficial, o recurso permite que o desenvolvedor crie aplicativos com registros de dados em tabelas, além de manipular seus registros utilizando o LINQ to SQL.

Uma base de dados local no WP7 fica localizada no Isolated Storage, um local acessível somente pela aplicação corrente, a arquitetura fica conforme a figura abaixo, onde temos a aplicação que contém um DataContext e através de LINQ to SQL, fazemos o acesso a base de dados local no Isolated Storage

Arquitetura Local Database

Arquitetura Local Database

Para saber mais sobre Isolated Storage acessem os links:

http://msdn.microsoft.com/en-us/library/ff402541(v=vs.92).aspx

http://www.windowsphonebrasil.net/windowsphonebrasil/post/2010/10/08/Salvando-e-restaurando-o-Application-State-no-Windows-Phone-7.aspx

No WP7 as aplicações ficam eram áreas isoladas uma das outras, ou seja, uma aplicação não tem acesso ao Isolated Storage de outra aplicação, portanto até o momento não é possível compartilhar uma base de dados local com diversas aplicações. Diferente de uma base de dados SQL Server, um local database não pode rodar como um serviço continuo, visto que ele é executado somente durante o processo da aplicação.

Você pode criar um local database para manipular uma quantidade de dados razoável utilizando as facilidades de consultas do LINQ to SQL juntamente com o relacionamento de tabelas, similar a uma base de dados comum, o local database é uma implementação do SQL CE para o WP7, permitindo realizar facilmente tarefas com incluir, alterar , excluir e realizar consultas com LINQ.

Até o momento não existe uma ferramenta de designer visual e oficial para criar as tabelas, relacionamentos, etc, com a base de dados local, o que poderia facilitar muito, neste artigo faremos um exemplo simples, somente com uma tabela, porém, em um projeto mais complexo, essa tarefa poderia ser um pouco trabalhosa, uma forma não oficial de criar o modelo seria utilizar o SQL Metal, para mais informação, acessem o Centro de Treinamento Oficial do Windows Phone no MSDN ou através do link : http://windowsphonegeek.com/articles/Using-SqlMetal-to-generate-Windows-Phone-Mango-Local-Database-classes .

Com o SQL Metal podemos criar o Data Context através de um comando e com poucas modificações deixá-lo compatível com o Mango e poupar a codificação manual da criação de tabelas e relacionamentos.

Exemplo de comando do SQL Metal:

%ProgramFiles(x86)%Microsoft SDKsWindowsv7.0ABin>SqlMetal.exe
/code:”C:CaminhoClienteDC.cs” “C:CaminhoClienteDB.sdf”

Outras formas:

http://claudiufarcas.blogspot.com/2011/10/windows-phone-mango-sql-ce-tips-and.html

http://blogs.ugidotnet.org/corrado/archive/2011/06/05/using-local-database-in-wp7-mango.aspx

Nesta primeira parte do artigo vou criar uma base de dados muito simples, com uma tabela somente e um único campo, dessa forma podemos focar em como criar e entender os conceitos envolvidos Vou criar uma base de dados Cliente.sdf, com uma tabela chamada Cliente e um campo chamado Nome.

A primeira classe que vamos criar é a entidade Cliente e decorar com alguns atributos utilizados para a manipulação da base de dados, a classe servirá de apoio para a criação da tabela cliente. Para que você possa inserir os atributos nas propriedades da classe, é necessário adicionar o using System.Data.Linq.Mapping, em seguida adicione o atributo [Table] logo acima da criação da classe e adicione o atributo [Column()] em cada propriedade, na primary key da tabela, personalize com :

[Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]

Dessa forma a coluna será criada na tabela como sendo Primary Key, não permitindo registros duplicados e gerando automaticamente um número a cada inclusão. Com a adição do atributo Column() nas outras propriedades, cada coluna correspondente será criado na tabela.

Com os atributos de colunas você pode definir uma série de recursos, para saber quais são os atributos de colunas que você pode utilizar no LINQ to SQL para WP7 acesse o link http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.columnattribute(VS.95).aspx

Um atributo em especial que adiciona uma coluna de versão pode auxiliar no desempenho de grandes atualizações de dados, apresentando uma significativa melhoria na aplicação, é o IsVersion=true, essa otimização é exclusiva para o LINQ to SQL do WP7 e usado internamente para identificar a versão da coluna modificada:

[Column (IsVersion = true)]
_VERSION Binary privado;

Igualmente importantes são os atributos de associações, que permitem realizar o relacionamento entre as tabelas, para mais informações acesse:

http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.associationattribute(v=VS.95).aspx

Exemplo de Associação:

[Association(Storage = "_cliente", ThisKey = "_clienteId", OtherKey = "Id", IsForeignKey = true)]

Código da Classe Cliente:

? ? ?  [Table]
? ? ?  public class Cliente : INotifyPropertyChanged, INotifyPropertyChanging
? ? ?  
? 
? ? ? ? ? ? ?  #region INotifyPropertyChanged Members
? 
? ? ? ? ? ? ?  public event PropertyChangedEventHandler PropertyChanged;
? 
? ? ? ? ? ? ?  private void NotifyPropertyChanged(string propertyName)
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  if (PropertyChanged != null)
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ?  }
? 
? ? ? ? ? ? ?  #endregion
? 
? ? ? ? ? ? ?  #region INotifyPropertyChanging Members
? 
? ? ? ? ? ? ?  public event PropertyChangingEventHandler PropertyChanging;
? 
? ? ? ? ? ? ? 
? ? ? ? ? ? ?  private void NotifyPropertyChanging(string propertyName)
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  if (PropertyChanging != null)
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ?  }
? 
? ? ? ? ? ? ?  #endregion
? 
? 
? ? ? ? ? ? ?  [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
? ? ? ? ? ? ?  private string id;
? ? ? ? ? ? ?  public string Id
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  get
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  return id;
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  set
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  if (id != value)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  NotifyPropertyChanging("Id");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  id = value;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  NotifyPropertyChanged("Id");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  }
? 
? ? ? ? ? ? ?  }
? ? ? ? ? ? ? 
? ? ? ? ? ? ?  [Column()]
? ? ? ? ? ? ?  private string nome;
? ? ? ? ? ? ?  public string Nome
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  get
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ?  ? ? ? ? ? ? ? ? return nome;
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  set
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  if (nome != value)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  NotifyPropertyChanging("Nome");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  nome = value;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  NotifyPropertyChanged("Nome");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  }
? 
? ? ? ? ? ? ?  }
? ? ? ? ? ? ? 
? 
? ? ?  }

Em aplicações Silverlight é comum implementar a interface INotifyPropertyChanged para monitorar mudanças nas propriedades da classe , e tirar um melhor proveito do recursos de databinding da tecnologia, para auxiliar o LINQ to SQL, também vamos implementar a interface INotifyPropertyChanging, com ela é possível monitorar quando uma propriedade será modificada e com isso o DataContext é informado e pode identificar as mudanças e melhorar a performance da aplicação.

O Data Context é o local onde definimos o contexto dos dados que servirão para criar a base de dados local, o LINQ to SQL depende do mapeamento entre o modelo de objetos e o esquema da base de dados. Dependendo da complexidade do modelo, esse arquivo pode ser trabalhoso de ser criado manualmente, mas existem formas de utilizar alguma ferramenta para cria-lo, o SQL Metal é uma delas conforme comentado acima no artigo.

Crie uma classe chamada ClienteDataContext , ela vai herdar de DataContext, o DataContext contém diversas propriedades e métodos que auxiliam na manipulação de base de dados, como por exemplo, verificar se uma base de dados existe, criar e excluir uma base de dados, entre outros, mais adiante vamos utilizar o método CreateDatabase() para criar fisicamente a base de dados local no Windows Phone.

A próxima etapa é criar a string de conexão com a base de dados, utilizaremos a palavra chave “isostore” para informar que o arquivo ficará no Isolated Storage, após isso informaremos o nome da base de dados como Cliente.sdf. É na string de conexão que você pode inserir um senha de acesso a base de dados, informar uma cultura específica ou até mesmo criar uma base de dados somente leitura, para mais informações sobre string de conexões para o WP7 acesse http://msdn.microsoft.com/en-us/library/hh202861(v=vs.92).aspx

Por último vamos definir uma tabela Cliente de acesso público e única no DataContext através de public Table Cliente.

No App.xaml.cs da aplicação , localize o construtor da classe e no final adicione o código abaixo, neste momento vamos criar uma base de dados usando o DataContext criado anteriormente, o código verifica se existe uma base de dados e caso não exista ele já cria uma nova base de dados.

using (ClienteDataContext ctx = new ClienteDataContext(ClienteDataContext.DBConnectionString))

? ? ?  if (ctx.DatabaseExists() == false)
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ?  ctx.CreateDatabase();
? ? ? ? ? ? ?  
? 
}

Para finalizar o artigo vou criar uma tela simples em Silverlight, sem se preocupar com o layout, a tela tem um botão chamado “add” que vai adicionar um registro na base de dados e logo abaixo um ListBox chamado “lst”, que está ligado através de databinding a propriedade ItemSource com uma ObservableCollection chamada Items, na propriedade Text vamos mostrar o nome do cliente também ligando através de databinding.


? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ? Grid.Row="1" Margin="12,0,12,0">
? ? ? ? ? ? ? ? ? ? ?  ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? 
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? 

No constructor do MainPage vamos criar uma instância do DataContext chamado clienteDB :

clienteDB = new ClienteDataContext(ClienteDataContext.DBConnectionString);

No evento ? Loaded da MainPage, realizamos um consulta LINQ to SQL e já adicionamos o resultado em uma ObservableCollections chamada Items, que está ligado ao ItemSource da ListBox, veja como é prático ligar as informações na tela, neste exemplo como o foco é o conceito de local database, o projeto foi criado todo no code-behind da MainPage, mas você poderia criar usando o ViewModel e ligando o ObservableCollection com a View.

var result = from Cliente r in clienteDB.Cliente
select r;
Items = new ObservableCollection(result);

Para mais informações sobre LINQ:

http://msdn.microsoft.com/en-us/library/bb397897.aspx

http://msdn.microsoft.com/en-us/library/bb386976.aspx

http://msdn.microsoft.com/en-us/library/bb386913.aspx

Vamos agora para o código do botão “add” que vai adicionar os registros na base de dados, através do InsertOnSubmit() adicionamos o objeto ao DataContext e através do SubmitChanges(), o objeto é registrado na base de dados, por último, inserimos o objeto na coleção para que seja apresentado na tela.

Cliente c = new Cliente();
c.Nome = txtNome.Text;
clienteDB.Cliente.InsertOnSubmit(c);
clienteDB.SubmitChanges();
Items.Add(c);

?

Código completo da MainPage:

? ?  public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
? ? ?  
? ? ? ? ? ? ? ?  ClienteDataContext clienteDB;
? ? ? ? ? ? ? ?  #region INotifyPropertyChanged Members
? ? ? ? ? ? ? ?  public event PropertyChangedEventHandler PropertyChanged;
? ? ? ? ? ? ? ?  private void NotifyPropertyChanged(string propertyName)
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  if (PropertyChanged != null)
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ?  }
? ? ? ? ? ? ? ?  #endregion
? ? ? 
? ? ? ? ? ? ?  private ObservableCollection _items;
? ? ? ? ? ? ?  public ObservableCollection Items
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  get
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  return _items;
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  set
? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  if (_items != value)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  _items = value;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  NotifyPropertyChanged("Items");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  }
? ? ? ? ? ? ?  }
? ? ? ? ? ? ? 
? ? ? ? ? ? ?  // Constructor
? ? ? ? ? ? ?  public MainPage()
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  InitializeComponent();
? ? ? ? ? ? ? ? ? ? ?  clienteDB = new ClienteDataContext(ClienteDataContext.DBConnectionString);
? ? ? ? ? ? ? ? ? ? ?  this.DataContext = this;
? ? ? ? ? ? ? ? ? ? ?  Loaded += new RoutedEventHandler(MainPage_Loaded);
? ? ? ? ? ? ?  
? ? ? ? ? ? ?  void MainPage_Loaded(object sender, RoutedEventArgs e)
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  var result = from Cliente r in clienteDB.Cliente
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  select r;
? ? ? ? ? ? ? ? ? ? ?  Items = new ObservableCollection(result);
? ? ? ? ? ? ?  
? ? ? ? ? ? ?  private void add_Click(object sender, RoutedEventArgs e)
? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ? ?  Cliente c = new Cliente();
? ? ? ? ? ? ? ? ? ? ?  c.Nome = txtNome.Text;
? ? ? ? ? ? ? ? ? ? ?  clienteDB.Cliente.InsertOnSubmit(c);
? ? ? ? ? ? ? ? ? ? ?  clienteDB.SubmitChanges();
? ? ? ? ? ? ? ? ? ? ?  Items.Add(c);
? ? ? ? ? ? ?  
? ? ?  }

Links:

Boas Práticas:

http://msdn.microsoft.com/en-us/library/hh286406(v=vs.92).aspx

Mais informações sobre local database no Windows Phone :

http://msdn.microsoft.com/en-us/library/hh202860(v=vs.92).aspx

http://msdn.microsoft.com/en-us/library/hh202876(v=VS.92).aspx

Alterações do esquema da base de dados:

http://msdn.microsoft.com/en-us/library/hh394018(v=VS.92).aspx

Ago 18

[ Adobe Flex Lib ][ GitHub ] Mudando o estilo visual dos Charts

Escrito por Erko Bridee em 1, 2.0, 3.5, 4, 6, action, Adobe, Adobe Flex, Air, api, AR, BI, blog, C#, class, classe, classes, código, custom, Estilo, Flex, Flex 4, git, Gráfico, ide, IE, image, imagens, mg, O, on, Ria’s Geral, S+S, screen, SDK, Twitter, UI @ 08 18th, 2011 | via http://blog.erkobridee.com | Sem comentários
Erko Bridee
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Ha algum tempo publiquei 2 códigos para customização das cores dos gráficos do Adobe Flex, então resolvi evoluir e disponibilizar uma lib para customizações das cores dos gráficos

Post anterior:? [ Adobe Flex ] Mudando o estilo visual dos Charts

Como está no título do post, criei um projeto Lib e um projeto para testar as customizações e publiquei no? GitHub: CustomChartLib? (Atenção: foi utilizado o Adobe Flex 4.5 SDK)

A lib atual conta com 4 classes:

- ColorHelper

Possui as definições de cores base, que serão utilizadas nas classes de customização.

- StylePieChart

- StyleAreaChart

- StyleColumnChart

Segue as imagens dos gráficos customizados:

PieChart

ColumnChart

AreaChart

Tweet

Veja também:

  • No Related Post
Jul 24

Princípios de Projeto OO – Single Responsibility Principle (SRP)

Escrito por Edgard Davidson em 1, 2.0, 4, 6, Agile, Air, api, AR, BI, blog, Blogs, boolean, C#, camp, class, classe, classes, dados, Design, Design Pattern, Design Patterns, Dica, for, ide, if, image, int, Java, mg, Microsoft, MSDN, O, on, pattern, POO, pt, RIA, Ria’s Geral, S+S, Software, TAT, UI, UML, zend @ 07 24th, 2011 | via http://edgarddavidson.com | Sem comentários
Edgard Davidson
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Princ?pio da ?nica Responsabilidade:

“Nunca deve haver mais de um motivo para uma classe ser alterada”

Cada responsabilidade constitui-se uma dimens?o de mudan?as. Se uma classe tem mais de uma responsabilidade, ent?o haver? mais de uma raz?o para alter?-la. Quanto mais responsabilidades h? numa classe, mais fr?gil (maior risco de para de funcionar) torna-se o projeto.

Viola??o do princ?pio:

Considere a Classe TAD:

import java.util.Vector;

/**
 *
 * @author Edgard Davidson
 */
public class TAD 

    private Vector vector;

    public TAD()
        vector = new Vector();

    public void empilhar(Object element)
        vector.insertElementAt(element, 0);

    public Object desempilhar()
        if (!this.eVazia())
            Object result = vector.firstElement();
            vector.removeElementAt(0);
            return result;
         else
            return null;

    }

    public void enfileirar(Object element)
        vector.add(element);

    public Object desenfileirar()
        if (!this.eVazia())
            Object result = vector.firstElement();
            vector.removeElementAt(0);
            return result;
         else
            return null;

    }

    public int obtemTamanho()
        return vector.size();

    public boolean eVazia()
        return vector.isEmpty();

}

Como pode ser visto, a classe TAD (Tipo Abstrato de Dados) ? uma classe que possui mais de uma responsabilidade. Ela implementa o contrato de um Pilha com os m?todos (empilha e desempilha) e o contrato de uma Fila com os m?todos (enfileira e desenfileira). A classe TAD viola o princ?pio da ?nica responsabilidade. Para se adequar ao princ?pio, ? necess?rio aplicar a refatora??o Extrair Classe. Essa t?cnica de refatora??o ? a mais indicada para o caso da viola??o do SRP. Sempre que houver uma classe fazendo o trabalho que deveria ser feito por duas classes, aplique a referida refatora??o para criar uma nova classe movendo os campos e m?todos pertinentes da classe antiga para a classe nova.

Al?m de aplicar a refatora??o Extrair Classe, na adequa??o ? viola??o do princ?pio, foi renomeado tamb?m a classe TAD, que n?o possuia um nome significativo ao seu contrato. Ap?s aplica??o de Refatora??o temos:

Adequa??o ao princ?pio:

Antes de mostrar a solu??o, a figura abaixo ilustra o contrato de uma Pilha e o contrato de uma Fila. Ambas s?o estruturas de dados com comportamentos diferenciados. A pilha implementa um algoritmo de LIFO (Last In, First Out), o ?ltimo a entrar ? o primeiro a sair. J? a fila implementa um algoritmo de FIFO (First In, First Out), o primeiro a entrar ? o primeiro a sair.

O diagrama de classe original foi refatorado e a classe TAD foi renomeada para Pilha e todos os m?todos referentes ao contrato de uma fila, ap?s aplicado o Extrair Classe e foram movidos para a classe Fila

Implementa??o da classe Pilha

import java.util.Vector;

/**
 *
 * @author Edgard Davidson
 */
public class Pilha 

    private Vector vector;

    public Pilha()
        vector = new Vector();

    public void empilhar(Object element)
        vector.insertElementAt(element, 0);

    public Object desempilhar()
        if (!this.eVazia())
            Object result = vector.firstElement();
            vector.removeElementAt(0);
            return result;
         else
            return null;

    }

    public int obtemTamanho()
        return vector.size();

    public boolean eVazia()
        return vector.isEmpty();

}

Implementa??o da classe Fila

import java.util.Vector;

/**
 *
 * @author Edgard Davidson
 */
public class Fila 

    private Vector vector;

    public Fila()
        vector = new Vector();

    public void enfileirar(Object element)
        vector.add(element);

    public Object desenfileirar()
        if (!this.eVazia())
            Object result = vector.firstElement();
            vector.removeElementAt(0);
            return result;
         else
            return null;

    }

    public int obtemTamanho()
        return vector.size();

    public boolean eVazia()
        return vector.isEmpty();

}

Com essa nova implementa??o, a classe Pilha e a classe Fila s?o extremamente coesas, possuem apenas um prop?sito, uma ?nica responsabilidade e apenas um contrato

Outras refer?ncias

  • http://engenhariadesoftwareagil.com/?p=236
  • http://www.objectmentor.com/resources/articles/srp.pdf
  • http://davidhayden.com/blog/dave/archive/2005/05/29/1066.aspx
  • http://c2.com/cgi/wiki?SingleResponsibilityPrinciple
  • http://msdn.microsoft.com/en-us/magazine/cc546578.aspx
  • http://codebetter.com/blogs/david_laribee/archive/2008/09/09/why-solid-gimme-an-s.aspx
  • Head First Design patterns. pags 185, 336, 339, 367
  • Agile Principles, Patterns, and Practices in C#.
  • UML for Java Programmers

« Entradas anteriores |

ACERCA

O que é o RedeRIA ?

O redeRIA não é nada mais que um agregador de feed's que disponibiliza o conteudo de varios blogs e autores ao redor do mundo RIA, actualmente agregamos mais de 2755 entradas vindas de 53 blogs especializados em ria’s, pelo que só fica a ganhar em assinar o feed ou seguir a comunidade no twitter.

Se acha que o seu blog ou um blog de um amigo é interessante e util para os leitores o redeRIA, faça a sua submissão aqui.

Feed: assine já
Twitter: siga-nos

GOOGLE

Votação


Deveria o RedeRia agregar conteúdo em inglês?
Ver Resultados

AUTORES


Eduardo KrausAlexandre TadashiBindableCognitiva SoluçõesDaniel LopesDaniel SchmitzDanielPedrinhaDClick TeamEbercomEdgard DavidsonElvis FernandesErko BrideeFabiel PrestesFábio Batista da SilvaFabio da SilvaFabriccio BernardesFelipe BorellaFlavia MoreiraGabriel VersalliniGabriela T. PerryIgor MusardoJanderson CardosoJoão AugustoJose Carlos FielKelps SousaLeonardo FrançaLucas MarçalLuis MessiasLuiz TarabalMario JuniorMário SantosMauro MartinsPablo SouzaPedro ClaudioreneRia BrazilriaPTRicardo CerqueiraRobson FernandesRodrigo Pereira FragaSaintBrSamuelFacchinelloSergio SouzaSilva DeveloperStefan HorochovecTech CaffeTecinforThiago BuenoVedVinícius SandimWillian ManoXAML Cast

PUBLICIDADE








Powered by Wordpress & msdevstudio.com