Registro de Código Fonte

Boa tarde, alguém tem conhecimento de como realizar a impressão de código fonte de uma aplicação java (desenvolvida no netbeans) para finalidade de registro de software ?

Existe alguma API ou ferramenta que faça isso ?

Impressão em papel ou export em .pdf

Sou iniciante ainda não usei, mais sei da existência do IReport.

Agradeço sua atenção, mas o IReport é utilizado para o desenvolvimento de relatórios, não para a finalidade da qual preciso!

O que eu preciso é imprimir os códigos fonte de minhas classes .java sem a necessidade de ter que abrir classe por classe e realizar este processo!

Como informei no tópico, este processo é necessário para registrar o software desenvolvido.

Imprimir diretamente para pdf, etc eu desconheço, mas com o javadoc você gera a doc de todas as classes do projeto em html… talvez ajude em algo…

https://www.caelum.com.br/apostila-java-orientacao-objetos/ferramentas-jar-e-javadoc/

Esse post indica algumas ferramentas…

1 curtida

Arquivos .java são meros arquivos de texto, você pode imprimi-los da mesma forma como imprimiria qualquer outro .txt.

Aproveitando o seu questionamento, como proceder para realizar o registro do Software? Existe alguma empresa responsável ou varias empresas, não entendo muito bem essa parte.

Nunca conheci ninguém que o tenha feito.
No Brasil ainda não temos regulamentação para isso, dessa forma, as leis que se aplicam ao software são as mesmas pertinentes à propriedade intelectual e direitos autorais.

Talvez consiga mais informações para sua dúvida no INPI.
http://www.inpi.gov.br/menu-servicos/programa-de-computador/documentacao-formal-para-registro-de-programa-de-computador

1 curtida

talvez na ABES consiga. veja em http://www.abessoftware.com.br/

Não tenho como dizer ser há alguma em específico que realize a impressão de todos os códigos fonte em um clique.

A ferramenta pronta também desconheço, mas é possível “varrer” as pastas do projeto procurando por arquivos .java e por semelhança, poderia ser feito o mesmo para outros tipos de arquivo.

Não posso dizer que fiz testes suficientes e tenho baixa expectativa quanto a sua eficiência por este motivo.
Achei legal a implementação e vou compartilhar por ser uma forma de aprendizado, assim, não cabe o utilizar para fins de trabalho, por questões de integridade.

O eixo principal da movimentação entre as pastas e arquivos é o método a seguir, digamos que ele seja o core:

//usado para separar pastas e agrupar arquivos.java
private void percorrerDiretorio(Path caminho) {

    try {
        //separa diretórios de arquivos
        Files.list(caminho).forEach(arquivo -> {
            if (arquivo.toFile().isDirectory()) {
                percorrerDiretorio(arquivo);
            } else if (arquivo.toString().endsWith(".java")) {
                gerenciarDiretorios(caminho.toFile().getAbsolutePath()).getArquivosJava().add(new ArquivoJava(arquivo));
            }
        });
    } catch (IOException ex) {
        Logger.getLogger(OrdenadorJava.class.getName()).log(Level.SEVERE, null, ex);
        logExcessoes.add(new LogExcessoes(ex.getMessage()));
    }
}

Eis as classes:

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

public class Efemera {
    
    //"imprimindo" os arquivos .java
    public static void main(String[] args) {
        JOptionPane.showMessageDialog(null, "Nas configurações atuais, pacotes que não contenham\n"
                + "arquivos.java, terão o seu caminho ignorados");
        JOptionPane.showMessageDialog(null, "Lembre de SALVAR o Projeto antes de imprimir.\nInforme a pasta onde estão os códigos fonte");
        
        JFileChooser jfc = new JFileChooser();
        jfc.setDialogTitle("Escolha a pasta source");
        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        
        
        if (jfc.showOpenDialog(jfc) == JFileChooser.APPROVE_OPTION) {
            OrdenadorJava ordenador = new OrdenadorJava(jfc.getSelectedFile().toPath());

            ordenador.getDiretorios().forEach(diretorio -> {

                System.out.println("===================================================\nPACOTE:\n"
                        + diretorio.getCaminho()
                        + "\n===================================================\n"
                        + "Total de arquivos.java no diretório: "
                        + diretorio.getArquivosJava().size()
                        + "\nArquivos relacionados: ");

                diretorio.getArquivosJava().forEach(arquivo -> System.out.println(arquivo.getCaminho().getFileName()));
                System.out.println("Imprimindo as classes\n\n");

                diretorio.getArquivosJava()
                        .stream()
                        .map(ArquivoJava::getLinhas)
                        //imprimindo os arquivos.java
                        .forEach(lista -> lista.forEach(System.out::println));
            });
            if (ordenador.getDiretorios().isEmpty()) {
                JOptionPane.showMessageDialog(null, "Não foram encontrados arquivos.java");
            }
        }
    }
}

.

import java.util.ArrayList;

public final class Diretorio {
    private final String caminho;
    private final ArrayList<ArquivoJava> arquivosJava = new ArrayList<>();

    public Diretorio(String diretorio) {
        this.caminho = diretorio;
    }

    public ArrayList<ArquivoJava> getArquivosJava() {
        return arquivosJava;
    }

    public String getCaminho() {
        return caminho;
    }
    
}

.

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.swing.JOptionPane;

//classe que fica
public final class ArquivoJava {

    private Path caminho;
    private List<String> linhas;
    private final List<LogExcessoes> logDeExcessoes = new ArrayList<>();

    //previsão de nullPointerException caso as linhas não possam ser atribuidas
    public ArquivoJava(Path caminho) {
        try {
            linhas = Files.readAllLines(caminho, StandardCharsets.UTF_8);
            this.caminho = caminho;
        } catch (IOException ex) {
            Logger.getLogger(ArquivoJava.class.getName()).log(Level.SEVERE, null, ex);
            JOptionPane.showMessageDialog(null, caminho.toString());
            logDeExcessoes.add(new LogExcessoes(ex.getMessage()));            
        }
    }

    public List<LogExcessoes> getLogDeExcessoes() {
        return logDeExcessoes;
    }
    
    public List<String> getLinhas() {
        return linhas;
    }
    
    

    public Path getCaminho() {
        return caminho;
    }

    public String tipo() {
        String[] tipos = {"abstract", "class", "@interface", "interface", "enum"};
        return Arrays.stream(tipos).filter(tipo -> caminho.toString().contains(tipo)).findFirst().orElse("O arquivo é inconsistente");
    }

    public int totalIfRelativo() {
        int relativa = (int) linhas.stream().filter(linha -> !linha.contains("\"") && linha.contains("?") && linha.contains(":")).count();
        return Collections.frequency(linhas, " if(") + relativa;
    }

    public int totalForRelativo() {
        return Collections.frequency(linhas, " for(") + Collections.frequency(linhas, "foreach(");
    }

    public int totalWhileRelativo() {
        return Collections.frequency(linhas, " while(");
    }

    public List<String> metodosPrivados() {
        return linhas.stream().filter(linha -> linha.contains("private ") && linha.contains("){")).collect(Collectors.toList());
    }

    public List<String> atributosPrivados() {
        return linhas.stream().filter(linha -> linha.contains("private ") && !linha.contains("){")).collect(Collectors.toList());
    }

}

.

import java.util.ArrayList;
import java.util.Calendar;

//apenas para fins de evolução da aplicação
public final class LogExcessoes {
    private final String mensagem;
    private final ArrayList<String> tratamentos = new ArrayList<>();

    public LogExcessoes(String mensagem) {
        this.mensagem = mensagem;
    }

    public String getMensagem() {
        return mensagem;
    }

    public ArrayList<String> getTratamentos() {
        return tratamentos;
    }

    public void adicionarTratamento(String tratamentoRealizado){
        tratamentos.add(Calendar.getInstance()+" - "+tratamentoRealizado);
    }
}

.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;

//Esta classe fica com a responsabilidade de pesquisar os arquivos.java e os organizar por diretórios
public final class OrdenadorJava {

    private final ArrayList<Diretorio> diretorios = new ArrayList<>();
    private final ArrayList<LogExcessoes> logExcessoes = new ArrayList<>();

    public OrdenadorJava(Path pastaRaiz) {
        percorrerDiretorio(pastaRaiz);
        Collections.unmodifiableCollection(diretorios);
        Collections.unmodifiableCollection(logExcessoes);
    }

    public ArrayList<Diretorio> getDiretorios() {
        return diretorios;
    }

    public ArrayList<LogExcessoes> getLogExcessoes() {
        return logExcessoes;
    }

    //usado para separar pastas e agrupar arquivos.java
    private void percorrerDiretorio(Path caminho) {

        try {
            //separa diretórios de arquivos
            Files.list(caminho).forEach(arquivo -> {
                if (arquivo.toFile().isDirectory()) {
                    percorrerDiretorio(arquivo);
                } else if (arquivo.toString().endsWith(".java")) {
                    gerenciarDiretorios(caminho.toFile().getAbsolutePath()).getArquivosJava().add(new ArquivoJava(arquivo));
                }
            });
        } catch (IOException ex) {
            Logger.getLogger(OrdenadorJava.class.getName()).log(Level.SEVERE, null, ex);
            logExcessoes.add(new LogExcessoes(ex.getMessage()));
        }
    }

    //o atributo diretorios só realiza a adição de diretórios inéditos
    private Diretorio gerenciarDiretorios(String caminho) {
        if (!diretorios.stream().anyMatch(diretorio -> diretorio.getCaminho().equals(caminho))) {
            Diretorio retorno = new Diretorio(caminho);
            diretorios.add(retorno);
            return retorno;
        }
        return diretorios.stream().filter(diretorio -> diretorio.getCaminho().equals(caminho)).findFirst().orElse(null);
    }
}

Estas classes fazem uso da recursividade para encontrar os arquivos.java.
Se perceber, vai ver vários métodos sem utilidade, mas eles podem vir a ter utilidade futuramente.

No que se refere as vantagens:

1 - esta implementação pode ser usada sem depender de uma IDE, setando apenas a pasta que contém os códigos fonte;

2 - Evoluindo a codificação:
I) pode ser integrado com ferramentas como o iText, imprimindo os códigos fonte em pdf com formatação personalizada, facilitando a sumarização de arquivos por pastas;
II) em vez de imprimir todo o projeto será possível imprimir apenas uma pasta ou um conjunto de pastas.
III) realizar estatísticas básicas (motivo da inclusão dos métodos desnecessários).

Desvantagens: é um protótipo para o qual não há expectativa na evolução da aplicação, além de falta de refatoração.

Por que implementar desta forma?
Por que as aplicações devem ser pensadas para evoluir.

Té+

1 curtida