001package org.unix4j.operation; 002 003import org.unix4j.command.AbstractCommand; 004import org.unix4j.command.Arguments; 005import org.unix4j.context.ExecutionContext; 006import org.unix4j.line.Line; 007import org.unix4j.operation.AdHocCommand.Args; 008import org.unix4j.processor.LineProcessor; 009 010/** 011 * Implementation of an ad-hoc command based on a {@link LineOperation}. 012 */ 013public class AdHocCommand extends AbstractCommand<Args> { 014 015 /** 016 * The "adhoc" name for this command. 017 */ 018 public static final String NAME = "adhoc"; 019 020 public AdHocCommand(LineOperation operation) { 021 super(NAME, new Args(operation)); 022 } 023 024 /** 025 * Arguments for {@link AdHocCommand}. 026 */ 027 public static final class Args implements Arguments<Args> { 028 private final LineOperation operation; 029 030 /** 031 * Constructor with the single operation argument passed to the 032 * constructor of {@link AdHocCommand}. 033 * 034 * @param operation 035 * the operation argument 036 */ 037 public Args(LineOperation operation) { 038 if (operation == null) { 039 throw new NullPointerException("operation cannot be null"); 040 } 041 this.operation = operation; 042 } 043 044 public final LineOperation getOperation() { 045 return operation; 046 } 047 048 @Override 049 public Args getForContext(ExecutionContext context) { 050 return this;// no variable args, hence the same for all contexts 051 } 052 053 @Override 054 public String toString() { 055 return "--operation " + operation; 056 } 057 } 058 059 @Override 060 public LineProcessor execute(final ExecutionContext context, final LineProcessor output) { 061 return new LineProcessor() { 062 final OperationOutput operationOutput = new OperationOutput(output); 063 final LineOperation operation = getArguments(context).getOperation(); 064 065 @Override 066 public boolean processLine(Line line) { 067 operation.operate(context, line, operationOutput); 068 return operationOutput.isOpen(); 069 } 070 071 @Override 072 public void finish() { 073 operationOutput.close(); 074 } 075 }; 076 } 077 078 private static class OperationOutput implements LineProcessor { 079 private final LineProcessor output; 080 private boolean open = true; 081 082 public OperationOutput(LineProcessor output) { 083 this.output = output; 084 } 085 086 @Override 087 public boolean processLine(Line line) { 088 if (open) { 089 open = output.processLine(line); 090 return open; 091 } 092 return false; 093 } 094 095 @Override 096 public void finish() { 097 open = false; 098 } 099 100 public boolean isOpen() { 101 return open; 102 } 103 104 public void close() { 105 finish(); 106 output.finish(); 107 } 108 } 109 110}