001package org.unix4j.unix.uniq; 002 003import java.util.LinkedHashMap; 004import java.util.Map; 005 006import org.unix4j.context.ExecutionContext; 007import org.unix4j.line.Line; 008import org.unix4j.processor.LineProcessor; 009 010/** 011 * Line processors implementing the actual uniq command execution for the case 012 * when the {@link UniqOption#global global} option is selected. The actual 013 * processors are member classes of this abstract base class. 014 */ 015abstract class GlobalProcessor extends UniqProcessor { 016 protected final Map<Line, Long> lineToCount = new LinkedHashMap<Line, Long>(); 017 public GlobalProcessor(UniqCommand command, ExecutionContext context, LineProcessor output) { 018 super(command, context, output); 019 } 020 021 /** 022 * Line processor implementing the actual uniq command execution for the 023 * case when only the {@link UniqOption#global global} option is selected. 024 */ 025 public static class Normal extends GlobalProcessor { 026 public Normal(UniqCommand command, ExecutionContext context, LineProcessor output) { 027 super(command, context, output); 028 } 029 @Override 030 protected boolean processLine(Line line, LineProcessor output) { 031 lineToCount.put(line, null);//we don't really need the count 032 return true;// we want all input 033 } 034 @Override 035 public void finish() { 036 final LineProcessor output = getOutput(); 037 for (final Line line : lineToCount.keySet()) { 038 output.processLine(line); 039 } 040 lineToCount.clear(); 041 output.finish(); 042 } 043 } 044 /** 045 * Abstract base class for member classes {@link UniqueOnly}, 046 * {@link DuplicateOnly} and {@link Count} 047 */ 048 abstract protected static class UniqueDuplicateCount extends GlobalProcessor { 049 private static final Long ONE = Long.valueOf(1); 050 private long maxCount = 0; 051 public UniqueDuplicateCount(UniqCommand command, ExecutionContext context, LineProcessor output) { 052 super(command, context, output); 053 } 054 @Override 055 protected boolean processLine(Line line, LineProcessor output) { 056 Long count = lineToCount.put(line, ONE); 057 if (count != null) { 058 count++; 059 lineToCount.put(line, count); 060 maxCount = Math.max(maxCount, count); 061 } else { 062 maxCount = Math.max(maxCount, 1); 063 } 064 return true;// we want all input 065 } 066 @Override 067 public void finish() { 068 final LineProcessor output = getOutput(); 069 final int maxDigits = String.valueOf(maxCount).length(); 070 for (final Map.Entry<Line, Long> e : lineToCount.entrySet()) { 071 writeLine(e.getKey(), e.getValue(), maxDigits, output); 072 } 073 lineToCount.clear(); 074 maxCount = 0; 075 output.finish(); 076 } 077 abstract protected void writeLine(Line line, long count, int maxCountDigits, LineProcessor output); 078 } 079 /** 080 * Line processor implementing the actual uniq command execution for the 081 * case when the {@link UniqOption#global global} option is selected along 082 * with the {@link UniqOption#uniqueOnly uniqueOnly} option. 083 */ 084 public static class UniqueOnly extends UniqueDuplicateCount { 085 public UniqueOnly(UniqCommand command, ExecutionContext context, LineProcessor output) { 086 super(command, context, output); 087 } 088 @Override 089 protected void writeLine(Line line, long count, int maxCountDigits, LineProcessor output) { 090 if (count == 1) { 091 output.processLine(line); 092 } 093 } 094 } 095 /** 096 * Line processor implementing the actual uniq command execution for the 097 * case when the {@link UniqOption#global global} option is selected along 098 * with the {@link UniqOption#duplicatedOnly duplicatedOnly} option. 099 */ 100 public static class DuplicateOnly extends UniqueDuplicateCount { 101 public DuplicateOnly(UniqCommand command, ExecutionContext context, LineProcessor output) { 102 super(command, context, output); 103 } 104 @Override 105 protected void writeLine(Line line, long count, int maxCountDigits, LineProcessor output) { 106 if (count > 1) { 107 output.processLine(line); 108 } 109 } 110 } 111 /** 112 * Line processor implementing the actual uniq command execution for the 113 * case when the {@link UniqOption#global global} option is selected along 114 * with the {@link UniqOption#count count} option. 115 */ 116 public static class Count extends UniqueDuplicateCount { 117 public Count(UniqCommand command, ExecutionContext context, LineProcessor output) { 118 super(command, context, output); 119 } 120 @Override 121 protected void writeLine(Line line, long count, int maxCountDigits, LineProcessor output) { 122 CountUtil.writeCountLine(line, count, Math.max(3, maxCountDigits), output); 123 } 124 } 125 126}