Skip to content

Commit

Permalink
Merge branch 'main' into StateMachine
Browse files Browse the repository at this point in the history
  • Loading branch information
avidraccoon authored Dec 16, 2024
2 parents 51d391e + ddc04e0 commit b691820
Show file tree
Hide file tree
Showing 23 changed files with 659 additions and 132 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=2024.11.29-beta
version=2025.0.0-beta
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Annotation to exclude fields from being serialized or deserialized in JSON.
*
* <p>When applied to a field, the field will be ignored during both the serialization and
* deserialization processes. Useful for marking fields that should not be part of the JSON
* representation.
*
* <p>Usage example:
*
* <pre>{@code
* public class Example {
* private String includedField;
*
* @JSONExclude
* private String excludedField;
* }
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JSONExclude {}
159 changes: 135 additions & 24 deletions parameter_tools/src/main/java/coppercore/parameter_tools/JSONSync.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,90 @@
package coppercore.parameter_tools;

import com.google.gson.*;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.LongSerializationPolicy;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
* A utility class for synchronizing Java objects with JSON files. Provides functionality for
* loading and saving data to a JSON file using the Gson library.
*/
public class JSONSync<T> {

private final Gson gson;

private T instance;

private String file;

private final JSONSyncConfig config;
private final Gson gson; // Gson instance for serialization and deserialization
private T instance; // The object being synchronized
private String file; // File path for the JSON file
private final JSONSyncConfig config; // Configuration for Gson

/**
* Retrieves the object synchronized with the JSON file.
*
* @return The synchronized object.
*/
public T getObject() {
return instance;
}

private FileReader getFileReader(String path) {
try {
return new FileReader(path);
} catch (FileNotFoundException e) {
throw new RuntimeException("File not found " + path, e);
}
}

/**
* Loads the data from the JSON file into the object.
*
* @throws RuntimeException if the JSON file cannot be read or parsed.
*/
@SuppressWarnings("unchecked")
public void loadData() {
instance = gson.fromJson(getFileReader(file), (Class<T>) instance.getClass());
}

/**
* Saves the current state of the object to the JSON file.
*
* @throws RuntimeException if the JSON file cannot be written.
*/
public void saveData() {
String json = gson.toJson(instance);
FileWriter writer = getFileWriter(file);
try {
writer.write(json);
writer.close();
} catch (IOException e) {
throw new RuntimeException("IOException", e);
}
}

/**
* Sets the file path for the JSON file.
*
* @param newFilePath The new file path for the JSON file.
*/
public void setFile(String newFilePath) {
file = newFilePath;
}

/**
* Constructs a new JSONSync instance.
*
* @param instance The object to synchronize with the JSON file.
* @param file The file path for the JSON file.
* @param config Configuration for the Gson instance; uses defaults if null.
*/
public JSONSync(T instance, String file, JSONSyncConfig config) {
this.instance = instance;
this.config = (config == null) ? new JSONSyncConfigBuilder().build() : config;
this.gson = generateGson();
this.file = file;
}

/**
* Generates a Gson instance with the current configuration.
*
* @return A configured Gson instance.
*/
private Gson generateGson() {
ExclusionStrategy strategy =
new ExclusionStrategy() {
Expand All @@ -54,19 +104,44 @@ public boolean shouldSkipClass(Class<?> clazz) {
if (this.config.prettyPrinting) builder.setPrettyPrinting();
if (this.config.excludeFieldsWithoutExposeAnnotation)
builder.excludeFieldsWithoutExposeAnnotation();
builder.setFieldNamingPolicy(this.config.namingPolicy);
builder.setLongSerializationPolicy(this.config.longSerializationPolicy);
builder.addDeserializationExclusionStrategy(strategy);
builder.setFieldNamingPolicy(this.config.namingPolicy)
.setLongSerializationPolicy(this.config.longSerializationPolicy)
.addDeserializationExclusionStrategy(strategy)
.addSerializationExclusionStrategy(strategy);
return builder.create();
}

public JSONSync(T instance, String file, JSONSyncConfig config) {
this.instance = instance;
this.config = (config == null) ? new JSONSyncConfigBuilder().build() : config;
this.gson = generateGson();
this.file = file;
/**
* Provides a FileReader for the given file path.
*
* @param path The file path.
* @return A FileReader for the specified file.
* @throws RuntimeException if the file cannot be found.
*/
private FileReader getFileReader(String path) {
try {
return new FileReader(path);
} catch (FileNotFoundException e) {
throw new RuntimeException("File not found " + path, e);
}
}

/**
* Provides a FileWriter for the given file path.
*
* @param path The file path.
* @return A FileWriter for the specified file.
* @throws RuntimeException if the file cannot be created or written to.
*/
private FileWriter getFileWriter(String path) {
try {
return new FileWriter(path);
} catch (IOException e) {
throw new RuntimeException("IOException " + path, e);
}
}

/** Configuration class for customizing Gson behavior. */
private static record JSONSyncConfig(
boolean serializeNulls,
boolean prettyPrinting,
Expand All @@ -83,40 +158,76 @@ public JSONSyncConfig(JSONSyncConfigBuilder builder) {
}
}

/** Builder class for creating a JSONSyncConfig instance. */
public static class JSONSyncConfigBuilder {
public boolean serializeNulls = false;
public boolean prettyPrinting = false;
public boolean excludeFieldsWithoutExposeAnnotation = false;
public FieldNamingPolicy namingPolicy = FieldNamingPolicy.IDENTITY;
public LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT;

/**
* Sets whether null fields should be serialized.
*
* @param serializeNulls True to serialize null fields, false otherwise.
* @return The builder instance.
*/
public JSONSyncConfigBuilder setSerializeNulls(boolean serializeNulls) {
this.serializeNulls = serializeNulls;
return this;
}

/**
* Sets whether the JSON output should use pretty printing.
*
* @param prettyPrinting True to enable pretty printing, false otherwise.
* @return The builder instance.
*/
public JSONSyncConfigBuilder setPrettyPrinting(boolean prettyPrinting) {
this.prettyPrinting = prettyPrinting;
return this;
}

/**
* Sets whether fields without @Expose annotations should be excluded.
*
* @param excludeFieldsWithoutExposeAnnotation True to exclude fields, false otherwise.
* @return The builder instance.
*/
public JSONSyncConfigBuilder setExcludeFieldsWithoutExposeAnnotation(
boolean excludeFieldsWithoutExposeAnnotation) {
this.excludeFieldsWithoutExposeAnnotation = excludeFieldsWithoutExposeAnnotation;
return this;
}

/**
* Sets the naming policy for fields in the JSON output.
*
* @param namingPolicy The field naming policy.
* @return The builder instance.
*/
public JSONSyncConfigBuilder setNamingPolicy(FieldNamingPolicy namingPolicy) {
this.namingPolicy = namingPolicy;
return this;
}

/**
* Sets the serialization policy for long values.
*
* @param longSerializationPolicy The serialization policy for long values.
* @return The builder instance.
*/
public JSONSyncConfigBuilder setLongSerializationPolicy(
LongSerializationPolicy longSerializationPolicy) {
this.longSerializationPolicy = longSerializationPolicy;
return this;
}

/**
* Builds the configuration object.
*
* @return A JSONSyncConfig instance.
*/
public JSONSyncConfig build() {
return new JSONSyncConfig(this);
}
Expand Down
37 changes: 33 additions & 4 deletions parameter_tools/src/test/java/ExampleJsonSyncClass.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,54 @@
package coppercore.paremeter_tools.test;
package coppercore.parameter_tools.test;

import coppercore.parameter_tools.JSONSync;
import coppercore.parameter_tools.JSONExclude;

/**
* Example class to demonstrate the usage of the {@link JSONSync} utility for saving and loading
* data in JSON format.
*
* <p>This class showcases how fields can be serialized and deserialized, including nested objects,
* using the {@link JSONSync} functionality.
*
* <p>Key features:
*
* <ul>
* <li>Defines several fields of various types to demonstrate JSON serialization.
* <li>Includes a nested class {@code BasicMotorDataHolder} to demonstrate handling nested data
* structures.
* <li>Utilizes {@link JSONSync} to manage serialization and deserialization with the associated
* JSON file.
* </ul>
*/
public class ExampleJsonSyncClass {

/**
* Static {@link JSONSync} instance for managing the serialization and deserialization of this
* class.
*/
public static JSONSync<ExampleJsonSyncClass> synced =
new JSONSync<ExampleJsonSyncClass>(
new JSONSync<>(
new ExampleJsonSyncClass(),
"filePath",
new JSONSync.JSONSyncConfigBuilder().build());

public final String testText = "";

public final Double testDouble = 0.0;
public final Integer testInt = 0;

public Integer testInt = 0;

public final BasicMotorDataHolder motorData = null;

/** Nested class to represent motor-related data. */
public class BasicMotorDataHolder {

public final Double maxVoltage = 0.0;

public final Double minVoltage = 0.0;

public Double currentVoltage = 0.0;

@Override
public String toString() {
return "minVoltage: "
+ minVoltage
Expand All @@ -31,6 +59,7 @@ public String toString() {
}
}

@Override
public String toString() {
return "testText: "
+ testText
Expand Down
Loading

0 comments on commit b691820

Please sign in to comment.