Author Archives: sutradi

Bysutradi

Criando um Spinner customizado com valores preenchidos por enum

O uso de Spinners em aplicativos Android é muito comum e isso pode ser feito de muitas maneiras, seguinte a rotina: crie o spinner, passe a lista, crie o adapter, crie o layout, etc.

Em alguns casos, tais Spinners são preenchidos com informações de domínio fechado.

Diante desta necessidade, é possível usar classes do tipo enum para preencher os valores em um Spinner customizado.

Neste tutorial, mostrarei como fazer isso criando algumas classes.

Vamos começar pela interface, para padronizar as classes enum.

public interface SpinnerEnum {

   public long getId();
   public String getNome();
   public Object[] listar();
}

Usaremos esta interface em todas as nossas futuras classes de enum.

O que precisamos agora é de nosso Adapter.

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import com.sutradi.lib.drawer.DatabaseModel;

import java.util.List;

public class SpinnerAdapter extends ArrayAdapter<DatabaseModel> {

	private final Context contexto;
	private final List<DatabaseModel> lista;
	DatabaseModel tempValues = null;
	int textViewID;
	int textViewNome;
	int spinnerLayoutID;

	/**
	 * Construtor.
	 * @param contexto
	 * @param listaObjetos
	 * @param spinnerLayout Layout que contenha 02 objetos TextView para ID e Nome
	 * @param _textViewID TextView para armazenar o ID
	 * @param _textViewNome TextView para armazenar o Nome
	 */
	public SpinnerAdapter(Context contexto, List<DatabaseModel> listaObjetos,
			int spinnerLayout, int _textViewID, int _textViewNome) {

		super(contexto, spinnerLayout, listaObjetos);
		this.contexto = contexto;
		this.lista = listaObjetos;
		this.textViewID = _textViewID;
		this.textViewNome = _textViewNome;
		this.spinnerLayoutID = spinnerLayout;
	}

	@Override
	public View getDropDownView(int position, View convertView, ViewGroup parent) {
		return getCustomView(position, convertView, parent);
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		return getCustomView(position, convertView, parent);
	}

	public View getCustomView(int position, View convertView, ViewGroup parent) {
		LayoutInflater inflater = (LayoutInflater) contexto
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View rowView = inflater.inflate(spinnerLayoutID, parent, false);
		tempValues = null;
		tempValues = (DatabaseModel) lista.get(position);

		TextView viewID = (TextView) rowView.findViewById(textViewID);
		TextView viewNome = (TextView) rowView.findViewById(textViewNome);
		viewID.setText(tempValues.getId());
		viewNome.setText(tempValues.getNome());

		return rowView;
	}
}

Em nosso Adapter, informaremos o ID para o layout e os IDs para os campos que representação o ID e Nome que serão usados no Spinner.

public SpinnerAdapter(Context contexto, List<DatabaseModel> listaObjetos,
			int spinnerLayout, int _textViewID, int _textViewNome) {

Essa implementação permitirá que você crie layouts diferentes para o Spinner. Caso queira padronizar o Spinner, basta remover estas informações do construtor e definir as informações corretas na implementação em getCustomView.

A classe DatabaseModel deve conter uma implementação POJO que contém ID e Nome. Bem simples.

Agora que temos o Adapter definido, vamos criar nosso Spinner customizado.

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Spinner;

import com.sutradi.lib.drawer.DatabaseModel;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Classe de apoio para uso de Spinners que apresentam somente Texto, carregando
 * dados a partir de um Enum (que deve extender à SpinnerEnum) O layout do
 * spinner deve ter somente um EditText para ID (hide) e outro para Nome.
 *
 * @author SUTRADI
 */
public class SpinnerUI extends Spinner {
    ArrayList<DatabaseModel> lista = null;

    /**
     * Construtor.
     *
     * @param _context
     */
    public SpinnerUI(Context _context) {
        super(_context);
    }

    /**
     * Construtor.
     *
     * @param _context
     * @param _attrs
     * @param _defStyle
     * @param _mode
     */
    public SpinnerUI(Context _context, AttributeSet _attrs, int _defStyle,
                     int _mode) {
        super(_context, _attrs, _defStyle, _mode);
    }

    /**
     * Construtor.
     *
     * @param _context
     * @param _attrs
     * @param _defStyle
     */
    public SpinnerUI(Context _context, AttributeSet _attrs, int _defStyle) {
        super(_context, _attrs, _defStyle);
    }

    /**
     * Construtor.
     *
     * @param _context
     * @param _attrs
     */
    public SpinnerUI(Context _context, AttributeSet _attrs) {
        super(_context, _attrs);
    }

    /**
     * Construtor.
     *
     * @param _context
     * @param _mode
     */
    public SpinnerUI(Context _context, int _mode) {
        super(_context, _mode);
    }

    /**
     * @param context
     * @param spinnerText
     * @param listaEnum
     * @param spinnerLayout
     * @param spinnerItemId
     * @param spinnerItemNome
     */
    public void loadSpinner(Context context, String spinnerText,
                            SpinnerEnum[] listaEnum, int spinnerLayout, int spinnerItemId,
                            int spinnerItemNome, SpinnerEnum... enumIgnorar) {

        ArrayList<DatabaseModel> listaDatabaseModel = montaLista(spinnerText,
                listaEnum, enumIgnorar);

        SpinnerAdapter msa = new SpinnerAdapter(context, listaDatabaseModel,
                spinnerLayout, spinnerItemId, spinnerItemNome);

        this.setAdapter(msa);

    }

    /**
     * @param labelPrimeiro
     * @param listaEnum
     * @return
     */
    private ArrayList<DatabaseModel> montaLista(final String labelPrimeiro,
                                                SpinnerEnum[] listaEnum, SpinnerEnum... enumIgnorar) {
        List<SpinnerEnum> temp = new ArrayList<SpinnerEnum>(Arrays.asList(listaEnum));

        for(SpinnerEnum e : enumIgnorar) {
            temp.remove(e);
        }
        lista = new ArrayList<DatabaseModel>();
        lista.add(new DatabaseModel("0", labelPrimeiro));
        for (SpinnerEnum obj : temp) {
            DatabaseModel dm = new DatabaseModel(String.valueOf(obj.getId()),
                    obj.getNome());
            lista.add(dm);
        }

        return lista;
    }

}

A implementação pública loadSpinner será a responsável por receber as informações necessárias para o preenchimento do Spinner, com base nas necessidades do SpinnerAdapter. Notem que além de informar a lista de nossa interface SpinnerEnum, também é necessário informar os IDs do layout, ID e Nome. De quebra, é possível também passarmos uma lista de itens do SpinnerEnum que não queremos que seja adicionado.

public void loadSpinner(Context context, String spinnerText,
                            SpinnerEnum[] listaEnum, int spinnerLayout, int spinnerItemId,
                            int spinnerItemNome, SpinnerEnum... enumIgnorar) {

A implementação privada montaLista conterá toda a lógica para o preenchimento do Spinner. Note que o primeiro elemento terá o valor “0” sempre.

E como podemos usar este SpinnerUI ?

SpinnerUI spinner = (SpinnerUI) view.findViewById(R.id.spinnerUI_despesas);
        spinner.loadSpinner(getActivity(), getString(R.string.despesaSelecionar), DespesaEnum.getSortedVaules(), R.layout.spinner_ui, R.id.spinnerUI_id, R.id.spinnerUI_nome, DespesaEnum.ABASTECIMENTO, DespesaEnum.TROCA_OLEO, DespesaEnum.REVISAO);

E como implementamos nossas classes do tipo enum? Veja uma implementação simples abaixo.

import com.sutradi.lib.ui.spinner.SpinnerEnum;

import java.util.Arrays;
import java.util.Comparator;

public enum DespesaEnum implements SpinnerEnum {

	REVISAO(1, "Revisão"), 
	ABASTECIMENTO(2, "Abastecimento"), 
	TROCA_OLEO(3,"Troca de Óleo"), 
	MANUTENCAO(4, "Manutenção / Mecânica"), 
	OUTRA(99, "Outras");

	private long id;
	private String nome;

	DespesaEnum(long _id, String _nome) {
		this.id = _id;
		this.nome = _nome;
	}

	public static DespesaEnum getById(long id) {
		for (DespesaEnum item : DespesaEnum.values()) {
			if (item.getId() == id) {
				return item;
			}
		}
		return DespesaEnum.OUTRA;
	}

	/**
	 * @return the id
	 */
	public long getId() {
		return id;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(long id) {
		this.id = id;
	}

	/**
	 * @return the nome
	 */
	public String getNome() {
		return nome;
	}

	/**
	 * @param nome
	 *            the nome to set
	 */
	public void setNome(String nome) {
		this.nome = nome;
	}

	@Override
	public Object[] listar() {
		return DespesaEnum.values();
	}
	
	public static DespesaEnum[] getSortedVaules(DespesaEnum... ignore) {
		DespesaEnum[] statures = values();
		Arrays.sort(statures, EnumByNameComparator.INSTANCE);
		return statures;
	}

	private static class EnumByNameComparator implements Comparator<Enum<?>> {
		public static final Comparator<Enum<?>> INSTANCE = new EnumByNameComparator();
		public int compare(Enum<?> enum1, Enum<?> enum2) {
			return enum1.name().compareTo(enum2.name());
		}
	}

}

Você será obrigado a implementar os métodos getId e getNome, que farão a ligação com os elementos no layout do Spinner.

Você pode adicionar mais atributos na interface SpinnerEnum e enriquecer sua implementação.

Bysutradi

Remover um Database no Oracle 11g sem usar o Console de Administração (dbca)

Se você, por algum motivo que só Deus consiga explicar, não conseguir fazer a remoção de um Database por vias normais usando o Console de Administração (dbca), faça o seguinte:

  • Exporte o ORACLE_SID para o Database que quer remover.

  • Acesse o SQL Plus (escrevo SQL Plux toda vez… não faço idéia pq) sem autenticação.

  • Autentique como SYS e faça o shutdown no Database

  • Pare o Listener

  • Remova os diretórios, arquivos e configurações da Database

Edite o arquivo $ORACLE_HOME/network/admin/tnsnames.ora e remova o trecho referente à base de dados
Vá ao diretório $ORACLE_HOME/dbs e remova os arquivos e diretórios referentes à base de dados
Vá ao diretório $ORACLE_HOME/admin e remova os arquivos e diretórios referentes à base de dados
Vá ao diretório $ORACLE_HOME/oradata e remova os arquivos e diretórios referentes à base de dados
Edite o arquivo /etc/oratab e remova a linha referente à base de dados

  • Inicie o Listenet

Bysutradi

Usando o RFHUtil

Para instalar e usar o RFHUtil para testar o envio de mensagens para o Barramento (MQ), execute os passos abaixo:

Faça o download e instalação do MQ Client na mesma versão do MQ. Basta descompactar o ZIP em alguma pasta temporária e executar o comando “setup” na pasta “Windows”. Não é necessário alterar nenhum parâmetro.

Faça o download do RFHUtil no site da IBM e descompacte o ZIP no local definitivo para uso da ferramenta.

Para acessar o ambiente das filas remotamente, é preciso de a variável de ambiente MQSERVER. Veja 2 exemplos abaixo:

Execute o programa “rfhutilc.exe” contido no diretório do RFHUtil.

Para enviar uma mensagem, preencha o Queue Manager Name e o Queue Name.

Clique em “Open File”, selecione o arquivo XML que compõe a mensagem a ser enviada e clique no botão “Write Q”. As mensagens são exibidas como no quadro abaixo, indicando sucesso.

Bysutradi

Personalization aplicado à apresentação de menus no Portal

As vezes nos deparamos com solicitações que nos fazem implementar soluções complementares para chegar ao resultado esperado.
Não diferente disso, precisei fazer com que o menu principal criado no WebSphere Portal tivesse o seguinte comportamento: quando o usuário não tiver permissão de acesso a uma página, o menu deve ser apresentado em cinza sem ação de mouse (e não direcionar para a página de destino). Quando o usuário tiver permissão, deve apresentar a página com os portlets. Resumindo: alguns usuários visualizarão a página “Exemplo” que conterá portlets e outros visualização um rótulo “Exemplo”, em cinza, que não possui link.
Porém, este é um comportamento diferente do padrão do produto: quando você não tem acesso a algo, este algo não é carregado/exibido.

Qual a solução encontrada?

A solução que encontramos foi usar o recurso de Personalization (que sobrepões as regras de acesso por usuários/grupos), criando regras opostas aplicadas nas duas páginas com o mesmo nome. Na página “Exemplo” (que contém os portlets) foram aplicadas as regras de permissão normal (com os grupos de acesso normais). Na página “Exemplo” (com mesmo nome, mas sem acesso aos portlets), aplicamos uma regra de personalização oposta à regra aplicada na página “Exemplo” (que contém os portlets) e adicionamos um parâmetro para que o tema possa saber que deve ser criado na cor cinza. A tratativa de exibição em cinza foi feita no tema.