getInputStream()
last analyzed

Size

Total Lines 1
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 1
ccs 0
cts 0
cp 0
1
/*
2
 * Copyright 2014, Armenak Grigoryan, and individual contributors as indicated
3
 * by the @authors tag. See the copyright.txt in the distribution for a
4
 * full listing of individual contributors.
5
 *
6
 * This is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as
8
 * published by the Free Software Foundation; either version 2.1 of
9
 * the License, or (at your option) any later version.
10
 *
11
 * This software is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
 * Lesser General Public License for more details.
15
 */
16
package com.strider.datadefender.anonymizer.functions;
17
18
import com.strider.datadefender.functions.NamedParameter;
19
import com.strider.datadefender.requirement.registry.RequirementFunction;
20
import com.strider.datadefender.utils.Xeger;
21
22
import java.io.InputStreamReader;
23
import java.io.BufferedReader;
24
import java.io.FileReader;
25
import java.io.IOException;
26
import java.io.InputStream;
27
import java.time.LocalDate;
28
import java.time.LocalDateTime;
29
import java.time.ZoneOffset;
30
import java.time.format.DateTimeFormatter;
31
import java.util.Collections;
32
import java.util.HashMap;
33
import java.util.Map;
34
import java.util.Iterator;
35
import java.util.ArrayList;
36
import java.util.List;
37
import java.util.Scanner;
38
39
import org.apache.commons.lang3.RandomUtils;
40
41
import lombok.extern.log4j.Log4j2;
42
43
/**
44
 * Core set of helpers for data anonymization.
45
 *
46
 * @author Armenak Grigoryan
47
 */
48
@Log4j2
49
public class Core extends RequirementFunction {
50
51
    private static final Map<String, List<String>> stringLists = new HashMap<>();
52
    private static final Map<String, Iterator<String>> stringIters = new HashMap<>();
53
    private static final  List<String> words = new ArrayList<>();
54
    private static String hash = null;
55
    
56
    public static interface InputStreamSupplier {
57
        public InputStream getInputStream() throws IOException;
58
    }
59 1
60 2
    /**
61 479619
     * Static block for loading words from dictionary
62 479617
     */
63
    static {
64
        try (Scanner scanner = new Scanner(Core.class.getResourceAsStream("dictionary.txt"))) {
65
            while (scanner.hasNext()) {
66
                words.add(scanner.next());
67
            }
68
        }
69
    }
70
    
71
    /**
72
     * Static block to load hash string for "salting" the encryption
73 6
     */
74 12
    static {
75 4
        try (Scanner scanner = new Scanner(Core.class.getResourceAsStream("hash.txt"))) {
76 8
            if (scanner.hasNext()) {
77 2
                hash = scanner.next();
78
            }
79
        }
80
    }    
81
82 4
    /**
83 4
     * Returns the next shuffled item from the named collection.
84
     *
85 4
     * @param String name
86 4
     * @return String
87 4
     */
88
    private String getNextShuffledItemFor(@NamedParameter("name") String name) {
89
        if (stringIters.containsKey(name)) {
90
            final Iterator<String> iter = stringIters.get(name);
91
            if (iter.hasNext()) {
92
                return iter.next();
93
            }
94
            // else shuffle again
95
        }
96
97
        final List<String> list = stringLists.get(name);
98
        Collections.shuffle(list);
99
100
        final Iterator<String> iter = list.iterator();
101 3
        stringIters.put(name, iter);
102 6
        return iter.next();
103 1
    }
104 1
105 1
    /**
106 2
     * Generates a list of random strings from a list of strings (new-
107 1
     * line separated) in a file.The function randomizes the collection, exhausting all possible values
108 2
     * before re-shuffling and re-using items.
109
110
     * @param id
111 1
     * @param supplier
112
     * @return A random string from the stream
113 3
     * @throws IOException
114
     */
115
    protected String randomStringFromStream(String id, InputStreamSupplier supplier) throws IOException {
116
        if (!stringLists.containsKey(id)) {
117
            log.info("Loading words from stream {}", id);
118
            final List<String> values = new ArrayList<>();
119
            InputStream stream = supplier.getInputStream();
120
            try (BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
121
                for (String line; (line = br.readLine()) != null; ) {
122
                    values.add(line);
123
                }
124
            }
125
            stringLists.put(id, values);
126
        }
127 4
        return getNextShuffledItemFor(id);
128 8
    }
129 2
130 2
    /**
131 4
     * Generates a list of random strings from a list of strings (new-
132 1
     * line separated) in a file.
133 2
     *
134
     * The function randomizes the collection, exhausting all possible values
135
     * before re-shuffling and re-using items.
136 1
     *
137
     * @param file the file name
138 3
     * @return A random string from the file
139
     * @throws java.io.IOException
140
     */
141
    public String randomStringFromFile(String file) throws IOException {
142
        if (!stringLists.containsKey(file)) {
143
            log.info("Loading words from file: {}", file);
144
            final List<String> values = new ArrayList<>();
145
            try (BufferedReader br = new BufferedReader(new FileReader(file))) {
146
                for (String line; (line = br.readLine()) != null; ) {
147
                    values.add(line);
148
                }
149
            }
150
            stringLists.put(file, values);
151 1
        }
152
        return getNextShuffledItemFor(file);
153
    }
154
155
    /**
156 1
     * Generates a random date between the passed start and end dates, and using
157 1
     * the passed format to parse the dates passed, and to format the return
158 1
     * value.
159 1
     *
160 1
     * @param start
161
     * @param end
162
     * @param format
163
     * @return
164
     */
165
    public String randomDate(
166
        @NamedParameter("start") String start,
167
        @NamedParameter("end") String end,
168
        @NamedParameter("format") String format
169
    ) {
170
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(format);
171
        LocalDate ds = LocalDate.parse(start, fmt);
172
        LocalDate de = LocalDate.parse(end, fmt);
173 1
        long day = RandomUtils.nextLong(0, de.toEpochDay() - ds.toEpochDay()) + ds.toEpochDay();
174
        return LocalDate.ofEpochDay(day).format(fmt);
175
    }
176
177
    /**
178 1
     * Generates a random date-time between the passed start and end dates, and
179 1
     * using the passed format to parse the dates passed, and to format the
180 1
     * return value.
181 1
     *
182 1
     * @param start
183
     * @param end
184
     * @param format
185
     * @return
186
     */
187
    public String randomDateTime(
188
        @NamedParameter("start") String start,
189
        @NamedParameter("end") String end,
190
        @NamedParameter("format") String format
191
    ) {
192
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(format);
193
        LocalDateTime ds = LocalDateTime.parse(start, fmt);
194 206
        LocalDateTime de = LocalDateTime.parse(end, fmt);
195 206
        long day = RandomUtils.nextLong(0, de.toEpochSecond(ZoneOffset.UTC) - ds.toEpochSecond(ZoneOffset.UTC)) + ds.toEpochSecond(ZoneOffset.UTC);
196 716
        return LocalDateTime.ofEpochSecond(day, 0, ZoneOffset.UTC).format(fmt);
197 304
    }
198 304
199
    /**
200 412
     * Generates a random string of 'num' words, with at most 'length'
201 68
     * characters (shortening the string if more characters appear in the
202
     * string).
203 138
     *
204
     * @param num The number of desired words
205
     * @param length The maximum length of the string
206
     * @return
207
     */
208
    public String randomString(@NamedParameter("num") int num, @NamedParameter("length") int length) {
209
        final StringBuilder randomString = new StringBuilder();
210
        for (int i = 0; i < num && randomString.length() < length; ++i) {
211
            final int r = RandomUtils.nextInt(0, words.size());
212 1
            randomString.append(words.get(r)).append(' ');
213 1
        }
214 1
        if (randomString.length() > length) {
215
            return randomString.toString().substring(0, length).trim();
216
        }
217
        return randomString.toString().trim();
218
    }
219
220
    /**
221
     * Generates a String from the passed regex that is guaranteed to match it.
222
     *
223
     * @param pattern
224
     * @return
225
     */
226
    public String randomStringFromPattern(@NamedParameter("pattern") String pattern) {
227
        final Xeger instance = new Xeger(pattern);
228
        return instance.generate();
229
    }
230
    
231
    public String getHash() {
232
        return hash;
233
    }
234
}
235