quinta-feira, 12 de dezembro de 2013

Recursividade

Para entender um método recursivo, primeiro você deve entender um método recursivo.

Eu me orgulho de poucos códigos. ESTE é um deles.

--------------------------------------------

public class DataObjectMetadataService {

@Resource(name = "dataObjectMetadataDAOImpl")
private DataObjectMetadataDAO domDAO;
private List<Programa> progs = new ArrayList<Programa>();
private Boolean carregaCampos;

public List<DataObjectMetadata> createOrRetrieveByClassName(DataObjectMetadataFilter filter) {
List<DataObjectMetadata> newDatas = null;
this.carregaCampos = filter.getCarregaCampos();

filter.setNmPrograma(domDAO.buscaClassNameCompleto(filter));
progs = domDAO.pesquisaPrograma(filter);
if(filter.getNmPrograma() != null) {
List<DataObjectMetadata> impedeRetorno = new ArrayList<DataObjectMetadata>();
newDatas = criaEstruturaClasse(filter.getNmPrograma(), impedeRetorno);
if(this.carregaCampos){
percorreNivelCampos(newDatas);
while(newDatas.get(0).getLevel() == null) {
defineNivel(newDatas);
}
}

return newDatas;
}

private List<DataObjectMetadata> criaEstruturaClasse(String className, List<DataObjectMetadata> impedeRetorno) {

List<DataObjectMetadata> datas = null;

try {

AbstractEntityPersister persister = buscaPropriedadesBanco(Class.forName(className));

DataObjectMetadata data = new DataObjectMetadata();
data.setClassName(persister.getName());
impedeRetorno.add(data);
if(carregaCampos){
datas = montaDadosClasse(persister, impedeRetorno);
completaDadosData(datas);
} else {
datas = montaDadosProgs(persister, impedeRetorno);
}
} catch(ClassNotFoundException e) {
e.printStackTrace();
}

return datas;

}

private <T> AbstractEntityPersister buscaPropriedadesBanco(Object cls) {
AbstractEntityPersister persister = null;
ClassMetadata hibernateMetadata = domDAO.findHibernateMetadata((Class<?>) cls);

if(hibernateMetadata != null) {
if(hibernateMetadata instanceof AbstractEntityPersister) {
persister = (AbstractEntityPersister) hibernateMetadata;
}
}
return persister;
}

private List<DataObjectMetadata> montaDadosClasse(AbstractEntityPersister persister, List<DataObjectMetadata> impedeRetorno) {

List<DataObjectMetadata> ir = copiaListaRetorno(impedeRetorno);

List<DataObjectMetadata> datas = new ArrayList<DataObjectMetadata>();
DataObjectMetadata data = null;

if(persister != null) {
String[] columnKey = persister.getKeyColumnNames();
String[] columnNames = persister.getPropertyNames();
Type[] columnTypes = persister.getPropertyTypes();
boolean[] columnNullable = persister.getPropertyNullability();

if(columnKey != null) {
List<String> keys = new ArrayList<String>(Arrays.asList(columnKey));
for(String key : keys) {
data = new DataObjectMetadata();

data.setDataStamp(new Date());

data.setTableName(persister.getTableName());
data.setClassName(persister.getName());
data.setColumnName(key);
data.setColumnType("Integer");
data.setIsNullable(SimNao.NAO);
data.setIsClassAntara(SimNao.NAO);
data.setMustInspectElement(SimNao.NAO);

data.setDataObjectMetadata(verificaSubObjetos(data, ir));

datas.add(data);
}
}

if((columnNames != null) && (columnTypes != null)) {
List<String> colunas = new ArrayList<String>(Arrays.asList(columnNames));
List<Type> tipos = new ArrayList<Type>(Arrays.asList(columnTypes));

if((colunas != null) && (tipos != null)) {
for(int i = 0; i < colunas.size(); i++) {
data = new DataObjectMetadata();

data.setDataStamp(new Date());

data.setTableName(persister.getTableName());
data.setClassName(persister.getName());
data.setColumnName(colunas.get(i));
data.setColumnType(tipos.get(i).getName());
data.setIsNullable(columnNullable[i] ? SimNao.SIM : SimNao.NAO);
data.setIsClassAntara(isClasseAntara(data.getColumnType()));
if(SimNao.SIM.equals(data.getIsClassAntara())) {
data.setMustInspectElement(deveInspecionarElemento(data.getColumnType(), ir));
} else {
data.setMustInspectElement(SimNao.NAO);
}

data.setDataObjectMetadata(verificaSubObjetos(data, ir));

datas.add(data);

}
}
}
}

return datas;
}

private void completaDadosData(List<DataObjectMetadata> datas) {

List<DataObjectMetadata> loadDatas = new ArrayList<DataObjectMetadata>();
loadDatas = domDAO.loadMedatadas(datas);
if(loadDatas != null) {
for(ListIterator<DataObjectMetadata> it = datas.listIterator(); it.hasNext();) {
DataObjectMetadata dom = it.next();
for (DataObjectMetadata load : loadDatas) {
if(dom.getTableName().equals(load.getTableName()) && dom.getColumnName().equals(load.getColumnName())){
it.remove();
it.add(load);
load.setLevel(null);
load.setMustInspectElement(dom.getMustInspectElement());
load.setDataObjectMetadata(dom.getDataObjectMetadata());
if(!StrUtil.validateString(load.getProgramName()) || !StrUtil.validateString(load.getProgramCode())){
completaDadosCampos(load);
}
break;
}
}
}
}
loadDatas.clear();
}

private List<DataObjectMetadata> copiaListaRetorno(List<DataObjectMetadata> impedeRetorno) {

List<DataObjectMetadata> copia = new ArrayList<DataObjectMetadata>();
DataObjectMetadata c = null;

for(DataObjectMetadata dom : impedeRetorno) {
c = new DataObjectMetadata();

c.setClassName(dom.getClassName());

copia.add(c);

}
return copia;
}

private List<DataObjectMetadata> verificaSubObjetos(DataObjectMetadata data, List<DataObjectMetadata> impedeRetorno) {
List<DataObjectMetadata> datas = null;

if(SimNao.SIM.equals(data.getMustInspectElement())) {
datas = criaEstruturaClasse(data.getColumnType(), impedeRetorno);
}

return datas;

}

private SimNao isClasseAntara(String columnType) {
if(columnType.contains(".")) {
String[] caminho = columnType.split(Pattern.quote("."));
int tam = caminho.length;

for(int j = 0; j < tam; j++) {
if("domain".equals(caminho[j])) {
return SimNao.SIM;
} else {
if("util".equals(caminho[j])) {
return SimNao.NAO;
}
if("java".equals(caminho[j])) {
return SimNao.NAO;
}
if("hibernate".equals(caminho[j])) {
return SimNao.NAO;
}
}
}

return SimNao.SIM;

}

return SimNao.NAO;
}

private SimNao deveInspecionarElemento(String columnType, List<DataObjectMetadata> impedeRetorno) {

for(DataObjectMetadata tipoJaUsado : impedeRetorno) {
if(columnType.equals(tipoJaUsado.getClassName())) {
return SimNao.NAO;
}
}

DataObjectMetadata aux = new DataObjectMetadata();
aux.setClassName(columnType);
impedeRetorno.add(aux);

return SimNao.SIM;
}

private void percorreNivelCampos(List<DataObjectMetadata> datas) {

Boolean encontrouUltimoNivel = false;

for(DataObjectMetadata data : datas) {
if(SimNao.SIM.equals(data.getMustInspectElement())) {
percorreNivelCampos(data.getDataObjectMetadata());
encontrouUltimoNivel = false;
}
}

if(!encontrouUltimoNivel) {
for(DataObjectMetadata dom : datas) {
if(SimNao.NAO.equals(dom.getMustInspectElement())) {
encontrouUltimoNivel = true;
} else {
encontrouUltimoNivel = false;
break;
}
}
}

if(encontrouUltimoNivel) {
for(DataObjectMetadata data : datas) {
data.setLevel(new Integer(1));

if(data.getDataObjectMetadata() == null) {
List<DataObjectMetadata> dates = Collections.emptyList();
data.setDataObjectMetadata(dates);
}
}
}
}

private void defineNivel(List<DataObjectMetadata> datas) {

Boolean recebeuLevel = false;
Integer level = new Integer(0);
for(DataObjectMetadata data : datas) {
if(SimNao.SIM.equals(data.getIsClassAntara()) && SimNao.SIM.equals(data.getMustInspectElement())) {
if(data.getDataObjectMetadata().get(1).getLevel() != null) {
if(data.getLevel() == null) {
if(level < (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1))) {
level = (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1));
}
recebeuLevel = true;
} else if(data.getLevel() < (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1))) {
if(level < (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1))) {
level = (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1));
}
recebeuLevel = true;
}
} else {
defineNivel(data.getDataObjectMetadata());
if(data.getLevel() == null) {
if(level < (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1))) {
level = (data.getDataObjectMetadata().get(1).getLevel() + new Integer(1));
}
recebeuLevel = true;
}
}
}
}

if(recebeuLevel) {
for(DataObjectMetadata dom : datas) {
if(dom.getLevel() == null) {
dom.setLevel(level);

if(dom.getDataObjectMetadata() == null) {
List<DataObjectMetadata> dates = Collections.emptyList();
dom.setDataObjectMetadata(dates);
}
}
}
}
}

public void save(List<DataObjectMetadata> datas, String usuario) {

List<DataObjectMetadata> saves = new ArrayList<DataObjectMetadata>();

desmembraObjetos(datas, saves);

for(DataObjectMetadata save : saves) {
save.setUsuarioStamp(usuario);

domDAO.save(save);
}

}

private void desmembraObjetos(List<DataObjectMetadata> datas, List<DataObjectMetadata> saves) {

for(DataObjectMetadata dom : datas) {
if(SimNao.SIM.equals(dom.getMustInspectElement())) {
desmembraObjetos(dom.getDataObjectMetadata(), saves);
adicionaObj(saves, dom);
} else {
adicionaObj(saves, dom);
}
}
}

private void adicionaObj(List<DataObjectMetadata> saves, DataObjectMetadata dom) {
Boolean add = true;
for(DataObjectMetadata save : saves) {
if(save.getClassName().equals(dom.getClassName())) {
if(save.getColumnName().equals(dom.getColumnName())) {
add = false;
break;
}
}
}

if(add) {
saves.add(dom);
}
}

public List<DataObjectMetadata> findToExport(DataObjectMetadata data) {
return domDAO.findToExport(data);
}

public List<DataObjectMetadata> getEstruturaExportacaoXml(List<DataObjectMetadata> metadatasRequisitados) {
List<DataObjectMetadata> retorno = new ArrayList<DataObjectMetadata>(metadatasRequisitados);
List<DataObjectMetadata> metadatas = domDAO.findAll();
metadatas.removeAll(retorno);

adicionaSubNiveis(retorno, metadatas);
return retorno;
}

private void adicionaSubNiveis(List<DataObjectMetadata> niveisSelecionados, List<DataObjectMetadata> todosMetadatas) {
List<DataObjectMetadata> subniveis = new ArrayList<DataObjectMetadata>();
List<String> classesEsperadasSubniveis = getSubniveisEsperadosParaListaDeDatas(niveisSelecionados);

// adiciona os metadatas relacionados aos subníveis selecionados
for(DataObjectMetadata metadata : todosMetadatas) {
if(classesEsperadasSubniveis.contains(metadata.getClassName())) {
subniveis.add(metadata);
}
}

// remove os metadatas adicionados da lista geral
todosMetadatas.removeAll(subniveis);

if(!subniveis.isEmpty()) {
adicionaSubNiveis(subniveis, todosMetadatas);
}

niveisSelecionados.addAll(subniveis);
}

private List<String> getSubniveisEsperadosParaListaDeDatas(List<DataObjectMetadata> metadatasParaAnalisar) {
List<String> classesEsperadasSubniveis = new ArrayList<String>(metadatasParaAnalisar.size());

for(DataObjectMetadata metadata : metadatasParaAnalisar) {
if(isClasseAntara(metadata.getColumnType()) == SimNao.SIM) {
classesEsperadasSubniveis.add(metadata.getColumnType());
}
}

return classesEsperadasSubniveis;
}
private List<DataObjectMetadata> montaDadosProgs(AbstractEntityPersister persister, List<DataObjectMetadata> impedeRetorno) {
List<DataObjectMetadata> ir = copiaListaRetorno(impedeRetorno);
List<DataObjectMetadata> datas = new ArrayList<DataObjectMetadata>();
DataObjectMetadata data = null;
if(persister != null) {
String[]  columnNames    = persister.getPropertyNames();
Type[]    columnTypes    = persister.getPropertyTypes();
if((columnNames != null) && (columnTypes != null)) {
List<String> colunas = new ArrayList<String>(Arrays.asList(columnNames));
List<Type> tipos = new ArrayList<Type>(Arrays.asList(columnTypes));
if((colunas != null) && (tipos != null)) {
for(int i = 0; i < colunas.size(); i++) {
data = new DataObjectMetadata();
if(SimNao.SIM.equals(isClasseAntara(tipos.get(i).getName()))){
data.setDataStamp(new Date());
data.setTableName(persister.getTableName());
data.setClassName(persister.getName());
data.setColumnName(colunas.get(i));
data.setColumnType(tipos.get(i).getName());
data.setIsClassAntara(isClasseAntara(data.getColumnType()));
data.setMustInspectElement(deveInspecionarElemento(data.getColumnType(), ir));
data.setDataObjectMetadata(verificaSubObjetos(data, ir));
completaDadosProg(data);
datas.add(data);
}
}
}
}
}
return datas;
}


private void completaDadosCampos(DataObjectMetadata data) {
Integer indexInicio = data.getClassName().lastIndexOf(".");
Integer indexFinal  = data.getClassName().length();
String nmBean = data.getClassName().substring((indexInicio+1), (indexFinal));
for (Programa prog : progs) {
indexInicio = prog.getNmPrograma().lastIndexOf(".");
indexFinal  = prog.getNmPrograma().length();
String nmPrograma = prog.getNmPrograma().substring((indexInicio+1), (indexFinal));
if(!nmPrograma.contains("Rep")){
if("Frm".equals(prog.getNmPrograma().substring((indexFinal-3), indexFinal))){
nmPrograma = prog.getNmPrograma().substring((indexInicio+1), (indexFinal-3));
}
if(nmPrograma.equals(nmBean)){
data.setProgramName(prog.getProgramaIdioma(new Locale("pt", "BR")).getNmTituloPrograma());
data.setProgramCode(prog.getCdPrograma());
break;
}
}
}
}
private void completaDadosProg(DataObjectMetadata data) {
Integer indexInicio = data.getColumnType().lastIndexOf(".");
Integer indexFinal  = data.getColumnType().length();
String nmBean = data.getColumnType().substring((indexInicio+1), (indexFinal));
for (Programa prog : progs) {
indexInicio = prog.getNmPrograma().lastIndexOf(".");
indexFinal  = prog.getNmPrograma().length();
String nmPrograma = prog.getNmPrograma().substring((indexInicio+1), (indexFinal));
if("Frm".equals(prog.getNmPrograma().substring((indexFinal-3), indexFinal))){
nmPrograma = prog.getNmPrograma().substring((indexInicio+1), (indexFinal-3));
}
if(nmPrograma.equals(nmBean)){
if(carregaCampos){
data.setProgramName(prog.getProgramasIdiomas().get(0).getNmTituloPrograma());
} else {
data.setClassName(prog.getProgramaIdioma(new Locale("pt", "BR")).getNmTituloPrograma());
}
data.setProgramCode(prog.getCdPrograma());
break;
}
}
}
}


-------------------------------------------------

public String buscaClassNameCompleto(String className) {
SessionFactory sf = getSessionFactory();
Map<String, ClassMetadata> classes = sf.getAllClassMetadata();

for(Map.Entry<String, ClassMetadata> entry : classes.entrySet()) {
ClassMetadata classMetadata = (ClassMetadata) entry.getValue();
String clazz = classMetadata.getMappedClass(EntityMode.POJO).getName();
int indexInicio = clazz.indexOf("domain.");
indexInicio += "domain.".length();
String objetoRetornado = clazz.substring(indexInicio, clazz.length());
if(objetoRetornado.equals(className)) {
return clazz;
}
}
return null;
}