Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions lesson_09/types/types_app/DWREADME.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
Bulk Sample Generator

In addition to completing the above assignment, you are tasked with adding a flag to the app that will allow it to bulk generate sample files dynamically for each DataProvider implementation.

## How to Run the Bulk Generator

The app now supports a bulk generation mode that will automatically discover all DataProvider implementations and generate sample JSON files for each one.

### Command Usage

To run the bulk generator, use either of these command-line flags:

```bash
# Using the long flag
./gradlew bootRun --args="--bulk"

# Using the short flag
./gradlew bootRun --args="-b"
```

### What It Does

When you run the app with the `--bulk` or `-b` flag, it will:

1. **Discover all DataProvider implementations** - The app automatically finds all classes that extend `DataProvider` and are annotated with `@Service`
2. **Loop through each provider** - For each discovered provider (e.g., `AnthonyMaysProvider`, `DeanWalstonProvider`, etc.)
3. **Generate sample data** - Creates 10 rows of sample data based on each provider's column type specifications
4. **Save to JSON files** - Saves each provider's sample data to `{providerName}.json` in the `src/main/resources/data/` directory

### Example Output

If the app finds providers like `AnthonyMaysProvider` and `DeanWalstonProvider`, it will generate:
- `anthonymays.json` - Sample data based on AnthonyMaysProvider's column specifications
- `deanwalston.json` - Sample data based on DeanWalstonProvider's column specifications

### Sample Console Output

```
Bulk generating sample files for all DataProvider implementations...
Found 2 DataProvider implementations:
- Generating sample file for: anthonymays
Column specifications for anthonymays:
- column1: Integer
- column2: String
- column3: Boolean
- column4: Float
- column5: Double
- column6: Long
- column7: Short
✓ Generated: anthonymays.json
- Generating sample file for: deanwalston
Column specifications for deanwalston:
- column1: Long
- column2: Short
- column3: Double
- column4: Integer
- column5: Boolean
- column6: String
- column7: Float
✓ Generated: deanwalston.json
Bulk generation completed! Files saved to: /path/to/src/main/resources/data
```

### Regular Usage (Single Provider)

The app still supports generating files for individual providers:

```bash
./gradlew bootRun --args="deanwalston"
```
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.codedifferently.lesson9;

import com.codedifferently.lesson9.dataprovider.DataProvider;
import com.codedifferently.lesson9.generator.BulkSampleFileGenerator;
import com.codedifferently.lesson9.generator.SampleFileGenerator;
import java.io.File;
import java.nio.file.Paths;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
Expand All @@ -12,22 +16,34 @@
@SpringBootApplication(scanBasePackages = "com.codedifferently")
public class Lesson9 implements CommandLineRunner {

@Autowired private Collection<DataProvider> dataProviders;

public static void main(String[] args) {
var application = new SpringApplication(Lesson9.class);
application.run(args);
}

@Override
public void run(String... args) throws Exception {
if (args.length == 0) {
return;
}

String path = getDataPath();

// Check for bulk generation flag
if (args[0].equals("--bulk") || args[0].equals("-b")) {
System.out.println("Bulk generating sample files for all DataProvider implementations...");
var bulkGenerator = new BulkSampleFileGenerator();
bulkGenerator.createBulkTestFiles(path, dataProviders);
return;
}

var providerName = args[0];
if (providerName == null) {
throw new IllegalArgumentException("Provider name is required");
}

String path = getDataPath();
var fileGenerator = new SampleFileGenerator();
fileGenerator.createTestFile(path, providerName);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.codedifferently.lesson9.dataprovider;

import java.util.Map;
import org.springframework.stereotype.Service;

@Service
public class DeanWalstonProvider extends DataProvider {

public String getProviderName() {
return "deanwalston";
}

public Map<String, Class> getColumnTypeByName() {
return Map.of(
"column1", Long.class,
"column2", Short.class,
"column3", Double.class,
"column4", Integer.class,
"column5", Boolean.class,
"column6", String.class,
"column7", Float.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.codedifferently.lesson9.generator;

import com.codedifferently.lesson9.dataprovider.DataProvider;
import com.codedifferently.lesson9.generator.Generators.BooleanValueGenerator;
import com.codedifferently.lesson9.generator.Generators.DoubleValueGenerator;
import com.codedifferently.lesson9.generator.Generators.FloatValueGenerator;
import com.codedifferently.lesson9.generator.Generators.IntValueGenerator;
import com.codedifferently.lesson9.generator.Generators.LongValueGenerator;
import com.codedifferently.lesson9.generator.Generators.ShortValueGenerator;
import com.codedifferently.lesson9.generator.Generators.StringValueGenerator;
import com.google.gson.GsonBuilder;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/** A class to bulk generate sample files with random data for all DataProvider implementations. */
public class BulkSampleFileGenerator {

private static final Map<Class<?>, ValueGenerator> GENERATOR_BY_TYPE =
Map.of(
Integer.class, new IntValueGenerator(),
String.class, new StringValueGenerator(),
Double.class, new DoubleValueGenerator(),
Short.class, new ShortValueGenerator(),
Long.class, new LongValueGenerator(),
Float.class, new FloatValueGenerator(),
Boolean.class, new BooleanValueGenerator());

/**
* Create test files with sample data for all provided DataProvider implementations.
*
* @param path the path to the directory where the files will be created
* @param dataProviders the collection of all DataProvider implementations
*/
public void createBulkTestFiles(String path, Collection<DataProvider> dataProviders) {
System.out.println("Found " + dataProviders.size() + " DataProvider implementations:");

for (DataProvider provider : dataProviders) {
System.out.println("- Generating sample file for: " + provider.getProviderName());
createTestFileForProvider(path, provider);
}

System.out.println("Bulk generation completed! Files saved to: " + path);
}

/**
* Create a test file with sample data for a specific DataProvider.
*
* @param path the path to the directory where the file will be created
* @param provider the DataProvider implementation
*/
private void createTestFileForProvider(String path, DataProvider provider) {
Map<String, Class> columnTypeByName = provider.getColumnTypeByName();

System.out.println(" Column specifications for " + provider.getProviderName() + ":");
columnTypeByName.forEach(
(column, type) -> System.out.println(" - " + column + ": " + type.getSimpleName()));

ArrayList<Map<String, String>> rows = createSampleDataForProvider(columnTypeByName);
saveToJsonFile(path, provider.getProviderName(), rows);
}

/**
* Create sample data rows based on the column type mapping from a DataProvider.
*
* @param columnTypeByName mapping of column names to their Java types
* @return list of sample data rows
*/
private ArrayList<Map<String, String>> createSampleDataForProvider(
Map<String, Class> columnTypeByName) {
var rows = new ArrayList<Map<String, String>>();
for (var i = 0; i < 10; ++i) {
Map<String, String> row = createRowForProvider(columnTypeByName);
rows.add(row);
}
return rows;
}

/**
* Create a single row of sample data based on column type mapping.
*
* @param columnTypeByName mapping of column names to their Java types
* @return a single sample data row
*/
private Map<String, String> createRowForProvider(Map<String, Class> columnTypeByName) {
var row = new LinkedHashMap<String, String>();
for (Map.Entry<String, Class> entry : columnTypeByName.entrySet()) {
String columnName = entry.getKey();
Class<?> columnType = entry.getValue();

ValueGenerator generator = GENERATOR_BY_TYPE.get(columnType);
if (generator != null) {
row.put(columnName, generator.generateValue());
} else {
System.err.println(
"Warning: No generator found for type "
+ columnType.getName()
+ " in column "
+ columnName
+ ". Using default string value.");
row.put(columnName, "unknown_type_" + columnType.getSimpleName());
}
}
return row;
}

/**
* Save the sample data to a JSON file.
*
* @param path the directory path
* @param providerName the name of the provider (used as filename)
* @param rows the sample data rows
*/
private void saveToJsonFile(
String path, String providerName, ArrayList<Map<String, String>> rows) {
var file = new File(path + File.separator + providerName + ".json");
file.getParentFile().mkdirs();
var gson = new GsonBuilder().setPrettyPrinting().create();
try (var writer = new FileWriter(file, false)) {
writer.write(gson.toJson(rows));
System.out.println(" ✓ Generated: " + file.getName());
} catch (IOException e) {
System.err.println(" ✗ Failed to generate file for " + providerName + ": " + e.getMessage());
}
}
}
92 changes: 92 additions & 0 deletions lesson_09/types/types_app/src/main/resources/data/deanwalston.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
[
{
"column4": "389971082",
"column5": "false",
"column6": "nshdc",
"column7": "6.135183E36",
"column1": "3383887488801300480",
"column2": "1566",
"column3": "2.815708965672392E307"
},
{
"column4": "375126042",
"column5": "true",
"column6": "yxpo0",
"column7": "3.3008857E38",
"column1": "4982624173995602944",
"column2": "27838",
"column3": "1.6758536573713958E308"
},
{
"column4": "574661113",
"column5": "false",
"column6": "atg4b7f",
"column7": "1.9907885E38",
"column1": "2889725125587536384",
"column2": "797",
"column3": "8.985254883099615E307"
},
{
"column4": "1983492216",
"column5": "false",
"column6": "gpchwf3skxmq",
"column7": "2.2199312E38",
"column1": "3642242784260707328",
"column2": "26373",
"column3": "4.832903782287359E307"
},
{
"column4": "683979250",
"column5": "false",
"column6": "3aw7tn",
"column7": "8.124872E37",
"column1": "2380753608752845312",
"column2": "20936",
"column3": "6.508463623033705E307"
},
{
"column4": "1029159949",
"column5": "false",
"column6": "tpul1yg",
"column7": "1.5425769E37",
"column1": "8093440394763274240",
"column2": "4228",
"column3": "3.5232401779434665E306"
},
{
"column4": "201841596",
"column5": "true",
"column6": "xhtopi2n9",
"column7": "2.654272E37",
"column1": "5247748052229204992",
"column2": "30751",
"column3": "8.465599922833556E307"
},
{
"column4": "941802560",
"column5": "false",
"column6": "ui6d7zhvl5",
"column7": "3.3986773E38",
"column1": "7733210581626198016",
"column2": "20785",
"column3": "1.6842403765767673E308"
},
{
"column4": "699391538",
"column5": "false",
"column6": "wtvdghcs23b",
"column7": "1.8785126E38",
"column1": "5024689015537510400",
"column2": "29837",
"column3": "1.5566962567613336E308"
},
{
"column4": "1585384699",
"column5": "false",
"column6": "nqbjfw9mdt0",
"column7": "1.855844E38",
"column1": "7907910887862272000",
"column2": "21227",
"column3": "1.3471632227822855E307"
}
]