summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java/bjc/utils/components
diff options
context:
space:
mode:
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/components')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescription.java13
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionFileParser.java60
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java4
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java127
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java19
5 files changed, 108 insertions, 115 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescription.java b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescription.java
index 9429dde..ab48c9b 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescription.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescription.java
@@ -10,19 +10,19 @@ public class ComponentDescription implements IDescribedComponent {
private static void sanityCheckArgs(String name, String author,
String description, int version) {
if (name == null) {
- throw new IllegalArgumentException(
- "Component name can't be null");
+ throw new NullPointerException("Component name can't be null");
} else if (author == null) {
- throw new IllegalArgumentException(
+ throw new NullPointerException(
"Component author can't be null");
} else if (description == null) {
- throw new IllegalArgumentException(
+ throw new NullPointerException(
"Component description can't be null");
- } else if (version < 0) {
+ } else if (version <= 0) {
throw new IllegalArgumentException(
"Component version must be greater than 0");
}
}
+
/**
* The author of the component
*/
@@ -53,8 +53,7 @@ public class ComponentDescription implements IDescribedComponent {
* @param version
* The version of the component
* @throws IllegalArgumentException
- * thrown if name, author or description is null, or if
- * version is less than 1
+ * thrown if version is less than 1
*/
public ComponentDescription(String name, String author,
String description, int version) {
diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionFileParser.java b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionFileParser.java
index be0a65b..b35c77b 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionFileParser.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionFileParser.java
@@ -1,13 +1,11 @@
package bjc.utils.components;
import java.io.InputStream;
-import java.util.function.BiConsumer;
-import bjc.utils.exceptions.PragmaFormatException;
-import bjc.utils.funcdata.FunctionalStringTokenizer;
-import bjc.utils.funcutils.ListUtils;
import bjc.utils.parserutils.RuleBasedConfigReader;
+import static bjc.utils.parserutils.RuleBasedReaderPragmas.*;
+
/**
* Read a component description from a file
*
@@ -15,8 +13,10 @@ import bjc.utils.parserutils.RuleBasedConfigReader;
*
*/
public class ComponentDescriptionFileParser {
+ // The reader used to read in component descriptions
private static RuleBasedConfigReader<ComponentDescriptionState> reader;
+ // Initialize the reader and its pragmas
static {
// This reader works entirely off of pragmas, so no need to handle
// rules
@@ -31,19 +31,6 @@ public class ComponentDescriptionFileParser {
setupReaderPragmas();
}
- private static BiConsumer<FunctionalStringTokenizer, ComponentDescriptionState> buildStringCollapserPragma(
- String pragmaName) {
- return (tokenizer, state) -> {
- if (!tokenizer.hasMoreTokens()) {
- throw new PragmaFormatException("Pragma " + pragmaName
- + " requires one string argument");
- }
-
- state.setName(ListUtils
- .collapseTokens(tokenizer.toList((strang) -> strang)));
- };
- }
-
/**
* Parse a component description from a stream
*
@@ -51,42 +38,29 @@ public class ComponentDescriptionFileParser {
* The stream to parse from
* @return The description parsed from the stream
*/
- public static ComponentDescription fromStream(
- InputStream inputSource) {
+ public static ComponentDescription
+ fromStream(InputStream inputSource) {
ComponentDescriptionState readState = reader
.fromStream(inputSource, new ComponentDescriptionState());
return readState.toDescription();
}
+ /*
+ * Create all the pragmas the reader needs to function
+ */
private static void setupReaderPragmas() {
- reader.addPragma("name", buildStringCollapserPragma("name"));
+ reader.addPragma("name", buildStringCollapser("name",
+ (name, state) -> state.setName(name)));
- reader.addPragma("author", buildStringCollapserPragma("author"));
+ reader.addPragma("author", buildStringCollapser("author",
+ (author, state) -> state.setAuthor(author)));
reader.addPragma("description",
- buildStringCollapserPragma("description"));
+ buildStringCollapser("description", (description,
+ state) -> state.setDescription(description)));
- reader.addPragma("version", (tokenizer, state) -> {
- if (!tokenizer.hasMoreTokens()) {
- throw new PragmaFormatException(
- "Pragma version requires one integer argument");
- }
-
- String token = tokenizer.nextToken();
-
- try {
- state.setVersion(Integer.parseInt(token));
- } catch (NumberFormatException nfex) {
- PragmaFormatException pfex = new PragmaFormatException(
- "Argument " + token
- + " to version pragma isn't a valid integer. "
- + "This pragma requires a integer argument");
-
- pfex.initCause(nfex);
-
- throw pfex;
- }
- });
+ reader.addPragma("version", buildInteger("version",
+ (version, state) -> state.setVersion(version)));
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java
index 199009c..a17a70b 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java
@@ -7,12 +7,16 @@ package bjc.utils.components;
*
*/
public class ComponentDescriptionState {
+ // Tentative name of this component
private String name;
+ // Tentative description of this componet
private String description;
+ // Tentative author of this component
private String author;
+ // Tentative version of this component
private int version;
/**
diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java b/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java
index e05afc0..182549c 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java
@@ -6,42 +6,36 @@ import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.function.BiPredicate;
import java.util.function.Function;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import bjc.utils.data.IHolder;
import bjc.utils.data.Identity;
-import bjc.utils.funcdata.FunctionalList;
import bjc.utils.funcdata.FunctionalMap;
-import bjc.utils.funcdata.IFunctionalList;
-import bjc.utils.funcdata.IFunctionalMap;
+import bjc.utils.funcdata.IList;
+import bjc.utils.funcdata.IMap;
import bjc.utils.funcutils.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* A component repository that loads its components from files in a
* directory
*
* @author ben
*
- * @param <E>
+ * @param <ComponentType>
* The type of component being read in
*/
-public class FileComponentRepository<E extends IDescribedComponent>
- implements IComponentRepository<E> {
+public class FileComponentRepository<ComponentType extends IDescribedComponent>
+ implements IComponentRepository<ComponentType> {
+ // The logger to use for storing data about this class
+ private static final Logger CLASS_LOGGER =
+ Logger.getLogger("FileComponentRepository");
- private static final Logger CLASS_LOGGER = LoggerFactory
- .getLogger(FileComponentRepository.class);
+ // The internal storage of components
+ private IMap<String, ComponentType> components;
- /**
- * The internal storage of components
- */
- private IFunctionalMap<String, E> components;
-
- /**
- * The path that all the components came from
- */
- private Path sourceDirectory;
+ // The path that all the components came from
+ private Path sourceDirectory;
/**
* Create a new component repository sourcing components from files in
@@ -57,33 +51,47 @@ public class FileComponentRepository<E extends IDescribedComponent>
* The function to use to convert files to components
*/
public FileComponentRepository(File directory,
- Function<File, ? extends E> componentReader) {
+ Function<File, ? extends ComponentType> componentReader) {
+ // Make sure we have valid arguments
if (!directory.isDirectory()) {
throw new IllegalArgumentException("File " + directory
+ " is not a directory.\n"
+ "Components can only be read from a directory");
+ } else if (componentReader == null) {
+ throw new NullPointerException(
+ "Component reader must not be null");
}
+ // Initialize our fields
components = new FunctionalMap<>();
-
sourceDirectory = directory.toPath().toAbsolutePath();
+ // Marker for making sure we don't skip the parent
IHolder<Boolean> isFirstDir = new Identity<>(true);
- BiPredicate<Path, BasicFileAttributes> firstLevelTraverser = (pth,
- attr) -> {
- if (attr.isDirectory() && !isFirstDir.getValue()) {
- // Don't skip the first directory, that's the
- // parent
- isFirstDir.replace(false);
- // Skip directories, they probably have
- // component
- return false;
- }
-
- return true;
- };
-
+ // Predicate to use to traverse all the files in a directory, but
+ // not recurse into sub-directories
+ BiPredicate<Path, BasicFileAttributes> firstLevelTraverser =
+ (pth, attr) -> {
+ if (attr.isDirectory() && !isFirstDir.getValue()) {
+
+ /*
+ * Skip directories, they probably have component
+ * support files.
+ */
+ return false;
+ }
+
+ /*
+ * Don't skip the first directory, that's the parent
+ * directory
+ */
+ isFirstDir.replace(false);
+
+ return true;
+ };
+
+ // Try reading components
try {
FileUtils.traverseDirectory(sourceDirectory,
firstLevelTraverser, (pth, attr) -> {
@@ -93,28 +101,23 @@ public class FileComponentRepository<E extends IDescribedComponent>
return true;
});
} catch (IOException ioex) {
- CLASS_LOGGER.warn("Error found reading component from file.",
- ioex);
+ CLASS_LOGGER.log(Level.WARNING, ioex,
+ () -> "Error found reading component from file.");
}
}
@Override
- public E getComponentByName(String name) {
+ public ComponentType getByName(String name) {
return components.get(name);
}
@Override
- public IFunctionalList<E> getComponentList() {
- IFunctionalList<E> returnedList = new FunctionalList<>();
-
- components
- .forEach((name, component) -> returnedList.add(component));
-
- return returnedList;
+ public IList<ComponentType> getList() {
+ return components.valueList();
}
@Override
- public IFunctionalMap<String, E> getComponents() {
+ public IMap<String, ComponentType> getAll() {
return components;
}
@@ -123,26 +126,38 @@ public class FileComponentRepository<E extends IDescribedComponent>
return "Components read from directory " + sourceDirectory + ".";
}
- private void loadComponent(Function<File, ? extends E> componentReader,
+ /*
+ * Load a component from a file
+ */
+ private void loadComponent(
+ Function<File, ? extends ComponentType> componentReader,
Path pth) {
try {
- E component = componentReader.apply(pth.toFile());
+ // Try to load the component
+ ComponentType component = componentReader.apply(pth.toFile());
if (component == null) {
throw new NullPointerException(
"Component reader read null component");
} else if (!components.containsKey(component.getName())) {
- components.put(component.getName(), component);
+ // We only care about the latest version of a component
+ ComponentType oldComponent =
+ components.put(component.getName(), component);
+
+ if (oldComponent.getVersion() > component.getVersion()) {
+ components.put(oldComponent.getName(), oldComponent);
+ }
} else {
- CLASS_LOGGER.warn("Found a duplicate component.\n"
+ CLASS_LOGGER.warning("Found a duplicate component.\n"
+ "Multiple versions of the same component are not currently supported.\n"
- + "The component" + component
- + " will not be registered .");
+ + "Only the latest version of the component"
+ + component + " will be registered .");
}
} catch (Exception ex) {
- CLASS_LOGGER.warn("Error found reading component from file "
- + pth.toString()
- + ". This component will not be loaded", ex);
+ CLASS_LOGGER.log(Level.WARNING, ex,
+ () -> "Error found reading component from file "
+ + pth.toString()
+ + ". This component will not be loaded");
}
}
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java b/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java
index 6780f2e..2644276 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java
@@ -1,17 +1,18 @@
package bjc.utils.components;
-import bjc.utils.funcdata.IFunctionalList;
-import bjc.utils.funcdata.IFunctionalMap;
+import bjc.utils.funcdata.IList;
+import bjc.utils.funcdata.IMap;
/**
- * A collection of implementations of {@link IDescribedComponent}
+ * A collection of implementations of a particular type of
+ * {@link IDescribedComponent}
*
* @author ben
*
- * @param <E>
+ * @param <ComponentType>
* The type of components contained in this repository
*/
-public interface IComponentRepository<E extends IDescribedComponent> {
+public interface IComponentRepository<ComponentType extends IDescribedComponent> {
/**
* Get a component with a specific name
*
@@ -20,15 +21,15 @@ public interface IComponentRepository<E extends IDescribedComponent> {
* @return The named component, or null if no component with that name
* exists
*/
- public E getComponentByName(String name);
+ public ComponentType getByName(String name);
/**
* Get a list of all the registered componets
*
* @return A list of all the registered components
*/
- public default IFunctionalList<E> getComponentList() {
- return getComponents().valueList();
+ public default IList<ComponentType> getList() {
+ return getAll().valueList();
}
/**
@@ -37,7 +38,7 @@ public interface IComponentRepository<E extends IDescribedComponent> {
* @return A map from component name to component, containing all of
* the components in the repositories
*/
- public IFunctionalMap<String, E> getComponents();
+ public IMap<String, ComponentType> getAll();
/**
* Get the source from which these components came