Sugestões para uma classe CNPJ

Estou criando uma classe CNPJ (Object Value) e se possivel estava querendo algumas sugestões… estou tentando deixar ela bem abrangente…

vou por aqui o link para o javadoc … e colar o código fonte… ela usa algumas outras classes da minha API

Java Doc: http://www.simrentacar.com.br/home/java/doc/org/lavieri/util/brazil/register/Cnpj.html
Código fonte: Cnpj.java

Código fonte das classes que Cnpj.java utiliza

VerifierDigits.java : http://pastebin.com/f18c7210d
DigitsSequence.java : http://pastebin.com/f6fe9c743
IntegerDigitsSequence.java : http://pastebin.com/f1b59161d
StringDigitsSequence.java : http://pastebin.com/f3e0e0cf7
StringUtil.java : http://pastebin.com/f2a6fdf91

Alguma funcionalidade do Objeto cnpj…

[code]package org.lavieri.aportepb.model.empresa;

import java.io.Serializable;

import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import org.hibernate.validator.Length;
import org.lavieri.util.brazil.register.Cnpj;

@Entity
public class Empresa implements Serializable {
private static final long serialVersionUID = 3359835129438155900L;
@Id @GeneratedValue private Integer id;
@Length(max=100) private String nome;
@Embedded @Length(max=14) private Cnpj cnpj;
}
[/code]

Além disso o teste de validação do CNPJ leva em conta as exceções de CNPJ invalidas de acordo com a receita federal, como número basico todo igual, número de ordem diferente de zero, entre outros…

Trabalho impressionante. Gostei.

Agora, não era melhor fazer só em português? Sem falar que está pecando bastante nos nomes em inglês.

Eu recomendaria mudar o toString para imprimir o valor formatado com a máscara, muitas tecnologias usam ele automaticamente obter uma representação imprimível do objeto.

[quote=Bruno Laturner]Trabalho impressionante. Gostei.

Agora, não era melhor fazer só em português? Sem falar que está pecando bastante nos nomes em inglês.[/quote]

bom, eu falava ingles quando tinha 15 anos auhahuauha… isso faz 13 anos… desde lá, meus contantos foram só através de games… meu ingles é horrivel, mais vou tentando voltar a escrever em ingles e etc… o que acho xato de escrever o código em portugues pq fica um treco horrivel…

getNome … no lugar de getName … pq alguns padrões como get, set, is, do, traduzidos ficam um lixu… mas nem meu português, nem meu inglês são os mehores auauhau…

Quando ao Cnpj formatado… cnpj.applayMask() … poem ele com formatação… eu só não deixei esse como toString, pq ficaria diferente do Long e do BigInteger…

visto que… de cnpj.equal(Cnpj.valueOf(cnpj.toBigInteger())) isso sempre é verdade… c alterar o valor de string, para string formatada não vai seguir a mesma logica

Edit…

sugestão aceita… a integridade esta mantida, visto que a saída de toString() pode voltar a ser um Cnpj através de valueOf(String cnpj) mesmo esta estando formatada

[quote=Bruno Laturner]Agora, não era melhor fazer só em português? Sem falar que está pecando bastante nos nomes em inglês.
[/quote]

quais seriam os nomes corretos para os metodos ?? ^^ =x … em inglês …

Digitos Verificadores em inglês: Check Digits

no lugar de applay, o certo é apply.

No equals, ao invés de várias checagens de instanceof, sobrecarregar o método, a JVM vai se encarregar de achar o certo:

public boolean equals(String cnpj)
public boolean equals(StringDigitsSequence cnpj)
public boolean equals(Long cnpj)
public boolean equals(BigInteger cnpj)
public boolean equals(Cnpj cnpj)
public boolean equals(Object cnpj) // se entrar aqui, certamente é false
	private boolean validateTeste() {
		boolean stillValid = true;
		for (ValidateCnpj validate : ValidateCnpj.values()) {
			stillValid = validate.isValid(this);
			if (!stillValid) 
				break;
		}
		return stillValid;
	}

Pode ser questão só da maneira de programar, mas dá pra evitar a alocação e atribuição de variáveis extras:

	private boolean validate() {
		for (ValidateCnpj validate : ValidateCnpj.values()) {
			if (! validate.isValid(this));
				return false;
		}
		return true;
	}

Outra coisa que reparei, porém não sei se estou certo, é que um objeto CNPJ não garante sua própria integridade, digo, dá pra criar um CNPJ que não seja válido. Não sei se isto é esperado ou não.

Recomendaria criar também uma classe Cpf, para poder estudar a questão de como instância de objetos diferentes afetam a sobre-escrita dos métodos:

StringDigitsSequence cnpj = new Cnpj(string); StringDigitsSequence cpf = new Cpf(string); Isso vai ajudar a escrever o nome dos métodos mais uniformemente.

E por último e mais importante, crie testes unitários em todos os métodos públicos, vai garantir que tudo funcione, como esse novo toString, que também teve repercussões internas no código.

[quote=Bruno Laturner]
No equals, ao invés de várias checagens de instanceof, sobrecarregar o método, a JVM vai se encarregar de achar o certo:

public boolean equals(String cnpj) public boolean equals(StringDigitsSequence cnpj) public boolean equals(Long cnpj) public boolean equals(BigInteger cnpj) public boolean equals(Cnpj cnpj) public boolean equals(Object cnpj) // se entrar aqui, certamente é false [/quote]

hmmm…

public boolean equals(StringDigitsSequence cnpj) e public boolean equals(Cnpj cnpj) os a verdade é que StringDigitsSequence é generico de Cnpj … ele nunca vai entrar no errado ? mesmo com cast ? esses 2 não seria bom deixar no mesmo equals ? (apesar que o método de teste são iguais)…

Segundo ouvi, a sun aconselha um único return para cada método, e c vc ver, todos os meus métodos só tem 1 único return… não acho o break elegante tb, mais foi o modo que encontrei para manter um único return

[quote]
Outra coisa que reparei, porém não sei se estou certo, é que um objeto CNPJ não garante sua própria integridade, digo, dá pra criar um CNPJ que não seja válido. Não sei se isto é esperado ou não. [/quote]
Bom, estou fazendo meu sistema para um caso pratico, e no meu caso, tenho CPF inválidos em arquivo antigo, e acredito que alguem possa ter CNPJ inválido tb, por essa questão é possivel criar o CNPJ e o CPF inválido, assim como núlo, e a verdade é que no mundo real, CPFs e CNPJs inválidos ee falsos existem, e estão por ai em todo canto …

pensei em uma variável estatica, onde vc possa alterar o modo do CNPJ ou de outras classes como CPF, e Inscrições Estaduais, para lançar exceptions quando são criados com números invalidas.

não sei c vale a pena limitar o objeto a valores válidos, afinal, se existe CNPJ válido, é pq existe ele invalido, e pra isso que tem o isValid()

ele já existem

http://www.simrentacar.com.br/home/java/doc/org/lavieri/util/brazil/register/Cpf.html
http://www.simrentacar.com.br/home/java/doc/org/lavieri/util/brazil/register/Cpf.java

assim como tem tb, um objeto, que recupera os dados de um CEP de uma base de dados mantida por um site, que libera essa base, devolvendo um Value Object com os resultados, contendo todo os dados que o correio libera sobre um CEP, além de dados sobre a propria consulta, mais informações no link abaixo

http://www.simrentacar.com.br/home/java/doc/org/lavieri/util/brazil/cep/package-tree.html

Ps.: Essa parte do CEP nãoe sta com código fonte no site, porem tem 1 post meu aki no GUJ, falando sobre CEP, que eu postie o link pra o código fonte

funciona + ou - assim

WebServiceCep cep = CepSearchEngineByQueryString.searchCep("13345-325"); //caso a busca ocorra bem, imprime os resultados. if (cep.wasSuccessful()) { System.out.println("Cep: "+cep.getCep()); System.out.println("Logradouro: "+cep.getLogradouroFull()); System.out.println("Bairro: "+cep.getBairro()); System.out.println("Cidade: "+ cep.getCidade()+"/"+ cep.cep()); //caso haja problemas imprime o código e msg de erro. } else { System.out.println("Erro número: " + cep.getResulCode()); System.out.println("Descrição do erro: " + cep.getResultText()); } A resposta do console seria:/** Cep: 13345325 Logradouro: Rua Cinco Bairro: Jardim Rêmulo Zoppi Cidade: Indaiatuba/SP */

Fora isso, tem tb a inscrição estadual, que estou criando o teste de validação, visto que cada um dos 27 estados, tem sua forma de validar, e algumas tem peculiaridades a respeito do modulo 11, enfim, estou montando a classe…

Ultima observação… não sei fazer teste Unit, c vc poder me dar algum link, eu agradeço

[quote=Lavieri]public boolean equals(StringDigitsSequence cnpj) e public boolean equals(Cnpj cnpj) os a verdade é que StringDigitsSequence é generico de Cnpj … ele nunca vai entrar no errado ? mesmo com cast ? esses 2 não seria bom deixar no mesmo equals ? (apesar que o método de teste são iguais)…
[/quote]

Ele nunca entra no errado.

public class TestaCovariancia
{
   public static void main(String[] args)   {
      System.out.println(metodo(new Gato()));
      System.out.println(metodo(new Cachorro()));
      System.out.println(metodo(new Animal()));
      System.out.println(metodo(new Object()));
   }

   private static String metodo(Object o)   {
      return "Object";
   }

   private static String metodo(Animal a)   {
      return "Animal";
   }

   private static String metodo(Cachorro c)   {
      return "Cachorro";
   }

   private static String metodo(Gato g)   {
      return "Gato";
   }
}

class Animal{}
class Cachorro extends Animal{}
class Gato extends Animal{}

Imprime

Gato Cachorro Animal Object

Quanto a StringDigitsSequence e Cnpj, você tem que se perguntar se o que importa é somente o conteúdo, ou se o tipo do objeto importa também. Se pelo menos o StringDigitsSequence fosse abstrato, dava pra garantir que alguém nunca iria passar um StringDigitsSequence válido sem que ele fosse um Cnpj, aí nem precisaria do equals(StringDigitsSequence)

É uma “regra” que não acho que vale a pena seguir. Piora o entendimento do programa.

Opiniões sobre o assunto: http://stackoverflow.com/questions/315546/only-one-return-statement-per-method-even-in-this-scenario
E até um refactoring p/ corrigir esse Bad Smell: http://www.refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html

[quote=Lavieri]Bom, estou fazendo meu sistema para um caso pratico, e no meu caso, tenho CPF inválidos em arquivo antigo, e acredito que alguem possa ter CNPJ inválido tb, por essa questão é possivel criar o CNPJ e o CPF inválido, assim como núlo, e a verdade é que no mundo real, CPFs e CNPJs inválidos ee falsos existem, e estão por ai em todo canto …

pensei em uma variável estatica, onde vc possa alterar o modo do CNPJ ou de outras classes como CPF, e Inscrições Estaduais, para lançar exceptions quando são criados com números invalidas.

não sei c vale a pena limitar o objeto a valores válidos, afinal, se existe CNPJ válido, é pq existe ele invalido, e pra isso que tem o isValid()[/quote]

Entendo.

Aqui, por exemplo, é regra não deixar que números de documentos inválidos entrem no sistema. Inclusive tem até triggers e procedures dentro do banco que rejeitam inserções de registros com números inválidos. Se por acaso processarmos um inválido, exceções são levantadas, tratamentos são feitos, mas ainda assim ele nunca é instanciado como inválido.

Depende da regra de negócio mesmo, não há jeito errado.

Muito show o Webservice de CEP, gostei.

E boa sorte se você for começar a tratar inscrições estaduais, até achar a informação sobre eles é um pouco complicado. Dê uma olhada no Caelum Stella, esse framework também se propõe a fazer validações e dezenas mais de coisas.

Quanto aos testes, acho melhor mesmo é pegar uma IDE que gere testes p/ você. No NetBeans é só ir no menu Tools -> Create JUnit tests. Daí é só olhar o código gerado, e ver a documentação online dele se precisar.

[quote=Bruno Laturner]
Quanto a StringDigitsSequence e Cnpj, você tem que se perguntar se o que importa é somente o conteúdo, ou se o tipo do objeto importa também. Se pelo menos o StringDigitsSequence fosse abstrato, dava pra garantir que alguém nunca iria passar um StringDigitsSequence válido sem que ele fosse um Cnpj, aí nem precisaria do equals(StringDigitsSequence)[/quote]

StringDigitSequence não tem o método isValid() … é apenas uma implementeção de DigitsSequence, para o formato String, o que o meu objeto CNPJ faz é, verificar c a sequencia de digitos passada no equals é igual a sequencia de digitos contida no CNPJ … o que é o mesmo que comparar o Objeto cnpj a uma String, o que quer dizer, que a string representa o mesmo Cnpj que o objeto… assim como é possivel compara-lo a BigInteger e Long…

na verdade eu vou por tb DigitsSequence ali no equals, para comparar, pois ele pode ser igual a uma IntegerDigitsSequence sem problema.

[code]package org.lavieri.util.brazil.register;

public interface DigitsSequence {
public int getNumberAt(int index);
public int length();
public String toMatrixString();
}
[/code]

[quote=Bruno Laturner]É uma “regra” que não acho que vale a pena seguir. Piora o entendimento do programa.

Opiniões sobre o assunto: http://stackoverflow.com/questions/315546/only-one-return-statement-per-method-even-in-this-scenario
E até um refactoring p/ corrigir esse Bad Smell: http://www.refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html[/quote]
vou olhar jaja esse links ^^ vlw

[quote=Lavieri]Bom, estou fazendo meu sistema para um caso pratico, e no meu caso, tenho CPF inválidos em arquivo antigo, e acredito que alguem possa ter CNPJ inválido tb, por essa questão é possivel criar o CNPJ e o CPF inválido, assim como núlo, e a verdade é que no mundo real, CPFs e CNPJs inválidos ee falsos existem, e estão por ai em todo canto …

pensei em uma variável estatica, onde vc possa alterar o modo do CNPJ ou de outras classes como CPF, e Inscrições Estaduais, para lançar exceptions quando são criados com números invalidas.

não sei c vale a pena limitar o objeto a valores válidos, afinal, se existe CNPJ válido, é pq existe ele invalido, e pra isso que tem o isValid()[/quote]

[quote=Bruno Laturner]Entendo.

Aqui, por exemplo, é regra não deixar que números de documentos inválidos entrem no sistema. Inclusive tem até triggers e procedures dentro do banco que rejeitam inserções de registros com números inválidos. Se por acaso processarmos um inválido, exceções são levantadas, tratamentos são feitos, mas ainda assim ele nunca é instanciado como inválido.

Depende da regra de negócio mesmo, não há jeito errado.[/quote]
Apesar que é algo izi de resolver ^^ …

public class CnpjValid extends Cnpj { public CnpjValid(String cnpj) throws IllegalArgumentException { super(cnpj); if (!isValid()) //Cnpj nulos tb não serão aceitos throw new IllegalArgumentException("O número do cnpj é invalido"); } public Cnpj(BigInteger cnpj) { this(toCnpjString(cnpj)); } public Cnpj(Long cnpj) { this(toCnpjString(cnpj)); } }

vlw ^^ … mais cuidado, o site la fala pra usar apenas quando não houver na base de dados… eles disponibilizam a base de dados de 2005 para donwload, e pede pra olhar no site apenas quando não for valido na base de dados…

Eu fui fazer um teste de performance … um for com 1000 hauahuahu… levei um block de ip =x

eu tenho esse link aki, http://www.sintegra.gov.br/insc_est.html que tem a regra para todos os estados… ja vi um monte de coisa pra facilitar o teste, ta quase encaminhado, falta pouco e sai um versão final da classe … ^^ … vi tb alguns exemplos no http://brazilutils.dev.java.net/ mas não gostei muito e por isso to fazendo um por conta propria ^^

eu uso o eclipse, detesto o netbeans (gosto so da parte de montar swing nele) … vou dar uma olhada nos testes

Também não sou fã do Netbeans, PRINCIPALMENTE pela parte de swing. O código gerado é complexo, confuso e difícil de manter. Só um detalhe quanto ao Eclipse: você conhece o plugin Visual Editor? Ele permite criar programas com AWT, swing e SWT no modo drag and drop, similar ao do Netbeans, porém o Visual Editor gera um código muito mais claro e legível.

Também não sou fã do Netbeans, PRINCIPALMENTE pela parte de swing. O código gerado é complexo, confuso e difícil de manter. Só um detalhe quanto ao Eclipse: você conhece o plugin Visual Editor? Ele permite criar programas com AWT, swing e SWT no modo drag and drop, similar ao do Netbeans, porém o Visual Editor gera um código muito mais claro e legível.[/quote]

bugado d + =/ … ja tentei muitas vezes… mais ele usa um misto de versões old de varios pacotes, e não é compativel com as versões mais novas… começo a usar ele… e depois de um tempo ele começa a falhar … gerar erros… etc … ja tentei por diversas vezes usar o VE mais nunca da certo…

quando o projeto eclipse realmente tentar colocar a parte visual, e não deixar isso a cargo de plug-in acredito que pode ficar bom

o netbeans eu acho facil de desenhar as janelas… o código em si não é lindo… mais ai fazer o q =/ … a parte de Desktop de java deixa muito a desejar

como tinha te falado, o código dele ta aki

http://www.guj.com.br/posts/list/114510.java

não lembro c só tem a versão XML que depende do dom4j ou c tem a versão queryString tb, que não depende de outras APIs

[quote=Lavieri]…bugado d + =/ … ja tentei muitas vezes… mais ele usa um misto de versões old de varios pacotes, e não é compativel com as versões mais novas… começo a usar ele… e depois de um tempo ele começa a falhar … gerar erros… etc … ja tentei por diversas vezes usar o VE mais nunca da certo…
[/quote]
Uso o VE a 3 meses e nunca tive problemas sérios (somente algumas vezes o visualizador não atualiza quanto muda o código, mas nada que um refresh não resolva…).

Que é isso!?!!? Se quer programar com drag and drop, vá programar em Delphi :-o
Java tem um poderosíssimo conjunto de gerenciadores de leiaute, APIs e frameworks de terceiros, que em conjunto, dão uma surra em muitas “linguagens de programação” baseada em componentes visuais. Sim, Java têm alguns bugs como toda linguagem, mas não concordo que a parte de Desktop deixa muito a desejar.

[quote=marcobiscaro2112][quote=Lavieri]…bugado d + =/ … ja tentei muitas vezes… mais ele usa um misto de versões old de varios pacotes, e não é compativel com as versões mais novas… começo a usar ele… e depois de um tempo ele começa a falhar … gerar erros… etc … ja tentei por diversas vezes usar o VE mais nunca da certo…
[/quote]
Uso o VE a 3 meses e nunca tive problemas sérios (somente algumas vezes o visualizador não atualiza quanto muda o código, mas nada que um refresh não resolva…).[/quote]

Me faz 1 favor?? zipa teu pacote de VE e me manda… pq porra, aki sempre inicia bem, e depois de um tempo começa a dar um NullPointerException no plug-in e não consigo + visualizar a parte visual…

!!?!?!

Nenhum segredo:

Linux Ubuntu 8.10
Eclise Ganymede
VE 1.4.0

Só.

[quote=marcobiscaro2112]!!?!?!

Nenhum segredo:

Linux Ubuntu 8.10
Eclise Ganymede
VE 1.4.0

Só.[/quote]

O VE é dependente de outro pacotes… não funciona sozinho…

eu n uso linxu…

minha versão do eclipse é

Eclipse Platform Version: 3.4.1 Build id: M20080911-1700

O VE funciona desde que você baixe o pack com todos os JARs. (procurar o link da versão 1.4 é com você…)

Os plugins do Eclipse (a maioria deles) são multiplataforma, logo o sistema operacional não influencia.

E a versão 3.4 é a versão Ganymede.

dei uma olhada aki… o problema é que na pagina la do eclipse… o plug-in ta com release 1.2 de 2006 … esse q deve ta ruim… http://www.eclipse.org/vep/WebContent/main.php

agora achei um site com o projeto 1.4 … http://wiki.eclipse.org/VE/Update

ele fala quer requer o EMF … to vendo ainda como baixar

Verdade… falei que não requeria nada mas precida do EMF. Olhá o link pra baixar:
http://www.eclipse.org/modeling/emf/downloads/?project=emf