Salve galera.

Hoje vamos abordar uma forma simples de trabalhar com MVC no Flex com Eventos.

Primeiramente oque é MVC?

Com o aumento da complexidade das aplicações desenvolvidas torna-se fundamental a separação entre os dados (Model) e o layout (View). Esta forma permite que trabalhamos separadamente entre layout e manipulação de dados, tornando flexível alterações no layout sem afetar o Controller e vice-versa.

O MVC resolve um dos maiores problemas entre acoplamento das camadas de acesso a dados e lógica de negócio da aplicação e apresentação de dados ao usuário, pois introduz um componente entre as duas camadas (dados e interface) chamada Controller, o Design Patter MVC está mais ligado a arquitetura da aplicação do que um tipo de padrão de projeto, pois afeta a maneira de como a aplicação será organizada e estruturada.

O MVC não abrange a camada de acesso a dados, pois supõe-se que ela esteja encapsulada dentro do model.

OBS: Camadas dizem como separar os componentes, mas MVC diz como os componentes interagem entre si.

As camadas:

  • Model: A representação especifica da informação em que a aplicação trabalha. Por exemplo, cliente, fornecedor e produtos fazem parte do domínio de um sistema de PDV. Não confunda Model com outro nome da camada de dominio. Lógica de dominio apresenta traz maior sentido aos dados crus. Ex: Temos um cliente com um saldo de crédito X, e um histórico de compras e pagamentos, e criamos um método que percorre o histórico de compras do cliente e de pagamentos e nos devolve se podemos ou não aumentar o crédito do cliente, isso é chamada lógida de domínio, onde é agregado maior sentido aos dados propriamente ditos "crus".
  • View: A camada view é responsável por expor os dados a uma iteração com o usuário lendo do Model as informações necessárias.
  • Controller: Controller é onde ocorre todo o processamento, validações, manipulação de eventos e solicitações do usuário.

O diagrama representa as seguintes associações:

  • O controller conhece a view e o model.
  • A view conhece apenas o model.
modelviewcontrollerdiagram

Modelo MVC

Fluxo:

  1. Ocorre uma interação do usuário com a interface ( clique em um botão de listagem).
  2. O controller recebe a solicitação pois havia sido previamente definido em uma rotina a manipulação do evento no proprio controller.
  3. O controller acessa o model baseado na interação do usuário.
  4. A view utiliza o model para gerar a interface( na maioria dos casos exibir os dados ou requisições do usuário),  a view obtem os dados do model sem que ele tenha conhecimento da camada de apresentação.
  5. A view espera as próximas interações do usuário e o ciclo se inicia.

Bem vamos a parte prática:

Crie a seguinte estrutura de pacotes:

pacotes_exemplo_flex

Agora vamos criar os componentes MXML dentro do pacote view:


<?xml version="1.0" encoding="utf-8"?>
<mx:Panel title="Listagem" creationComplete="init()" xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:List id="list" width="100%" dataProvider="{model.clients}" labelField="name" height="100%" />
<mx:ApplicationControlBar>
<mx:Button id="btList" label="Listar" />
<mx:Button id="btClear" label="Limpar" />
</mx:ApplicationControlBar>
<mx:Script>
<![CDATA[
import br.com.ronaldorigoni.controller.ListagemController;
import br.com.ronaldorigoni.model.ListagemModel;
[Bindable]
public var model:ListagemModel = null;
public var controller:ListagemController = null;

private function init():void{
model = new ListagemModel();
controller = new ListagemController(this);
}
]]>
</mx:Script>
</mx:Panel>

Sublistagem.mlxml


<?xml version="1.0" encoding="utf-8"?>
<mx:Panel title="Sublistagem" creationComplete="init()" xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:Form>
<mx:FormItem label="ID:">
<mx:TextInput editable="false" id="clientId" text="{model.client.id}" />
</mx:FormItem>
<mx:FormItem label="Name">
<mx:TextInput editable="false" id="clientName" text="{model.client.name}"/>
</mx:FormItem>
</mx:Form>
<mx:Script>
<![CDATA[
import br.com.ronaldorigoni.controller.SublistagemController;
import br.com.ronaldorigoni.model.SublistagemModel;
[Bindable]
public var model:SublistagemModel = null;
public var controller:SublistagemController = null;

private function init():void{
model = new SublistagemModel();
controller = new SublistagemController(this);
}
]]>
</mx:Script>
</mx:Panel>

Em seguida criaremos os controllers para cada componente da camada view:

ListagemController.as


package br.com.ronaldorigoni.controller{
import br.com.ronaldorigoni.event.ListagemEvento;
import br.com.ronaldorigoni.view.Listagem;
import br.com.ronaldorigoni.vo.Client;

import flash.events.MouseEvent;

import mx.collections.ArrayCollection;
import mx.events.ListEvent;

public class ListagemController{
// instancia da camada view para o controller poder manipulá-la
private var view:Listagem = null;
/**
* Contrutor do controller
* @param _view A instancia da view
*/
public function ListagemController(_view:Listagem){
// atribue a instancia da view a instancia local
this.view = _view;
// adiciona evento de clique para listar clientes
view.btList.addEventListener(MouseEvent.CLICK, listClients);
// adiciona evento para limpar a listagem de clientes
view.btClear.addEventListener(MouseEvent.CLICK, clearClients);
// adiciona evento de selecao de um cliente
this.view.list.addEventListener(ListEvent.ITEM_CLICK, dispatchEvent);
}
/**
* Invoca preenchimento do modelo de clientes.
* Lembrando que em uma aplicacao real isso deve ser
* feito por uma linguagem de servidor, geralmente com acesso
* a banco de dados.
*/
private function listClients(event:MouseEvent):void{
fillClients();
}

/**
* Limpa a lista de clientes.
*/
private function clearClients(event:MouseEvent):void{
view.model.clearModel();
}

/**
* Preenche a lista de clientes.
* Sendo quem em uma aplicação real estes dados devem ser alimentados
* por uma linguagem de servidor.         *
*/
private function fillClients():void{
for(var i:int = 0; i < 10; i ++){
var client:Client = new Client();
client.name = "Client "+i;
client.id = i;
view.model.addClient(client);
}
}

/**
* Dispara um evento para o componente pai da listagem, e este
* terá adicionado os listeners para este tipo de evento.
* Onde fará a invocação das funcoes.
*/
private function dispatchEvent(event:ListEvent):void{
// setando o cliente selecionado dentro do modelo de listagem
view.model.selected = view.list.selectedItem as Client;
var listagemEvento:ListagemEvento =    new ListagemEvento(ListagemEvento.EVENT_CLIENT_SELECTED);
// inserindo dentro do objeto de evento o cliente selecionado.
listagemEvento.sublistagemModel.client = view.model.selected;
// invoca o componente pai da view no caso a application
// para disparar um evento, sendo que nela esta definido um ouvinte para este
// tipo de evento, e a funcao será invocada, internamente no evento existe os dados
// que a visão necessita para exibir.
view.parent.dispatchEvent(listagemEvento);
}
}
}

SublistagemController.as


package br.com.ronaldorigoni.controller{
import br.com.ronaldorigoni.event.ListagemEvento;
import br.com.ronaldorigoni.view.Sublistagem;

import mx.controls.Alert;
public class SublistagemController{

/**
* Instancia da camada view
*/
private var view:Sublistagem = null;

/**
* Construtor do controller, recebe instancia da camada view para
* poder manipulá-la
*/
public function SublistagemController(_view:Sublistagem){
view = _view;
}
/**
* Manipula o evento de cliente selecionado.
*/
public function handleEventSelected(event:ListagemEvento):void{
// seta o titulo do painel de sublistagem
view.title = "Sublistagem       Evento recebido:"+event.type;
// seta o model da sublistagem
// quando o model é setado ele é automaticamente renderizado
// na view, pois está marcado com o [Bindable]
view.model = event.sublistagemModel;
}
}
}

Agora vamos criar as Classes de Modelo para os dois componentes visuais da camada View:

ListagemModel.as


package br.com.ronaldorigoni.model{
import br.com.ronaldorigoni.vo.Client;

import mx.collections.ArrayCollection;

public class ListagemModel{
/**
* Array de clientes que será exibido na listagem.
*/
private var _clients:ArrayCollection = new ArrayCollection();
private var _selected:Client;

public function ListagemModel(){
}
/**
* Defina o arrayCollection de clientes.
*/
public function set clients(clients:ArrayCollection):void{
this._clients = clients;
}
/**
* Retorna o arrayCollection de clientes
*/
public function get clients():ArrayCollection{
return _clients;
}
/**
* Limpa o array de clientes.
*/
public function clearModel():void{
this._clients.removeAll();
}
public function addClient(client:Client):void{
_clients.addItem(client);
}

public function set selected(selected:Client):void{
this._selected = selected;
}
public function get selected():Client{
return _selected;
}
}
}

E SublistagemModel.as


package br.com.ronaldorigoni.model{
import br.com.ronaldorigoni.vo.Client;

public class SublistagemModel{

/**
* Representa o cliente atualmente selecionado.
*/
private var _client:Client = new Client();

public function SublistagemModel(){
}

/**
* Seta o cliente atualmente selecionado.
*/
public function set client(client:Client):void{
this._client = client;
}
/**
* Recupera o cliente atual selecionado.
*/
public function get client():Client{
return _client;
}
}
}

Agora vamos criar a classe de Eventos que armazenará uma instância de SublistagemModel para notificar o controller de Sublistagem.

</pre>
package br.com.ronaldorigoni.event{
import br.com.ronaldorigoni.model.SublistagemModel;

import flash.events.Event;
/**
* Classe de eventos para operacoes de listagem.
* Armazena o cliente atual selecionado.
*/
public class ListagemEvento extends Event{

/**
* Representa um evendo de cliente selecionado.
*/
public static const EVENT_CLIENT_SELECTED:String = "clientSelected";

private var _sublistagemModel:SublistagemModel = new SublistagemModel();
public function ListagemEvento(tipo:String){
super(tipo,true);
}
/**
* Define o modelo selecionado a sublistagem
*/
public function set sublistagemModel(sublistagemModel:SublistagemModel):void{
this._sublistagemModel = sublistagemModel;
}
/**
* Recupera o modelo da sublistagem
*/
public function get sublistagemModel():SublistagemModel{
return _sublistagemModel;
}
}
}

Esta classe de evento mantem uma propriedade do tipo cliente que alimentará o model de Sublistagem.

Agora vamos criar a classe de VO Client.as, que armazena as informações de cada cliente.


package br.com.ronaldorigoni.vo{
/**
* VO de cliente.
*/
public class Client{

private var _id:uint;
private var _name:String;

public function Client(){
}
/**
* seta o nome do cliente
*/
public function set name(name:String):void{
this._name = name;
}
/**
* Seta o id do cliente;
*/
public function set id(id:uint):void{
this._id = id;
}
/**
* Retorna o atual nome do cliente
*/
public function get name():String{
return _name;
}
/**
* Retorna o id do cliente
*/
public function get id():uint{
return _id;
}
}
}

E por fim nosso código do nosso application ExemploMVC.mxml:


<?xml version="1.0" encoding="utf-8"?>
<mx:Application creationComplete="init()" xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" xmlns:view="br.com.ronaldorigoni.view.*">
<mx:HBox>
<view:Listagem id="listagem"/>
<view:Sublistagem id="sublistagem"/>
</mx:HBox>
<mx:Script>
<![CDATA[
import br.com.ronaldorigoni.event.ListagemEvento;
/**
* Funcao é disparada quando a aplicacao terminar de carregar.
*/
private function init():void{
/**
* Adiciona o listener de evento, para quando for disparado um
* evento deste tipo a funcao para manipular seja invocada.
*/
addEventListener(ListagemEvento.EVENT_CLIENT_SELECTED,
sublistagem.controller.handleEventSelected);
}
]]>
</mx:Script>
</mx:Application>

No application tem um listener adicionado para quando for disparado um evento do tipo "ListagemEvento.EVENT_CLIENT_SELECTED", que dispara a função "SublistagemConroller.handleEventSelected", que captura dentro do evento o cliente selecionado atravéz da propriedade "selected", e atualiza o modelo de sublistagem fazendo com que o cliente selecionado chege até a sublistagem sem que os componentes esteja acoplados.

Para testarmos o funcionamento rode a aplicação como Flex Application, clique sobre "Listar", onde o controller manipula este clique e lista os clientes, quando for clicado sobre um cliente na List da Listagem.mxml será criado uma instância de ListagemEvento e adicionado o Client selecionado dentro deste evento e é disparado através do componente pai de Listagem.xml o evento criado, como temos um listener para este tipo de evento em ExemploMVC.mxml ele dispara a função com este evento como um parâmetro, e la é feita a manipulação e atualização do model de Sublistagem.

A grande vantagem de se programar desta forma é que os componentes não ficam acoplados e não se conhecem em tempo de compilação. Já esta estrutura de MVC permite que possamos futuramente efetuar alterações em cada camada sem que outra camada seja afetada ou alterado o funcionamento. Ex, se precisarmos alterar o layout da aplicação o controller não precisa saber disso.

Com o uso da anotação de metadados "Bindable", nos modelos dentro da view, faz com que qualquer alteração pelo Controller sobre o model ela seja automaticamente exibida na camada view, e no caso inverso, quando o usuário altera algum dado apresentado na camada view, ele já é autimaticamente atualizado no model, sendo assim o controller tem total controle sobre a exibição e alteração dos dados.

Aparentemente com esta estrutura temos mais código, mas isso é relativamente incomparável quando for um sistema relativamente grande e que necessite de constante manutenção, pois será alterado apenas as partes que necessitam sem afetar as demais.

Todas as classes estão comentadas e explicadas, qualquer dúvida crítica ou sugestão me escreva ronaldo arroba ronaldorigoni.com.br

Segue link para download do projeto.

Abraços e até um próximo post.

Monday, May 11, 2009Singleton em Java

Simples post para demonstrar o uso do Design Pattern Singleton em Java.

Assegura que uma determinada classe tenha apenas uma única instância, e apenas um meio de acesso a mesma.

Por exemplo em um sistema operacional é o uso de impressoras, temos vários clientes conectados a impressora, mas a mesma possui apenas um spool de documentos.

Segundo Gof temos o diagrama abaixo:

singleton_gofE como codificar isso? Imagine um cenário seguinte, precisamos desenvolver um chat entre múltiplos clientes,

onde todos podem se comunicar com todos, de que forma podemos implementar e assegurar que todos os usuários do nosso chat acessem exclusivamente a mesma instância da classe?


package br.com.ronaldorigoni.singleton;
/**
* Exemplo de Singleton - ChatRoom
* @author ronaldorigoni.com.br
*/
public class ChatRoom {
/**
* Única instancia da sala de bate papo, deve ser privada para
* não permitir acesso direto.
*/
private static ChatRoom instance = null;

/**
* Construtor privado para não permitir a
* criação de novas instancias da classe.
*/
private ChatRoom(){
// aqui codigo para a inicialização do chat.
// verifica configurações em banco ou outras
// operações.
}
/**
* Única forma de acesso para a instancia "instance" da classe
* @return  - A única instância da sala de Chat
*/
public static ChatRoom getInstance(){
if(instance == null)
instance = new ChatRoom();
return instance;
}

}

Através do método getInstance(), qualquer cliente tem apenas uma forma de acesso e em uma única instancia da sala de Chat.

Agora criaremos um método writeMessage(String message):


/**
* Envia uma mensagem a todos os usuários
* @param message
*/
public void writeMessage(String message){
for(User user : userList){
user.sendMessage(message);
}
}

Mesmo o método sendo public, só conseguiremos acessar ele através de uma instancia da classe desta forma:


ChatRoom.getInstance().writeMessage("Mensagem de teste");

Mas cuidado, em um ambiente MultiThread não está seguro que existe apenas uma instancia da classe, se em um determinado momento duas threads acessarem o método getInstance() ao mesmo tempo será criada duas instancias.

Como bloquear isso?  Adicionaremos um bloco s no método getInstance(), desta forma garantimos que toda Thread que entrar neste bloco irá bloquear o objeto instance para si mesmo, e só fará o desbloqueio quando o bloco de código terminar, assim uma vez desbloqueado estará disponível para uma nova thread utilizar.


public static ChatRoom getInstance() {

// garante que apenas uma thread por vez

// executará este bloco de código
synchronized (instance) {
if (instance == null)
instance = new ChatRoom();
}
return instance;
}

Para deixarmos nosso exemplo mais seguro, muitos desenvolvedores acham este método bizarro, mas eu o utilizei varias vezes, altere o método getInstance() para o modificador de acesso private, em seguida crie uma classe interna conforme abaixo, esta classe deve ser public static abstract, mas espere aí? Classe estatica é possível? Sim classe static é possível desde que a mesma seja aninhada ( classe interna).


private static ChatRoom getInstance() {
synchronized (instance) {
if (instance == null)
instance = new ChatRoom();
}
return instance;
}

E agora nossa classe interna aninhada:


public abstract static class ChatRoomHolder{
public static ChatRoom getInstance(){
return ChatRoom.getInstance();
}
}

Repare que a classe é abstrata, com isso fica impossível instanciá-la, mas por ela ser interna ela tem acesso aos métodos private de nossa ChatRoom, invoca o método getInstance() e retorna a instancia criada no construtor.

Desta forma estamos garantindo de duas maneiras que a classe ChatRoom tenha apenas uma única instancia:

  • Com o uso de construtor privado e um bloco sincronizado no método getInstance().
  • Com o uso de uma classe abstrata interna que não permite ser instanciada por ser abstrata.

Singleton pode ser aplicado em diversos casos, ( conexão a banco de dados, mecanismo de Log, Objetos de configuração, etc…).

Dúvidas, ronaldo@ronaldorigoni.com.br

Até um próximo post.

Monday, May 4, 2009Observer em Java

Salve galera.
Hoje iremos abordar um padrão de projeto designado Observer.
Observer é um padrão de projeto que se caracteriza em uma associação 1 x N entre objetos. Em que quando um dos objetos muda de estado ou característica, todos os objetos relacionados sejam notificados.
Um objeto do lado 1 da relação deve permitir acesso a seus elementos sem que sua estrutura interna seja exposta.
Como podemos implementar de uma forma abstrata e sem acoplamento a relação, sendo que qualquer alteração no objeto todos os seus relacionados sejam notificados  e que eles não se conhecem em tempo de compilação?

Devemos ter em mente os seguintes requisitos:

  • Os objetos relacionados devem conhecer o objeto de interesse, mas não devem estar
  • O objeto de interesse ( lado 1 da relação), deve notificar os objetos relacionados e interessados sobre ocorrência modificações.

Deve ser implementado de uma forma que os objetos não se conheçam em tempo de compilação, possibilitando acoplamento em tempo de execução e desfazê-lo a qualquer momento.

Aplicabilidade do padrão é quando necessitamos encapsular dois objetos por uma interface em que eles não se conheçam, sendo assim eles ficam completamente desacoplados, possibilitando o reuso separadamente de cada objeto.

Bem, vamos ao que interessa.

Imagine a seguinte situação de envio de email.

  • O remetente deseja saber quando o email chegou a caixa postal do destinatário e também saber quando o email foi lido.
  • O destinatário deseja saber quando chegou um novo email na caixa postal.

Como podemos implementar isso sem que destinatário e remetente estejam acoplados?

Primeiramente criaremos uma classe EmailEvent que representará os eventos ocorridos sobre um email.


package br.com.ronaldorigoni.observer;

/**
* Classe EmailEvent, representa todo e qualquer evento ocorrido com um email.
* Classe herda de java.util.EventObject para podermos manipular o método
* getSource(), que nos devolve o email que ocorreu o evento.
*
* @author ronaldorigoni.com.br
*/
public class EmailEvent extends java.util.EventObject {

public EmailEvent(Object source) {
super(source);
}

}

Em seguida deveremos criar uma interface EmailListener que será implementada pelo Remetente e Destinatário, que será através dela que eles serão notificados.


package br.com.ronaldorigoni.observer;

/**
* Interface de Listeners para email.
* @author ronaldorigoni.com.br
*
*/
public interface EmailListener {
public void emailRecebido(EmailEvent emailEvent);
public void emailLido(EmailEvent emailEvent);
}

Agora criaremos a classe Email, conforme abaixo.


package br.com.ronaldorigoni.observer;

import java.util.ArrayList;
import java.util.Collection;

/**
* Representa um email.
*
* @author ronaldorigoni.com.br
*
*/
public class Email {
/**
* Lista de objetos interessados nos eventos ocorridos com um email.
*/
private Collection<EmailListener> emailListeners =
new ArrayList<EmailListener>();

/**
* Envia um email.
*
* @param email
*/
public void enviar() {
disparaEmailRecebido();
disparaEmailLido();
}

/**
* Dispara um evento quando este email for recebido.
*/
public void emailRecebido() {
this.disparaEmailRecebido();
}

/**
* Dispara um evento quando este email for lido.
*/
public void emailLido() {
this.disparaEmailLido();
}

/**
* Método sincronizado para impedir que seja adicionado o mesmo listener
* mais de uma vez.
*
* @param emailListener
*            - o Listener
*/
public synchronized void addEmailListener(EmailListener emailListener) {
this.emailListeners.add(emailListener);
}

/**
* Remove um listener.
*
* @param emailListener
*            O listener.
*/
public synchronized void removeEmailListener(EmailListener emailListener) {
this.emailListeners.remove(emailListener);
}

/**
* Notifica todos os listeners que um email foi lido.
*/
private void disparaEmailLido() {
// criando um evento do próprio email
EmailEvent event = new EmailEvent(this);
// iterando sobre todos os listeners
// para notificar evento de email lido.
for (EmailListener listener : emailListeners) {
listener.emailLido(event);
}
}

/**
* Notifica todos os listeners que um email foi recebido.
*/
private void disparaEmailRecebido() {
// criando um evento do próprio email
EmailEvent event = new EmailEvent(this);
// iterando sobre todos os listeners
// para notificar evento de email recebido.
for (EmailListener listener : emailListeners) {
listener.emailRecebido(event);
}
}

}

Em seguida criaremos as classes Remetente e Destinatario, que deverão implementar a interface EmailListeners pois se tratam de interessados nos eventos ocorridos sobre os emails.


package br.com.ronaldorigoni.observer;

/**
* Representa um destinatário para um email.
* @author ronaldorigoni.com.br
*
*/
public class Destinatario implements EmailListener {

@Override
public void emailLido(EmailEvent emailEvent) {
Email email = (Email) emailEvent.getSource();
System.out.println("DESTINATÁRIO: Você acabou de ler o email:" + email + ".");
}

@Override
public void emailRecebido(EmailEvent emailEvent) {
Email email = (Email) emailEvent.getSource();
System.out.println("DESTINATÁRIO: Você acabou de receber um novo email:"+email);
}

}

E a classe Remetente.


package br.com.ronaldorigoni.observer;

/**
* Representa um
* @author ronaldorigoni.com.br
*
*/
public class Remetente implements EmailListener {

@Override
public void emailLido(EmailEvent emailEvent) {
Email email = (Email) emailEvent.getSource();
System.out.println("REMETENTE: O email " + email + " acaba de ser lido.");
}

@Override
public void emailRecebido(EmailEvent emailEvent) {
Email email = (Email) emailEvent.getSource();
System.out.println("REMETENTE: O email " + email
+ " acaba de ser recebido pelo destinatário.");
}

}

Agora criaremos a classe CaixaPostal que é onde a nossa brincadeira acontece.


package br.com.ronaldorigoni.observer;

/**
* Representa uma caixa postal para teste sobre emails.
* @author ronaldorigoni.com.br
*
*/
public class CaixaPostal {
public static void main(String[] args) {
// criando dois emails
Email email1 = new Email();
Email email2 = new Email();
// criando destinatário e remetente
Destinatario destinatario = new Destinatario();
Remetente remetente = new Remetente();
// Adicionaodo os listeners aos emails
email1.addEmailListener(destinatario);
email1.addEmailListener(remetente);

email2.addEmailListener(destinatario);
email2.addEmailListener(remetente);
/**
* Aqui é onde tudo acontece, brinque com os codigos abaixo,
* comente e descomente as linhas.
*/
email1.enviar();

email2.emailRecebido();
//email2.emailLido();
}
}

Execute o arquivo CaixaPostal.java e veja que quando um email é enviado tanto o remetente quando o destinatário são notificados nenhum conhece a implementação do outro.

Segue aqui o aqui para download do projeto

Bom por hoje fico por aqui, qualquer duvidas ou sugestões segue meu email ronaldo@ronaldorigoni.com.br

Até um próximo post.

Get Adobe Flash playerPlugin by wpburn.com wordpress themes

© 2007 Ronaldo Rigoni | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress