Skip to content

Commit e59d76c

Browse files
committed
Separate Utils module from DBMonitoringWindowApp module
1 parent 2f6693a commit e59d76c

18 files changed

+2330
-0
lines changed

Utils/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build/

Utils/bin/main/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/root/

Utils/bin/test/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/root/

Utils/build.gradle

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
plugins {
2+
id 'java'
3+
}
4+
5+
repositories {
6+
mavenCentral()
7+
}
8+
9+
dependencies {
10+
11+
// Apache Commons Library
12+
implementation 'org.apache.commons:commons-configuration2:2.7'
13+
implementation 'org.apache.commons:commons-lang3:3.11'
14+
15+
// Apache POI
16+
implementation 'org.apache.poi:poi:3.17'
17+
implementation 'org.apache.poi:poi-ooxml-schemas:3.17'
18+
implementation 'org.apache.poi:poi-scratchpad:3.17'
19+
implementation 'org.apache.poi:poi-ooxml:3.17'
20+
21+
// Logback
22+
implementation 'ch.qos.logback:logback-classic:1.2.3'
23+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package root.utils;
2+
3+
public class ConsoleUtils {
4+
public static final String RESET = "\u001B[0m";
5+
public static final String FONT_BLACK = "\u001B[30m";
6+
public static final String FONT_RED = "\u001B[31m";
7+
public static final String FONT_GREEN = "\u001B[32m";
8+
public static final String FONT_YELLOW = "\u001B[33m";
9+
public static final String FONT_BLUE = "\u001B[34m";
10+
public static final String FONT_PURPLE = "\u001B[35m";
11+
public static final String FONT_CYAN = "\u001B[36m";
12+
public static final String FONT_WHITE = "\u001B[37m";
13+
public static final String BACKGROUND_BLACK = "\u001B[40m";
14+
public static final String BACKGROUND_RED = "\u001B[41m";
15+
public static final String BACKGROUND_GREEN = "\u001B[42m";
16+
public static final String BACKGROUND_YELLOW = "\u001B[43m";
17+
public static final String BACKGROUND_BLUE = "\u001B[44m";
18+
public static final String BACKGROUND_PURPLE = "\u001B[45m";
19+
public static final String BACKGROUND_CYAN = "\u001B[46m";
20+
public static final String BACKGROUND_WHITE = "\u001B[47m";
21+
}
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
package root.utils;
2+
3+
import java.lang.reflect.Constructor;
4+
import java.lang.reflect.Field;
5+
import java.lang.reflect.Method;
6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.LinkedHashMap;
9+
import java.util.List;
10+
import java.util.Map;
11+
import java.util.stream.Collectors;
12+
13+
import org.apache.commons.lang3.StringUtils;
14+
import org.apache.commons.text.StringEscapeUtils;
15+
16+
public class CsvUtils {
17+
18+
/**
19+
* 객체리스트를 csv string 형태로 변환한다.
20+
*
21+
* @param list
22+
* @param clazz
23+
* @return
24+
*/
25+
public static String toCsvString(List<?> list, Class<?> clazz) {
26+
StringBuffer sb = new StringBuffer();
27+
28+
try {
29+
Field[] fields = clazz.getDeclaredFields();
30+
List<String> fieldName = Arrays.asList(fields).stream().map(f -> (f.getName()))
31+
.collect(Collectors.toList());
32+
33+
sb.append(createCsvHeader(fieldName));
34+
35+
for (Object item : list) {
36+
sb.append(System.lineSeparator()).append(createCsvRow(item, clazz));
37+
}
38+
} catch (IllegalArgumentException | IllegalAccessException e) {
39+
e.printStackTrace();
40+
}
41+
42+
return sb.toString();
43+
}
44+
45+
/**
46+
* 문자열리스트를 comma(,) 문자로 이어 csv형태의 헤더를 반환한다.
47+
*
48+
* @param fieldNames
49+
* @return
50+
*/
51+
public static String createCsvHeader(List<String> fieldNames) {
52+
StringBuffer sb = new StringBuffer();
53+
54+
for (String f : fieldNames) {
55+
sb.append(sb.isEmpty() ? wrapInDoubleQuotation(f) : "," + wrapInDoubleQuotation(f));
56+
}
57+
58+
return sb.toString();
59+
}
60+
61+
/**
62+
* 매개변수로 전달된 Class의 필드와, 부모 클래스의 필드를 comma(,)로 이어 csv형태의 헤더를 반환한다.
63+
*
64+
* @param clazz
65+
* @return
66+
*/
67+
public static String createCsvHeader(Class<?> clazz) {
68+
StringBuffer sb = new StringBuffer();
69+
70+
try {
71+
List<Field> fields = getAllFields(clazz);
72+
List<String> fieldName = fields.stream().map(f -> (f.getName())).collect(Collectors.toList());
73+
74+
sb.append(createCsvHeader(fieldName));
75+
} catch (IllegalArgumentException e) {
76+
e.printStackTrace();
77+
}
78+
79+
return sb.toString();
80+
}
81+
82+
/**
83+
*
84+
* @param object
85+
* @param clazz
86+
* @return
87+
* @throws IllegalArgumentException
88+
* @throws IllegalAccessException
89+
*/
90+
public static String createCsvRow(Object object, Class<?> clazz)
91+
throws IllegalArgumentException, IllegalAccessException {
92+
StringBuffer sb = new StringBuffer();
93+
94+
if (StringUtils.equals(object.getClass().getName(), clazz.getName())) {
95+
for (Field f : getAllFields(clazz)) {
96+
@SuppressWarnings("deprecation")
97+
boolean accessible = f.isAccessible();
98+
99+
f.setAccessible(true);
100+
101+
String appender = sb.isEmpty()
102+
? StringUtils.getIfEmpty(wrapInDoubleQuotation(f.get(object).toString()),
103+
() -> wrapInDoubleQuotation("-"))
104+
: "," + StringUtils.getIfEmpty(wrapInDoubleQuotation(f.get(object).toString()),
105+
() -> wrapInDoubleQuotation("-"));
106+
sb.append(appender);
107+
108+
f.setAccessible(accessible);
109+
}
110+
}
111+
112+
return sb.toString();
113+
}
114+
115+
/**
116+
*
117+
* @param <T>
118+
* @param headers
119+
* @param csvString
120+
* @param type
121+
* @return
122+
*/
123+
public static <T> List<T> parseCsvToBeanList(List<String> headers, String csvString, Class<T> type) {
124+
List<T> beanList = new ArrayList<>();
125+
126+
List<Map<String, String>> parsedList = parseCsvString(headers, csvString);
127+
128+
for (Map<String, String> row : parsedList) {
129+
130+
Constructor<T> constructor;
131+
Object instance;
132+
Class<?> instanceClass;
133+
try {
134+
constructor = type.getConstructor();
135+
instance = constructor.newInstance();
136+
instanceClass = instance.getClass();
137+
} catch (Exception e) {
138+
e.printStackTrace();
139+
return null;
140+
}
141+
142+
for (String header : row.keySet()) {
143+
String setterName = "set" + header.substring(0, 1).toUpperCase() + header.substring(1);
144+
145+
try {
146+
List<Field> allFields = getAllFields(instance.getClass());
147+
Class<?> fieldType = allFields.stream().filter(f -> f.getName().equals(header)).findFirst().get()
148+
.getType();
149+
150+
Object fieldValue = null;
151+
152+
if (fieldType == int.class) {
153+
fieldValue = Integer.valueOf(row.get(header));
154+
} else if (fieldType == double.class) {
155+
try {
156+
fieldValue = Double.valueOf(row.get(header));
157+
} catch (Exception e) {
158+
fieldValue = -1;
159+
}
160+
} else {
161+
fieldValue = row.get(header);
162+
}
163+
164+
Method method = instanceClass.getMethod(setterName, fieldType);
165+
method.invoke(instance, fieldValue);
166+
167+
} catch (Exception e) {
168+
e.printStackTrace();
169+
}
170+
}
171+
172+
beanList.add((type.cast(instance)));
173+
}
174+
return beanList;
175+
}
176+
177+
/**
178+
*
179+
* @param headers
180+
* @param csvString
181+
* @return
182+
*/
183+
public static List<Map<String, String>> parseCsvString(List<String> headers, String csvString) {
184+
List<Map<String, String>> result = new ArrayList<>();
185+
186+
String[] csvLines = csvString.split("\n");
187+
for (String line : csvLines) {
188+
Map<String, String> map = new LinkedHashMap<>();
189+
190+
Map<Integer, String> lineMap = parseCsvLine(line);
191+
for (int index : lineMap.keySet()) {
192+
if (index >= headers.size()) {
193+
continue;
194+
} else {
195+
map.put(headers.get(index), lineMap.get(index));
196+
}
197+
}
198+
199+
result.add(map);
200+
}
201+
202+
return result;
203+
}
204+
205+
/**
206+
* csv 형태의 문자열을 파싱하여 순서대로 Map객체에 담아 반환한다.
207+
*
208+
* @param csvLine
209+
* @return
210+
*/
211+
public static Map<Integer, String> parseCsvLine(String csvLine) {
212+
Map<Integer, String> map = new LinkedHashMap<>();
213+
214+
int index = 0;
215+
boolean isFirst = true;
216+
boolean isOpen = false;
217+
StringBuilder element = new StringBuilder();
218+
for (char c : csvLine.toCharArray()) {
219+
if (c == '"') {
220+
isOpen = !isOpen;
221+
if (isFirst) {
222+
isFirst = false;
223+
continue;
224+
}
225+
226+
if (!isOpen) {
227+
map.put(index, StringEscapeUtils.unescapeHtml4(element.toString()));
228+
element = new StringBuilder();
229+
}
230+
} else if (c == ',') {
231+
if (isOpen) {
232+
element.append(c);
233+
} else {
234+
index++;
235+
}
236+
} else {
237+
element.append(c);
238+
}
239+
}
240+
return map;
241+
}
242+
243+
/**
244+
* 문자열을 쌍따옴표로 감싼 후 반환한다. 단, 문자열 내에 쌍따옴표가 있다면 html escape된 문자로 변환한다.
245+
*
246+
* @param string
247+
* @return
248+
*/
249+
private static String wrapInDoubleQuotation(String string) {
250+
return StringUtils.join("\"", StringEscapeUtils.escapeHtml4(string), "\"");
251+
}
252+
253+
/**
254+
* 매개변수로 전달된 클래스의 Field와, 부모클래스의 Field까지 Reflection하여 반환한다.
255+
*
256+
* @param clazz
257+
* @return
258+
*/
259+
private static List<Field> getAllFields(Class<?> clazz) {
260+
List<Field> fields = new ArrayList<Field>();
261+
262+
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
263+
264+
Class<?> superClazz = clazz.getSuperclass();
265+
if (superClazz != null) {
266+
fields.addAll(getAllFields(superClazz));
267+
}
268+
269+
return fields;
270+
}
271+
}

0 commit comments

Comments
 (0)