|
|
| (65 intermediate revisions by the same user not shown) |
| Line 1: |
Line 1: |
| {{PRJPOAvisos|co15@l2f.inesc-id.pt|2015/10/23 12:00|2015/11/16 12:00|2015/12/01 12:00|2015/12/01-2015/12/04}}
| | #REDIRECT [[ist:Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2015-2016]] |
| <!--{{PRJPOAvisosEpocaEspecial|co15@l2f.inesc-id.pt|2015/07/16 12:00|2015/07/16 13:00}}-->
| |
| {{PRJPOMandatory}}
| |
| | |
| O objectivo do projecto é criar uma aplicação que permite ver e alterar um documento textual. A aplicação mantém o nome do documento onde deve ser guardado o documento em disco. A aplicação apenas edita um documento de cada vez, embora possa trocar de documento.
| |
| | |
| Neste texto, o tipo <tt>fixo</tt> indica um literal; o símbolo <amsmath>\verb*| |</amsmath> indica um espaço; e o tipo ''itálico'' indica uma parte variável.
| |
| | |
| = Estrutura e Formatação de um Documento =
| |
| | |
| Um documento tem uma estrutura interna, correspondente à organização do seu conteúdo, sendo possível alterar este conteúdo.% Além dos elementos estruturais, existem ainda propriedades relativas à formatação e decoração dos elementos textuais.
| |
| | |
| Os documentos têm um título, um ou mais autores, e um conjunto de parágrafos e secções.
| |
| | |
| Cada autor tem um nome e um contacto (email).
| |
| | |
| As secções têm um título, uma sequência de parágrafos e uma sequência de subsecções (ambas potencialmente vazias). Os parágrafos e as subsecções são identificados implicitamente em cada secção pelo seu número de ordem (ambos com início em 0). Cada parágrafo (sequências de frases relacionadas contextualmente) ou secção pode ter um identificador único no contexto do documento (cadeia de caracteres).
| |
| | |
| É possível adicionar/remover secções e parágrafos a/de documentos e secções. É possível alterar o conteúdo de um parágrafo.
| |
| | |
| = Interacção com o Utilizador: Editor de Documentos =
| |
| | |
| Descreve-se abaixo a '''funcionalidade máxima''' da interface com o utilizador. Em geral, os comandos pedem toda a informação antes de proceder à sua validação (excepto onde indicado). Todos os menus têm automaticamente a opção '''Sair''' (fecha o menu).
| |
| | |
| As operações de leitura e escrita '''devem''' realizar-se através do objecto '''ist.po.ui.Dialog.IO'''. As mensagens são produzidas pelos métodos das bibliotecas de suporte ('''po-uilib''' e '''edt-support'''). As mensagens não podem ser usadas no núcleo da aplicação. Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.
| |
| | |
| As excepções usadas na interacção, excepto se indicado, são subclasses de '''ist.po.ui.DialogException''', são lançadas pelos comandos e tratadas por '''ist.po.ui.Menu'''. Outras excepções não devem substituir as fornecidas nos casos descritos. Nas secções dos comandos (abaixo), indicam-se os números correspondentes às excepções que podem ocorrer em cada um.
| |
| | |
| == Menu Principal ==
| |
| | |
| As acções do menu, listadas em '''edt.textui.main.MenuEntry''', permitem gerir a salvaguarda do estado da aplicação, assim como operar sobre o documento actual: [[#Criar|Criar]], [[#Abrir|Abrir]], [[#Guardar|Guardar]], [[#Listar meta-informação|Listar meta-informação]], [[#Adicionar autor|Adicionar autor]], [[#Listar secções|Listar secções]], [[#Mostrar elemento de texto|Mostrar elemento de texto]] e [[#Editar|Editar]]. A classe \code{edt.textui.main.Message} define os métodos para geração das mensagens de diálogo. Inicialmente, a aplicação tem um documento vazio e anónimo.
| |
| | |
| === Salvaguarda do Documento Actual ===
| |
| | |
| O conteúdo do documento pode ser guardado posterior recuperação (via serialização Java: '''java.io.Serializable'''). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:
| |
| | |
| * '''Criar''' -- Cria um novo documento anónimo não associado a nenhum ficheiro.
| |
| * '''Abrir''' -- Carrega um documento anteriormente salvaguardado, associado-se ao ficheiro nomeado: pede-se o nome do ficheiro a abrir~('''openFile()'''): caso não exista, é apresentada a mensagem '''fileNotFound()'''.
| |
| * '''Guardar''' -- Guarda o documento actual no ficheiro associado. Se não existir associação, pede-se o nome do ficheiro a utilizar, ficando a ele associada. Esta interacção realiza-se através do método '''newSaveAs()'''. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda. O estado transitório (directório de trabalho) não é salvaguardado.
| |
| | |
| Apenas existe um documento no editor (explicitamente criado ou aberto). A opção '''Sair''' nunca guarda o estado da aplicação, mesmo que existam alterações.
| |
| | |
| === Listar meta-informação ===
| |
| | |
| É apresentada a seguinte informação: título do documento, autores do documento, número de secções de topo do documento, número de figuras do documento.
| |
| | |
| <amsmath>\verb*|Título: |</amsmath> ''título do documento''
| |
| <amsmath>\verb*|Autor: |</amsmath> ''nome do autor 1''/''email do autor 1''
| |
| ...
| |
| <amsmath>\verb*|Autor: |</amsmath> ''nome do autor N''/''email do autor N''
| |
| <amsmath>\verb*|Secções de topo: |</amsmath> ''número de secções de topo''
| |
| <amsmath>\verb*|Dimensão do documento (bytes): |</amsmath> ''dimensão do documento (soma da dimensão dos títulos e dos parágrafos)''
| |
| <amsmath>\verb*|Identificadores únicos: |</amsmath> ''número de identificadores''
| |
| | |
| === Adicionar autor ===
| |
| | |
| É pedido o nome ('''requestAuthorName()''') e o email ('''requestEmail()''') do novo autor. Se o nome já estiver associado ao documento, apresenta a mensagem '''duplicateAuthor()''' e não executa nenhuma acção.
| |
| | |
| === Listar secções de topo ===
| |
| | |
| É apresentada a lista de títulos de todas as secções de topo do documento (um título por linha): cada título é precedido pelo seu identificador entre parênteses. O título do documento deve ser apresentado antes da lista de secções. Exemplo: <tt>[x123] {Isto é um Título}</tt>
| |
| | |
| === Mostrar elemento de texto ===
| |
| | |
| Permite apresentar o conteúdo do elemento de texto indicado pelo utilizador (através da especificação do identificador único'''requestElementId()'''). Se o elemento de texto não existir, é apresentada a mensagem '''noSuchTextElement()''' e a acção termina. Caso contrário, é apresentado o conteúdo. Se o elemento de texto de texto for um parágrafo, apresenta-se simplesmente o seu texto. Se for uma secção, apresenta-se tal como especificado em [[#Mostrar conteúdo|mostrar conteúdo]].
| |
| | |
| === Editar ===
| |
| | |
| Abre o menu de edição (alteração) do documento e do seu conteúdo, estabelecendo como secção actual a secção 0 (zero), ou seja, o nível de topo do documento.
| |
| | |
| == Menu de Edição ==
| |
| | |
| Este menu permite efectuar operações sobre um documento. A lista completa é a seguinte: [[#Alterar título|Alterar título]], [[#Listar secções|Listar secções]], [[#Mostrar conteúdo|Mostrar conteúdo]], [[#Ir para secção|Ir para secção]], [[#Inserir secção|Inserir secção]], [[#Nomear secção|Nomear secção]], [[#Remover secção|Remover secção]], [[#Inserir parágrafo|Inserir parágrafo]], [[#Nomear parágrafo|Nomear parágrafo]], [[#Alterar parágrafo|Alterar parágrafo]], [[#Remover parágrafo|Remover parágrafo]].
| |
| | |
| As etiquetas das opções deste menu estão definidas na classe '''edt.textui.section.MenuEntry'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''edt.textui.section.Message'''.
| |
| | |
| Em todos os casos, só podem ser indicados secções e parágrafos filhos da secção actual. O documento é estruturalmente semelhante a uma secção, sendo considerado a secção raiz (na abertura deste menu).
| |
| | |
| === Alterar título ===
| |
| | |
| Permite alterar o título da secção actual (ou do próprio documento). Para tal, pede-se o novo título ('''requestSectionTitle()''').
| |
| | |
| === Listar secções ===
| |
| | |
| É apresentada a lista de títulos de todas as subsecções da secção actual (recursivamente): cada título entre chavetas é precedido pelo seu identificador entre parênteses rectos. Exemplo: <amamath>\verb*|[x123] {Isto é um Título}|</amsmath>
| |
| | |
| === Mostrar conteúdo ===
| |
| | |
| Apresenta todo o conteúdo da secção actual: o texto de cada parágrafo é apresentado por ordem; cada secção é apresentada tal como no caso da apresentação do índice ([[#Listar secções|listar secções]]), seguida dos seus parágrafos e subsecções (apresentação recursiva).
| |
| | |
| === Ir para secção ===
| |
| | |
| Permite seleccionar a secção indicada pelo utilizador (através da especificação do identificador local '''requestSectionId()'''). Se a secção indicada não existir, continua na secção actual, sendo apresentada a mensagem '''noSuchSection()'''. Caso contrário, é apresentada a mensagem '''newActiveSection()''' e o menu de edição de secções é aberto para a secção seleccionada.
| |
| | |
| === Inserir secção ===
| |
| | |
| Permite inserir uma subsecção antes de outra de referência (indicada pelo identificador local '''requestSectionId()'''). É pedido o título ('''requestSectionTitle()''') da nova secção. Se a subsecção de referência não existir, insere a nova subsecção no final da secção actual.
| |
| | |
| === Nomear secção ===
| |
| | |
| Permite atribuir um identificador único (no contexto do documento) a uma secção. É pedido o identificador local (inteiro) da subsecção a identificar ('''requestSectionId()''') e o identificador único a atribuir ('''requestSectionId()''') (cadeia de caracteres). Se a secção não existir é apresentada a mensagem '''noSuchSection()''' e a acção termina. Se o identificador já existir, passa a designar a nova secção (a ligação anterior é destruída). Se a secção já tiver um identificador, a mensagem de aviso '''sectionNameChanged()''' é apresentada e é atribuído o novo identificador único à secção.
| |
| | |
| === Remover secção ===
| |
| | |
| Permite remover a secção indicada pelo utilizador ('''requestSectionId()'''). Se a secção indicada não existir, apresenta a mensagem '''noSuchSection()''' e não realiza nenhuma acção.
| |
| | |
| === Inserir parágrafo ===
| |
| | |
| Permite inserir um novo parágrafo antes de outro parágrafo da secção actual. É pedido o número do parágrafo de referência ('''requestParagraphId()''') e o texto do novo parágrafo ('''requestParagraphContent()'''). Se o parágrafo de referência não existir, insere o novo parágrafo no final da sequência de parágrafos da secção.
| |
| | |
| === Nomear parágrafo ===
| |
| | |
| Permite atribuir um identificador único (no contexto do documento) a um parágrafo. É pedido o número do parágrafo a identificar ('''requestParagraphId()''') e o identificador único a atribuir ('''requestParagraphId()''') (cadeia de caracteres). Se o parágrafo não existir é apresentada a mensagem '''noSuchParagraph()''' e a acção termina. Se o identificador já existir, passa a designar o novo parágrafo (a ligação anterior é destruída). Se o parágrafo já tiver um identificador, a mensagem de aviso '''paragraphNameChanged()''' é apresentada e é atribuído o novo identificador único ao parágrafo.
| |
| | |
| === Alterar parágrafo ===
| |
| | |
| Permite alterar o texto do parágrafo indicado. É pedido o número do parágrafo a alterar ('''requestParagraphId()''') e o texto do novo parágrafo ('''requestParagraphContent()'''). Se o parágrafo indicado não existir, apresenta a mensagem '''noSuchParagraph()''' e não realiza nenhuma acção.
| |
| | |
| === Remover Parágrafo ===
| |
| | |
| Permite remover o parágrafo indicado pelo utilizador ('''requestParagraphId()'''). Se o parágrafo indicado não existir, apresenta a mensagem '''noSuchParagraph()''' e não realiza nenhuma acção.
| |
| | |
| = Leitura de um Documento a Partir de Ficheiro =
| |
|
| |
| Além das opções de manipulação de ficheiros descritas no [[#Salvaguarda do Documento Actual|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java '''import''' (apresentada abaixo; este exemplo está no ficheiro '''test.import'''). Estes dados são apenas uma forma cómoda de inicialização e '''nunca''' são produzidos pela aplicação (nem mesmo para salvaguardar o estado para execuções futuras). Quando se especifica a propriedade, o sistema de ficheiros é povoado com as entidades do ficheiro indicado (uma por linha).
| |
| | |
| Assume-se que não há entradas mal-formadas (nestes ficheiros, as secções têm sempre identificador; os parágrafos não são identificados). Sugere-se a utilização do método '''String.split''', para dividir uma cadeia de caracteres em campos.
| |
| | |
| Objects in Space
| |
| Obi-Wan Kenobi/ob1@tatooine.geocities.com|Master Yoda/yoda@dagobah.net|Luke Skywalker/luke@jedi.org
| |
| SECTION|lfd|A Walk in the Desert
| |
| PARAGRAPH|These aren't the droids you're looking for.
| |
| SECTION|wm|Patience You Must Have
| |
| PARAGRAPH|Do or do not.
| |
| PARAGRAPH|There is no try.
| |
| SECTION|dvls|Drama in the Clouds
| |
| PARAGRAPH|Obi-Wan never told you what happened to your father.
| |
| PARAGRAPH|He told me enough! He told me YOU killed him.
| |
| PARAGRAPH|NOOOOOOOOOOOOOOOOOOO...
| |
| | |
| O editor nunca produz ficheiros neste formato, nem os pode ler a partir de nenhum menu.
| |
| | |
| = Considerações sobre Flexibilidade e Eficiência =
| |
|
| |
| Devem ser possíveis extensões ou alterações de funcionalidade com impacto mínimo no código já produzido para o editor de texto. O objectivo é aumentar a flexibilidade da aplicação relativamente ao suporte de novas funções. Em particular, a solução encontrada para visualizar o conteúdo do documento deve ser suficientemente flexível por forma a que se possa visualizar o conteúdo de um documento noutro formato (por exemplo XML) sem que isso implique alterações no código ''core'' da aplicação.
| |
| | |
| = Execução dos Programas e Testes Automáticos =
| |
| | |
| Usando os ficheiros '''test.import''', '''test.in''' e '''test.out''', é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável '''CLASSPATH''' (ou da opção equivalente '''-cp''' do comando '''java'''), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação ('''edt.textui.Editor.main'''). As propriedades são tratadas automaticamente pelo código de apoio.
| |
| | |
| java -Dimport=test.import -Din=test.in -Dout=test.outhyp edt.textui.Editor
| |
| | |
| Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída '''test.outhyp'''. Em caso de sucesso, os ficheiros das saídas esperada ('''test.out''') e obtida ('''test.outhyp''') devem ser iguais. A comparação pode ser feita com o comando:
| |
| | |
| diff -b test.out test.outhyp
| |
| | |
| Este comando não deve produzir qualquer resultado quando os ficheiros são iguais. Note-se, contudo, que este teste não garante o correcto funcionamento do código desenvolvido, apenas verificando alguns aspectos da sua funcionalidade.
| |
| | |
| [[category:Ensino]]
| |
| [[category:PO]]
| |
| [[category:Projecto de PO]]
| |
| [[en:Object-Oriented Programming]]
| |