Manter o estado do balcão após reiniciar

JavaBeginner
Pratique Agora

Introdução

Um balcão de empréstimos precisa lembrar quem está com cada ferramenta após fechar a aplicação. Este ambiente independente fornece regras de empréstimo funcionais e um novo arquivo do balcão, incluindo empréstimos existentes e uma ferramenta em manutenção. Seu código de armazenamento incompleto atualmente perde o estado salvo ao carregar e não grava alterações.

Você mapeará registros de arquivos UTF-8 para objetos e salvará apenas alterações válidas. Deve conhecer as regras de objetos do laboratório anterior; não precisa de nenhum arquivo daquele ambiente. Esta é uma aplicação didática de um único processo, não um banco de dados nem uma garantia contra quedas de energia. Tempo de leitura e prática estimado pelo autor: 45 minutos.

Carregar o estado que realmente está no disco

Nesta etapa, você lerá um registro comum de arquivo e depois corrigirá como o estado salvo e as relações com os membros se transformam em objetos Java.

Abra a aba Terminal. cd seleciona a pasta deste laboratório independente. Use Ctrl+U para limpar uma linha incorreta do terminal ainda não executada. Se houver erro de caminho, volte a esta pasta e tente novamente com o comando correto.

cd /home/labex/project/tool-library

A aplicação fornece regras de objetos funcionais, mas armazenamento incompleto. Primeiro use um pequeno arquivo de prática para ver o formato de cinco campos sem arriscar os empréstimos existentes. mkdir -p cria a pasta de prática se necessário. printf escreve conforme o formato escolhido: \t produz uma tabulação e \n encerra o registro; > grava a saída no arquivo indicado, substituindo uma cópia anterior de prática. As aspas simples impedem que o shell modifique o formato. cp copia a lista de membros para junto desse arquivo porque a aplicação procura members.tsv ao lado da entrada do balcão. Nenhum desses comandos altera o balcão real.

mkdir -p work
printf 'S01\tSpare drill\tAVAILABLE\t-\tPractice only\n' > work/sample.tsv
cp members.tsv work/members.tsv

Compile o código-fonte atual. -encoding UTF-8 seleciona a codificação do texto, -d out seleciona a saída compilada e *.java seleciona os arquivos Java desta pasta. Continue somente se a compilação terminar sem erros.

javac -encoding UTF-8 -d out *.java

-cp out informa ao Java onde estão as classes. -Dfile.encoding=UTF-8 seleciona a codificação do texto durante a execução. A entrada de prática é work/sample.tsv; --memory impede o salvamento desta demonstração.

java -Dfile.encoding=UTF-8 -cp out Desk work/sample.tsv --memory

Dentro do programa, digite estas linhas, pressionando Enter após cada uma:

list
borrow S01 M01
list
quit

S01 começa AVAILABLE, com responsável -; seu empréstimo a M01 é aceito. Esse caso comum funciona mesmo com o carregador incompleto porque o registro de prática já tem o estado que o código defeituoso presume. Ele não comprova a preservação dos empréstimos existentes. A alteração de prática desaparece quando esse processo fecha.

Leia o balcão real e os membros cadastrados. cat exibe um arquivo sem editá-lo:

cat desk.tsv
cat members.tsv

Há cinco campos separados por tabulações: ID, nome, estado do enum, membro responsável e observação. Esse formato controlado permite espaços e texto UTF-8 nos campos, mas não tabulações nem quebras de linha. T24 já está emprestada a M03; T25 está emprestada a M02 e tem a observação Cafe workshop. T23 está em manutenção. Esses fatos devem ser preservados no carregamento. Não edite diretamente desk.tsv, members.tsv nem a pasta reference.

Leia o código de armazenamento preparado:

cat Store.java

Store é o limite de persistência: registros se tornam objetos em load; objetos se tornam registros em save. Files.readAllLines lê UTF-8 explicitamente. fields(line) verifica o formato e fornece os campos de f[0] a f[4]. Encontre a chamada new Tool(...): atualmente ela substitui o estado e o responsável de cada registro por Tool.State.AVAILABLE e "-". Preveja o efeito sobre o responsável pelo empréstimo de T24 e o estado de manutenção de T23. O laço, a lista e os métodos auxiliares de análise e validação já estão preparados; preserve-os. Não é necessário reescrever sua implementação com HashSet.

Faça uma cópia de segurança apenas do código-fonte antes de editar:

cp Store.java work/Store-before-load.java.txt
nano Store.java

Como no primeiro laboratório, Ctrl+W procura, Enter confirma a busca, as setas movem o cursor e Backspace corrige caracteres. Procure Tool tool = new Tool para localizar essa única chamada ao construtor. Edite seus argumentos de estado e responsável para que fique assim:

            Tool tool = new Tool(f[0], f[1], Tool.State.valueOf(f[2]), f[3], f[4]);

Tool.State.valueOf(f[2]) converte o nome do enum salvo no valor correspondente; f[3] restaura o membro responsável salvo. Preserve os argumentos de ID, nome e observação, o laço ao redor e todos os métodos auxiliares. Você está mapeando informações existentes, não inventando uma ferramenta disponível nova. Salve com Ctrl+O, Enter e saia com Ctrl+X. Para descartar um erro ainda não salvo, use Ctrl+X, N. Reabra e procure a chamada para corrigir um erro de compilação. Se precisar recomeçar deliberadamente esta edição, cp work/Store-before-load.java.txt Store.java restaura apenas esse arquivo-fonte; refaça o mapeamento depois. Nunca execute setup novamente para desfazer edições.

Aqui, throws IOException declara que o acesso ao arquivo pode falhar. O laço de comandos imprime Cannot continue e para se a entrada estiver ausente ou malformada. É um problema de arquivo, não um empréstimo recusado. Corrija o caminho indicado ou o mapeamento no código-fonte; não esvazie nem regrave os registros originais para remover o erro.

Compile o código salvo e inicie o balcão real. Ao contrário da demonstração, omita --memory: o balcão real persistirá alterações válidas quando você concluir o salvamento na próxima etapa. Um erro de sintaxe indica o arquivo e a linha; corrija no nano e compile com sucesso antes de iniciar, em vez de executar classes antigas.

javac -encoding UTF-8 -d out *.java
java -Dfile.encoding=UTF-8 -cp out Desk desk.tsv

Digite estas linhas dentro do programa do balcão:

list
members
quit

A lista deve preservar T24 → M03, T25 → M02, o estado MAINTENANCE de T23 e todas as observações. members exibe os IDs cadastrados. Abrir e listar não deve regravar o arquivo. quit volta ao shell. A próxima etapa completa o salvamento real; uma mensagem de sucesso por si só não comprova persistência.

Salvar alterações válidas e reabrir o balcão

Nesta etapa, você fará um novo empréstimo e uma devolução válida sobreviverem ao encerramento real do processo.

Comece no shell da mesma aba Terminal. O salvamento serializa cada objeto atual, incluindo empréstimos e registros de manutenção não alterados. row(tool) junta os cinco campos com tabulações. O laço adiciona todas as linhas a uma lista; Files.write grava essas linhas como UTF-8. O laço de comandos chama save somente depois que um método do domínio retorna normalmente. Uma ação recusada não deve gravar o arquivo de dados, nem mesmo para regravar conteúdo idêntico.

Leia a estrutura de comandos para relacionar essa regra ao limite de armazenamento:

cat Desk.java

Encontre found.borrow(c[2]), found.giveBack(c[2]) e a chamada seguinte Store.save(path, tools). Uma exceção lançada pelo domínio pula a chamada de salvamento e se torna uma recusa normal. Preserve essa ordem preparada; acrescentar uma gravação ao tratamento de recusas violaria o contrato.

Faça uma cópia de segurança apenas do código-fonte, preservando o carregador corrigido:

cp Store.java work/Store-before-save.java.txt
nano Store.java

Pressione Ctrl+W, procure TODO: write all rows e pressione Enter. Leia o laço logo acima: ele reúne uma linha serializada para cada ferramenta, incluindo empréstimos não alterados. Use as setas para chegar ao final desse comentário e Backspace para remover seus caracteres. Digite a gravação com o mesmo recuo. Substitua apenas o comentário TODO por esta gravação real, depois do laço e antes da chave de fechamento do método:

        Files.write(path, rows, StandardCharsets.UTF_8);

path é o arquivo escolhido do balcão; rows é a lista serializada completa, não apenas o último objeto alterado. A codificação explícita preserva a codificação do texto de cada campo. Mantenha o método load corrigido, o laço de registros e todos os métodos auxiliares. Salve com Ctrl+O, Enter, Ctrl+X. Se houver erro ainda não salvo, Ctrl+X, N o descarta. Para um erro de código já salvo, reabra e corrija; cp work/Store-before-save.java.txt Store.java é uma opção para restaurar apenas o código-fonte, preservando o carregador. Refaça a gravação depois. Não redefina o arquivo do balcão nem execute setup novamente.

Compile novamente o código-fonte salvo:

javac -encoding UTF-8 -d out *.java
java -Dfile.encoding=UTF-8 -cp out Desk desk.tsv

Digite o seguinte dentro do balcão:

borrow T21 M01
borrow T21 M02
return T24 M01
borrow T23 M01
borrow TYPO M01
return T24 M03
list
quit

T21 fica emprestada a M01. O empréstimo duplicado, o membro incorreto na devolução, o empréstimo da ferramenta em manutenção e o ID digitado incorretamente são recusados intencionalmente. Somente a devolução de T24 por M03 tem sucesso. T22 continua disponível, T23 permanece em manutenção e T25 continua emprestada a M02 com sua observação original. A recusa do ID desconhecido mantém o laço utilizável; corrija o ID em vez de reiniciar ou redefinir o ambiente.

Agora inicie um novo processo Java usando o mesmo arquivo:

java -Dfile.encoding=UTF-8 -cp out Desk desk.tsv
list
quit

T21 ainda deve constar como BORROWED por M01, e T24 deve continuar AVAILABLE, com o membro responsável definido como -. Caso contrário, verifique se você compilou o Store.java atual e iniciou sem --memory. Não edite os registros finais para imitar um empréstimo salvo. Se uma operação aceita já foi salva, não a repita só porque agora ela é recusada; list mostra a situação real atual.

De volta ao shell, leia o resultado efetivamente armazenado:

cat desk.tsv

As relações nos registros devem corresponder à lista do novo processo. Preserve todos os IDs, nomes, membros, estados de manutenção, empréstimos não envolvidos e observações. Mudam apenas o estado/membro de T21 e o estado/membro de T24. Essa pequena rotina de gravação substitui o arquivo durante um salvamento bem-sucedido; não fornece acesso concorrente, recuperação após falhas nem transação atômica. Se a gravação falhar, pare e examine o erro antes de continuar.

Resumo

Você mapeou registros UTF-8 para objetos Java, salvou todos os registros atuais após uma transição válida e reabriu o balcão em um novo processo. Empréstimos existentes, manutenção e observações permaneceram intactos, enquanto operações recusadas não gravaram no armazenamento.