package tirateima.controlador; import java.util.List; import java.util.ListIterator; import java.util.Stack; import tirateima.gui.arquivos.AbstractArquivo; import tirateima.gui.arquivos.VarText; import tirateima.gui.variaveis.VarChar; import tirateima.gui.variaveis.VarGrade; import tirateima.gui.variaveis.VarInteger; import tirateima.gui.variaveis.VarReal; import tirateima.gui.variaveis.VarRecord; import tirateima.gui.variaveis.VarString; import tirateima.gui.variaveis.Variavel; import tirateima.parser.TiraTeimaParserConstants; import tirateima.parser.Token; /** * Comando de chamada de operação, que pode ser funções do sistema * (manipulação de arquivos, write) ou de função definida pelo * usuário. * * @author Luciano Santos */ @SuppressWarnings("unchecked") public class CommandOperationCall extends Command implements TiraTeimaParserConstants { private Token cmd; List<Object> args; public CommandOperationCall(Token operation, List<Object> args) { this.cmd = operation; this.args = args; } /** * Implementa o execute herdado do comando. * * Recebe os tipos de operações e as executa. */ public void execute(Controlador c) throws TiraTeimaLanguageException { AbstractArquivo arq; switch (cmd.kind) { case KW_ASSIGN: case KW_RESET: case KW_REWRITE: case KW_READ: case KW_READLN: case KW_CLOSE: if ((arq = getFile(c, args)) == null) gerarErro("Arquivo não encontrado!"); //remove o primeiro argumento para usar o método executeFileOperation Object argumento = args.remove(0); executeFileOperation(c, cmd, arq, args); //restaura o primeiro argumento para caso o comando seja re-executado args.add(0, argumento); break; case KW_WRITE: case KW_WRITELN: try { if ((arq = getFile(c, args)) == null) gerarErro("Arquivo não encontrado!"); args.remove(0); executeWriteOperation(c, cmd, arq, args); break; } catch (TiraTeimaLanguageException e) { executeWriteOperation(c, cmd, null, args); } break; case KW_COMMENT: executeAlertOperation(c, cmd, args); break; case KW_SOUND: executeSoundOperation(c, cmd); break; } } @Override public void revert(Controlador c) throws TiraTeimaLanguageException, ExecutionException { // TODO Auto-generated method stub } /** * Recebe um gerador e argumentos e retorna um arquivo. * * Usada para pegar o arquivo do gerenciador de arquivos. * @param g * @param args * @return * @throws TiraTeimaLanguageException */ private AbstractArquivo getFile(Controlador c, List<Object> args) throws TiraTeimaLanguageException { //Pilha auxiliar para armazenar temporariamente os valores da pilha. Stack<Object> pilhaAux = new Stack<Object>(); ListIterator<Object> i = args.listIterator(); if (!i.hasNext()) gerarErro("Nome de arquivo era esperado"); /** checa se o primeiro é um arquivo*/ Object obj = i.next(); if (obj instanceof Stack<?>){ Stack<Object> stack = (Stack<Object>) obj; if (stack.size() == 1) { String name = (String) stack.pop(); pilhaAux.push(name); restaurarPilha(stack, pilhaAux); obj = stack; return c.ga.getArquivo(name); } else gerarErro("Nome de arquivo era esperado."); } else gerarErro("Nome de arquivo era esperado."); return null; } /** * Executa uma operação de arquivo. * * Recebe um tipo de operação sobre o arquivo e gera erro se houver problema. * Caso não haja erro, executa a operação solicitada sobre o arquivo. * * @param g * @param cmd * @param arq * @param args * @throws TiraTeimaLanguageException */ private void executeFileOperation( Controlador c, Token cmd, AbstractArquivo arq, List<Object> args) throws TiraTeimaLanguageException { Object aux; try { switch (cmd.kind) { case KW_ASSIGN: if (args.size() != 1) gerarErro("Número de parâmetros incorreto para comando 'assign'."); aux = args.get(0); if (!(aux instanceof String)) { gerarErro("Uma string era esperada."); } arq.assign((String) aux); break; case KW_RESET: if (args.size() != 0) gerarErro("Número de parâmetros incorreto para comando 'reset'."); arq.reset(); break; case KW_REWRITE: if (args.size() != 0) gerarErro("Número de parâmetros incorreto para comando 'rewrite'."); arq.rewrite(); break; case KW_CLOSE: if (args.size() != 0) gerarErro("Número de parâmetros incorreto para comando 'close'."); arq.close(); break; case KW_READ: case KW_READLN: executeReadOperation(c, cmd, arq, args); break; } } catch (Exception e) { gerarErro("Falha ao executar operação no arquivo."); } } /** * Executa operação de leitura do arquivo solicitada pelo usuário. * @param g * @param cmd * @param arq * @param args * @throws TiraTeimaLanguageException * @throws Exception */ private void executeReadOperation( Controlador c, Token cmd, AbstractArquivo arq, List<Object> args) throws TiraTeimaLanguageException, Exception { /** verifica número de parâmetros */ int size = args.size(); if ((size < 1) || (size > 2)) { gerarErro("Número de parâmetros incorreto para comando 'read'."); } /** pega o tipo da variável a ser lida */ Object first = args.get(0); if (!(first instanceof Stack)) gerarErro("Era esperada uma variável."); ListIterator<Object> i = ((Stack<Object>) first).listIterator(); Variavel v = c.mostrador.getCopiaVariavel((String) i.next()); while (i.hasNext()) { Object aux = i.next(); if (aux instanceof String) { v = ((VarRecord) v).getCopiaCampo((String) aux); } else { v = ((VarGrade) v).getCopiaTipo(); } } Object value = null; if (v instanceof VarString) { if (size == 2) { Object aux = args.get(1); if (!(aux instanceof Integer)) { gerarErro("Era esperado um inteiro positivo."); } int length = (Integer) aux; value = ((VarText) arq).readString(length); if (cmd.kind == KW_READLN) ((VarText) arq).readln(); } else { value = ((VarText) arq).readLine(); } } else { if (size > 1) gerarErro("Número de parâmetros incorreto para comando 'read'."); if (v instanceof VarReal) { value = ((VarText) arq).readReal(); } else if (v instanceof VarInteger) { value = ((VarText) arq).readInt(); } else if (v instanceof VarChar) { value = ((VarText) arq).read(); } if (cmd.kind == KW_READLN) ((VarText) arq).readln(); } setValue(c.mostrador, (Stack<Object>) first, value); } /** * Executa operação de escrita no arquivo. * @param g * @param cmd * @param arq * @param args */ private void executeWriteOperation( Controlador c, Token cmd, AbstractArquivo arq, List<Object> args) { ListIterator<Object> i = args.listIterator(); Object obj; while (i.hasNext()) { obj = i.next(); if (obj instanceof List<?>) obj = getValue(c, (List<Object>) obj); //escreve no arquivo if (arq != null) { ((VarText) arq).write(obj.toString()); } else { //escreve no console c.console.print(obj.toString()); } } if (cmd.kind == KW_WRITELN) { if (arq != null) { ((VarText) arq).writeln(""); } else { //escreve no console c.console.println(); } } } /** * Executa a operação de alerta mostrando um alerta no tirateima * @param g * @param cmd * @param args */ private void executeAlertOperation( Controlador c, Token cmd, List<Object> args) { ListIterator<Object> i = args.listIterator(); Object obj; while (i.hasNext()) { obj = i.next(); if (obj instanceof List<?>) obj = getValue(c, (List<Object>) obj); //marca estado para mostrar um comentario c.alerta.print(obj.toString()); } } /** * Executa operação de som, tocando um som para o usuário. * @param g * @param cmd */ private void executeSoundOperation( Controlador c, Token cmd) { //marca estado para tocar um som c.alerta.tocaSom(); } }