1 package de.spiritscorp.datasync.controller;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.nio.file.Path;
24 import java.util.Map;
25
26 import de.spiritscorp.datasync.ScanType;
27 import de.spiritscorp.datasync.model.FileAttributes;
28
29
30
31
32
33
34
35
36
37
38
39
40 @SuppressWarnings( "PMD.LongVariable" )
41 class LogFormatter {
42
43
44
45 private static final long BYTES_PER_GIB_THRESHOLD = 1_073_741_824L;
46
47 private static final long BYTES_PER_MIB_THRESHOLD = 1_048_576L;
48
49 private static final long BYTES_PER_KIB_THRESHOLD = 1_024L;
50
51 private static final double CONVERSION_FACTOR_MIB = 1_048_576.0;
52
53 private static final double CONVERSION_FACTOR_KIB = 1_024.0;
54
55 private static final long MINIMUM_BYTE_PLURAL_THRESHOLD = 1L;
56
57
58
59 private static final double NANOSECONDS_PER_SECOND = 1_000_000_000.0;
60
61 private static final int SECONDS_PER_TWO_HOURS = 7200;
62
63 private static final int SECONDS_PER_ONE_HOUR = 3600;
64
65 private static final int SECONDS_PER_MINUTE = 60;
66
67
68
69 private static final int DEFAULT_LOG_DISPLAY_LIMIT = 10_000;
70
71 private static final int INITIAL_LOG_BUFFER_SIZE = 2_000;
72
73 private static final int DISPLAY_LIMIT_HALF_DIVIDER = 2;
74
75
76
77
78
79
80
81 String getReadableBytes( final long bytes ) {
82 if( bytes > BYTES_PER_GIB_THRESHOLD ) {
83 return String.format( "%.3f GiB", bytes / CONVERSION_FACTOR_MIB / CONVERSION_FACTOR_KIB );
84 }else if( bytes > BYTES_PER_MIB_THRESHOLD ) {
85 return ( bytes / BYTES_PER_MIB_THRESHOLD ) + " MiB";
86 }else if( bytes > BYTES_PER_KIB_THRESHOLD ) {
87 return ( bytes / BYTES_PER_KIB_THRESHOLD ) + " KiB";
88 }else if( bytes > MINIMUM_BYTE_PLURAL_THRESHOLD ) {
89 return bytes + " bytes";
90 }else {
91 return bytes + " byte";
92 }
93 }
94
95
96
97
98
99
100
101 String getTimeFormatted( final long endTimeNano ) {
102 final double endTimeSec = endTimeNano / NANOSECONDS_PER_SECOND;
103
104
105 final long totalSeconds = (long) endTimeSec;
106 final long hours = totalSeconds / SECONDS_PER_ONE_HOUR;
107 final long minutes = totalSeconds % SECONDS_PER_ONE_HOUR / SECONDS_PER_MINUTE;
108 final double seconds = endTimeSec % SECONDS_PER_MINUTE;
109
110 if( endTimeSec >= SECONDS_PER_TWO_HOURS ) {
111 return String.format( "%d Stunden %d Minuten %.3f Sekunden", hours, minutes, seconds );
112 }else if( endTimeSec >= SECONDS_PER_ONE_HOUR ) {
113 return String.format( "%d Stunde %d Minuten %.3f Sekunden", hours, minutes, seconds );
114 }else if( endTimeSec >= SECONDS_PER_MINUTE ) {
115 return String.format( "%d Minuten %.3f Sekunden", minutes, seconds );
116 }else {
117 return String.format( "%.3f Sekunden", endTimeSec );
118 }
119 }
120
121
122
123
124
125
126
127
128
129
130
131 String formatMaps( final ScanType scanType, final Map<Path, FileAttributes> sourceMap, final Map<Path, FileAttributes> destMap, final Map<Path, FileAttributes> failMap ) {
132 final String line = System.lineSeparator();
133 final String scanFinish = "Scan abgeschlossen!\n";
134 final String tableSep = "------------------------------\n";
135 final StringBuilder stringBuilder = new StringBuilder( INITIAL_LOG_BUFFER_SIZE );
136
137 if( scanType == ScanType.SYNCHRONIZE ) {
138 stringBuilder.append( scanFinish ).append( "Zu kopieren in das Sourceverzeichnis:\n" ).append( tableSep );
139 if( sourceMap != null ) {
140 buildEntries( stringBuilder, sourceMap, DEFAULT_LOG_DISPLAY_LIMIT );
141 }
142 stringBuilder.append( line ).append( "Zu kopieren in das Zielverzeichnis:\n" ).append( tableSep );
143 if( destMap != null ) {
144 buildEntries( stringBuilder, destMap, DEFAULT_LOG_DISPLAY_LIMIT );
145 }
146 if( failMap != null && !failMap.isEmpty() ) {
147 stringBuilder.append( line ).append( "Zu löschende Dateien:\n" ).append( tableSep );
148 buildEntries( stringBuilder, failMap, DEFAULT_LOG_DISPLAY_LIMIT );
149 }
150 }else {
151 stringBuilder.append( scanFinish ).append( "Zu kopierende Dateien:\n" ).append( tableSep );
152 if( sourceMap != null ) {
153 buildEntries( stringBuilder, sourceMap, DEFAULT_LOG_DISPLAY_LIMIT );
154 }
155 stringBuilder.append( line ).append( "Zu löschende Dateien:\n" ).append( tableSep );
156 if( destMap != null ) {
157 buildEntries( stringBuilder, destMap, DEFAULT_LOG_DISPLAY_LIMIT );
158 }
159 if( failMap != null && !failMap.isEmpty() ) {
160 stringBuilder.append( line ).append( "Fehlerhafter Zugriff:\n" ).append( tableSep );
161 buildEntries( stringBuilder, failMap, DEFAULT_LOG_DISPLAY_LIMIT );
162 }
163 }
164 return stringBuilder.toString();
165 }
166
167
168
169
170
171
172
173
174
175
176 private StringBuilder buildEntries( final StringBuilder stringBuilder, final Map<Path, FileAttributes> printableMap, final int displayLimit ) {
177 final String valueSeparator = " , ";
178 int index = 0;
179 for( final Map.Entry<Path, FileAttributes> entry : printableMap.entrySet() ) {
180 final FileAttributes value = entry.getValue();
181 stringBuilder.append( value.getFileName() ).append( valueSeparator )
182 .append( getReadableBytes( value.getSize() ) ).append( valueSeparator )
183 .append( value.getModTimeString() ).append( valueSeparator )
184 .append( value.getCreateTimeString() ).append( valueSeparator )
185 .append( value.getFileHash() ).append( " " )
186 .append( entry.getKey().toString() )
187 .append( '\n' );
188
189 index++;
190 if( index > ( displayLimit / DISPLAY_LIMIT_HALF_DIVIDER ) ) {
191 break;
192 }
193 }
194 return stringBuilder;
195 }
196
197 }