Skip to content

Commit 88db22a

Browse files
committed
DevynBenson lesson_09 submission
1 parent 1c86afb commit 88db22a

File tree

5 files changed

+385
-1
lines changed

5 files changed

+385
-1
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Types App - Data Types Exercise
2+
3+
This application demonstrates data type identification and sample data generation for Lesson 09.
4+
5+
## Overview
6+
7+
The Types App provides two main functionalities:
8+
1. Generate sample data files for individual providers
9+
2. Bulk generate sample data files for all registered `DataProvider` implementations
10+
11+
## Prerequisites
12+
13+
- Java 17 or higher
14+
- Gradle (included via Gradle Wrapper)
15+
16+
## Running the Application
17+
18+
### Standard Mode - Single Provider
19+
20+
Generate a sample data file for a specific provider:
21+
22+
```bash
23+
cd lesson_09/types
24+
./gradlew bootRun --args="yourprovidername"
25+
```
26+
27+
This will create a JSON file in `src/main/resources/data/yourprovidername.json` with 10 rows of sample data.
28+
29+
**Example:**
30+
```bash
31+
./gradlew bootRun --args="devynbenson"
32+
```
33+
34+
### Stretch Assignment - Bulk Generator Mode
35+
36+
Generate sample data files for **all** registered `DataProvider` implementations:
37+
38+
```bash
39+
cd lesson_09/types
40+
./gradlew bootRun --args="-bulk"
41+
```
42+
43+
This bulk mode will:
44+
- Automatically discover all registered `DataProvider` implementations
45+
- Generate a unique JSON file for each provider
46+
- Create files in `src/main/resources/data/` directory
47+
- Each file contains 10 rows of sample data with appropriate data types
48+
49+
**What happens in bulk mode:**
50+
1. The app scans for all `DataProvider` beans registered in the Spring context
51+
2. For each provider, it generates sample data based on the provider's column type definitions
52+
3. Creates individual JSON files named after each provider (e.g., `devynbenson.json`, `anthonymays.json`, etc.)
53+
54+
## Output Format
55+
56+
Generated files are in JSON format with the following structure:
57+
58+
```json
59+
[
60+
{
61+
"column1": "sample_value_1",
62+
"column2": "sample_value_2",
63+
"column3": "sample_value_3",
64+
...
65+
},
66+
// ... 9 more rows
67+
]
68+
```
69+
70+
## Data Types Supported
71+
72+
The bulk generator supports the following Java data types:
73+
- `Integer` - Whole numbers
74+
- `Double` - Decimal numbers
75+
- `String` - Text values
76+
- `Boolean` - True/false values
77+
- `Short` - Small integers
78+
- `Long` - Large integers
79+
- `Float` - Single-precision decimals
80+
81+
## Implementation Details
82+
83+
### Bulk Generator Class
84+
85+
The bulk functionality is implemented in `DevynBensonBulkGenerator.java`, which:
86+
- Uses Spring's dependency injection to access all `DataProvider` beans
87+
- Maps each provider's column types to appropriate value generators
88+
- Generates realistic sample data for each column type
89+
- Outputs properly formatted JSON files
90+
91+
### Usage in Main Application
92+
93+
The main `Lesson9.java` class detects the `-bulk` flag and switches to bulk generation mode:
94+
95+
```java
96+
if("-bulk".equals(providerName)) {
97+
var path = getDataPath();
98+
var fileGenerator = new DevynBensonBulkGenerator();
99+
fileGenerator.createTestFileForEveryProvider(path, dataProviders);
100+
return;
101+
}
102+
```
103+
104+
## Testing and Validation
105+
106+
After running the application, validate your implementation:
107+
108+
```bash
109+
# Format code
110+
./gradlew spotlessApply
111+
112+
# Run tests
113+
./gradlew check
114+
```
115+
116+
## File Locations
117+
118+
- **Generated Data Files:** `src/main/resources/data/`
119+
- **DataProvider Implementations:** `src/main/java/com/codedifferently/lesson9/dataprovider/`
120+
- **Bulk Generator:** `src/main/java/com/codedifferently/lesson9/generator/DevynBensonBulkGenerator.java`
121+
122+
## Example Workflow
123+
124+
1. Create your `DataProvider` implementation
125+
2. Run bulk generator to see sample data for all providers:
126+
```bash
127+
./gradlew bootRun --args="-bulk"
128+
```
129+
3. Examine the generated JSON file for your provider
130+
4. Verify the data types match your expectations
131+
5. Run tests to validate implementation

lesson_09/types/types_app/src/main/java/com/codedifferently/lesson9/Lesson9.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
package com.codedifferently.lesson9;
2-
32
import com.codedifferently.lesson9.generator.SampleFileGenerator;
3+
import com.codedifferently.lesson9.generator.DevynBensonBulkGenerator;
44
import java.io.File;
55
import java.nio.file.Paths;
66
import org.springframework.boot.CommandLineRunner;
77
import org.springframework.boot.SpringApplication;
88
import org.springframework.boot.autoconfigure.SpringBootApplication;
99
import org.springframework.context.annotation.Configuration;
10+
import org.springframework.beans.factory.annotation.Autowired;
1011

1112
@Configuration
1213
@SpringBootApplication(scanBasePackages = "com.codedifferently")
1314
public class Lesson9 implements CommandLineRunner {
1415

16+
@Autowired
17+
private List<DataProvider> dataProviders;
1518
public static void main(String[] args) {
1619
var application = new SpringApplication(Lesson9.class);
1720
application.run(args);
@@ -27,6 +30,13 @@ public void run(String... args) throws Exception {
2730
throw new IllegalArgumentException("Provider name is required");
2831
}
2932

33+
if("-bulk".equals(providerName)) {
34+
var path = getDataPath();
35+
var fileGenerator = new DevynBensonBulkGenerator();
36+
fileGenerator.createTestFileForEveryProvider(path, dataProviders);
37+
return;
38+
}
39+
3040
String path = getDataPath();
3141
var fileGenerator = new SampleFileGenerator();
3242
fileGenerator.createTestFile(path, providerName);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.codedifferently.lesson9.dataprovider;
2+
3+
import java.util.Map;
4+
import org.springframework.stereotype.Service;
5+
6+
@Service
7+
public class DevynBensonProvider extends DataProvider {
8+
public String getProviderName() {
9+
return "devynbenson";
10+
}
11+
12+
public Map<String, Class> getColumnTypeByName() {
13+
return Map.of(
14+
"column1", Boolean.class, // true/false values
15+
"column2", Float.class, // Scientific notation floats like 1.3605703E38
16+
"column3", String.class, // Text strings like "vqjy6zgi32lr"
17+
"column4", Long.class, // Very large integers like 649023162885324032
18+
"column5", Short.class, // Small integers like 4581 (fits in Short range)
19+
"column6", Integer.class, // Medium integers like 383252171
20+
"column7", Double.class); // Very large scientific notation like 1.7759E307
21+
}
22+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
2+
package com.codedifferently.lesson9.generator;
3+
4+
import com.codedifferently.lesson9.dataprovider.DataProvider;
5+
import java.util.List;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import com.codedifferently.lesson9.generator.Generators.*;
8+
import com.google.gson.GsonBuilder;
9+
import java.io.File;
10+
import java.io.FileWriter;
11+
import java.io.IOException;
12+
import java.util.ArrayList;
13+
import java.util.Arrays;
14+
import java.util.Collections;
15+
import java.util.LinkedHashMap;
16+
import java.util.List;
17+
import java.util.Map;
18+
19+
/** A class to generate a sample file with random data. */
20+
public class DevynBensonBulkGenerator {
21+
22+
@Autowired
23+
private List<DataProvider> dataProviders;
24+
25+
private static final ValueGenerator[] GENERATORS = {
26+
new IntValueGenerator(),
27+
new StringValueGenerator(),
28+
new DoubleValueGenerator(),
29+
new ShortValueGenerator(),
30+
new LongValueGenerator(),
31+
new FloatValueGenerator(),
32+
new BooleanValueGenerator()
33+
};
34+
35+
/**
36+
* Create a test file with sample data.
37+
*
38+
* @param path the path to the directory where the file will be created
39+
* @param providerName the name of the provider
40+
*/
41+
public void createTestFileForEveryProvider(String path, List<DataProvider> dataProviders) {
42+
43+
for (var dataProvider : dataProviders) {
44+
var generators = getShuffledGenerators();
45+
ArrayList<Map<String, String>> rows = createSampleData(generators);
46+
saveToJsonFile(path, dataProvider.getProviderName(), rows);
47+
}
48+
}
49+
// Mapping of classes to value generators
50+
private static final Map<Class<?>, ValueGenerator> TYPE_TO_GENERATOR =
51+
Map.of(
52+
Integer.class, new IntValueGenerator(),
53+
Short.class, new ShortValueGenerator(),
54+
Long.class, new LongValueGenerator(),
55+
Float.class, new FloatValueGenerator(),
56+
Boolean.class, new BooleanValueGenerator(),
57+
String.class, new StringValueGenerator(),
58+
Double.class, new DoubleValueGenerator());
59+
60+
/**
61+
* Creates a JSON provider file with generated sample data.
62+
*
63+
* @param path the file path where the provider file will be written
64+
* @param providerName the name of the provider
65+
* @param provider the {DataProvider} that defines columns
66+
* @throws IllegalArgumentException if no generator is found for a column type
67+
*/
68+
public void createProviderFile(String path, String providerName, DataProvider provider) {
69+
var generators = getGenerators(provider);
70+
ArrayList<Map<String, String>> rows = createSampleData(generators);
71+
72+
// Writes the generated rows to a JSON file.
73+
saveToJsonFile(path, providerName, rows);
74+
}
75+
private List<ValueGenerator> getGenerators(DataProvider provider) {
76+
Map<String, Class> columnTypes = provider.getColumnTypeByName();
77+
ArrayList<ValueGenerator> generators = new ArrayList<>();
78+
79+
for (int i = 1; i <= columnTypes.size(); i++) {
80+
String column = "column" + i;
81+
Class<?> type = columnTypes.get(column);
82+
83+
// Look up the appropriate generator for this column type.
84+
ValueGenerator generator = TYPE_TO_GENERATOR.get(type);
85+
if (generator == null) {
86+
throw new IllegalArgumentException("No generator found for type: " + type);
87+
}
88+
generators.add(generator);
89+
}
90+
91+
return generators;
92+
}
93+
94+
private List<ValueGenerator> getdGenerators(DataProvider provider) {
95+
var generators = Arrays.asList(GENERATORS);
96+
Collections.shuffle(generators);
97+
return generators;
98+
}
99+
100+
private ArrayList<Map<String, String>> createSampleData(List<ValueGenerator> generators) {
101+
var rows = new ArrayList<Map<String, String>>();
102+
for (var i = 0; i < 10; ++i) {
103+
Map<String, String> row = createRow(generators);
104+
rows.add(createRow(generators));
105+
}
106+
return rows;
107+
}
108+
109+
private Map<String, String> createRow(List<ValueGenerator> generators) {
110+
var row = new LinkedHashMap<String, String>();
111+
for (int i = 0; i < GENERATORS.length; ++i) {
112+
var columnIndex = i + 1;
113+
row.put("column" + columnIndex, GENERATORS[i].generateValue());
114+
}
115+
return row;
116+
}
117+
118+
private void saveToJsonFile(
119+
String path, String providerName, ArrayList<Map<String, String>> rows) {
120+
var file = new File(path + File.separator + providerName + ".json");
121+
file.getParentFile().mkdirs();
122+
var gson = new GsonBuilder().setPrettyPrinting().create();
123+
try (var writer = new FileWriter(file, false)) {
124+
writer.write(gson.toJson(rows));
125+
} catch (IOException e) {
126+
e.printStackTrace();
127+
}
128+
}
129+
}

0 commit comments

Comments
 (0)