diff --git a/ax-command/pom.xml b/ax-command/pom.xml index 2a652b4f..3eb72206 100644 --- a/ax-command/pom.xml +++ b/ax-command/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 ax-command @@ -13,4 +15,13 @@ Alexandria Command Library for command line programming. + + + + com.g2forge.alexandria + ax-adt + ${project.version} + test + + diff --git a/ax-command/src/main/java/com/g2forge/alexandria/command/invocation/environment/SystemEnvironment.java b/ax-command/src/main/java/com/g2forge/alexandria/command/invocation/environment/SystemEnvironment.java index 1606d46c..7d7cffcb 100644 --- a/ax-command/src/main/java/com/g2forge/alexandria/command/invocation/environment/SystemEnvironment.java +++ b/ax-command/src/main/java/com/g2forge/alexandria/command/invocation/environment/SystemEnvironment.java @@ -1,8 +1,11 @@ package com.g2forge.alexandria.command.invocation.environment; +import java.util.Collections; import java.util.Map; +import java.util.TreeMap; import com.g2forge.alexandria.java.core.marker.ISingleton; +import com.g2forge.alexandria.java.platform.HPlatform; public class SystemEnvironment implements IEnvironment, ISingleton { protected static final SystemEnvironment INSTANCE = new SystemEnvironment(); @@ -20,6 +23,21 @@ public String apply(String name) { @Override public Map toMap() { + final Map systemEnvironment = getSystemEnvironment(); + + if (isCaseInsensitive()) { + final TreeMap retVal = new TreeMap(String.CASE_INSENSITIVE_ORDER); + retVal.putAll(systemEnvironment); + return Collections.unmodifiableSortedMap(retVal); + } + return systemEnvironment; + } + + protected Map getSystemEnvironment() { return System.getenv(); } + + protected boolean isCaseInsensitive() { + return HPlatform.getPlatform().getPathSpec().isCaseSensitive(); + } } diff --git a/ax-command/src/main/java/com/g2forge/alexandria/command/invocation/environment/modified/ModifiedEnvironment.java b/ax-command/src/main/java/com/g2forge/alexandria/command/invocation/environment/modified/ModifiedEnvironment.java index 9e2a4c0f..785c9ade 100644 --- a/ax-command/src/main/java/com/g2forge/alexandria/command/invocation/environment/modified/ModifiedEnvironment.java +++ b/ax-command/src/main/java/com/g2forge/alexandria/command/invocation/environment/modified/ModifiedEnvironment.java @@ -1,10 +1,9 @@ package com.g2forge.alexandria.command.invocation.environment.modified; -import java.util.Collections; -import java.util.LinkedHashMap; import java.util.Map; import com.g2forge.alexandria.command.invocation.environment.IEnvironment; +import com.g2forge.alexandria.java.core.helpers.HMap; import lombok.Builder; import lombok.Data; @@ -34,7 +33,7 @@ public IEnvironment simplify() { @Override public Map toMap() { - final Map retVal = new LinkedHashMap<>(getBase().toMap()); + final Map retVal = HMap.copy(getBase().toMap()); for (Map.Entry entry : getModifiers().entrySet()) { final String variable = entry.getKey(); @@ -44,6 +43,6 @@ public Map toMap() { else retVal.put(variable, modified); } - return Collections.unmodifiableMap(retVal); + return HMap.unmodifiableMap(retVal); } } diff --git a/ax-command/src/test/java/com/g2forge/alexandria/command/main/TestDispatchCommand.java b/ax-command/src/test/java/com/g2forge/alexandria/command/command/TestDispatchCommand.java similarity index 92% rename from ax-command/src/test/java/com/g2forge/alexandria/command/main/TestDispatchCommand.java rename to ax-command/src/test/java/com/g2forge/alexandria/command/command/TestDispatchCommand.java index 8da3f3a3..1528b5a9 100644 --- a/ax-command/src/test/java/com/g2forge/alexandria/command/main/TestDispatchCommand.java +++ b/ax-command/src/test/java/com/g2forge/alexandria/command/command/TestDispatchCommand.java @@ -1,4 +1,4 @@ -package com.g2forge.alexandria.command.main; +package com.g2forge.alexandria.command.command; import java.io.InputStream; import java.io.PrintStream; @@ -6,8 +6,6 @@ import org.junit.Assert; import org.junit.Test; -import com.g2forge.alexandria.command.command.DispatchCommand; -import com.g2forge.alexandria.command.command.IStandardCommand; import com.g2forge.alexandria.command.exit.Exit; import com.g2forge.alexandria.command.exit.IExit; import com.g2forge.alexandria.command.invocation.CommandInvocation; diff --git a/ax-command/src/test/java/com/g2forge/alexandria/command/main/TestStandardCommand.java b/ax-command/src/test/java/com/g2forge/alexandria/command/command/TestStandardCommand.java similarity index 96% rename from ax-command/src/test/java/com/g2forge/alexandria/command/main/TestStandardCommand.java rename to ax-command/src/test/java/com/g2forge/alexandria/command/command/TestStandardCommand.java index 280082d9..d225a0c6 100644 --- a/ax-command/src/test/java/com/g2forge/alexandria/command/main/TestStandardCommand.java +++ b/ax-command/src/test/java/com/g2forge/alexandria/command/command/TestStandardCommand.java @@ -1,4 +1,4 @@ -package com.g2forge.alexandria.command.main; +package com.g2forge.alexandria.command.command; import java.io.BufferedReader; import java.io.InputStream; @@ -8,7 +8,6 @@ import org.junit.Assert; import org.junit.Test; -import com.g2forge.alexandria.command.command.IStandardCommand; import com.g2forge.alexandria.command.command.IStandardCommand.TestResult; import com.g2forge.alexandria.command.exit.IExit; import com.g2forge.alexandria.command.invocation.CommandInvocation; diff --git a/ax-command/src/test/java/com/g2forge/alexandria/command/invocation/environment/TestSystemEnvironment.java b/ax-command/src/test/java/com/g2forge/alexandria/command/invocation/environment/TestSystemEnvironment.java new file mode 100644 index 00000000..4a2ba050 --- /dev/null +++ b/ax-command/src/test/java/com/g2forge/alexandria/command/invocation/environment/TestSystemEnvironment.java @@ -0,0 +1,50 @@ +package com.g2forge.alexandria.command.invocation.environment; + +import java.util.Map; +import java.util.Objects; + +import org.junit.Test; + +import com.g2forge.alexandria.adt.associative.map.MapBuilder; +import com.g2forge.alexandria.test.HAssert; + +public class TestSystemEnvironment { + @Test + public void caseInsensitive() { + final String key = "Key", value = "Value"; + final Map inputMap = new MapBuilder<>(key, value).build(); + final Map outputMap = new SystemEnvironment() { + @Override + protected Map getSystemEnvironment() { + return inputMap; + } + + @Override + protected boolean isCaseInsensitive() { + return true; + } + }.toMap(); + HAssert.assertEquals(value, outputMap.get(key)); + HAssert.assertEquals(value, outputMap.get(key.toUpperCase())); + HAssert.assertEquals(value, outputMap.get(key.toLowerCase())); + } + + @Test + public void caseSensitive() { + final String key = "Key", value = "Value"; + final Map inputMap = new MapBuilder<>(key, value).build(); + final Map outputMap = new SystemEnvironment() { + @Override + protected Map getSystemEnvironment() { + return inputMap; + } + + @Override + protected boolean isCaseInsensitive() { + return false; + } + }.toMap(); + HAssert.assertEquals(value, outputMap.get(key)); + HAssert.assertFalse(Objects.equals(value, outputMap.get(key.toUpperCase())) && Objects.equals(value, outputMap.get(key.toLowerCase()))); + } +} diff --git a/ax-command/src/test/java/com/g2forge/alexandria/command/invocation/environment/modified/TestModifiedEnvironment.java b/ax-command/src/test/java/com/g2forge/alexandria/command/invocation/environment/modified/TestModifiedEnvironment.java new file mode 100644 index 00000000..9d646cbc --- /dev/null +++ b/ax-command/src/test/java/com/g2forge/alexandria/command/invocation/environment/modified/TestModifiedEnvironment.java @@ -0,0 +1,58 @@ +package com.g2forge.alexandria.command.invocation.environment.modified; + +import java.util.Map; +import java.util.SortedMap; + +import org.junit.Test; + +import com.g2forge.alexandria.adt.associative.map.MapBuilder; +import com.g2forge.alexandria.command.invocation.environment.MapEnvironment; +import com.g2forge.alexandria.command.invocation.environment.SystemEnvironment; +import com.g2forge.alexandria.test.HAssert; + +public class TestModifiedEnvironment { + @Test + public void unspecified() { + final String key = "Key", value = "Value"; + final ModifiedEnvironment environment = ModifiedEnvironment.builder().base(new MapEnvironment(new MapBuilder<>(key, value).build())).modifier(key, EnvironmentModifier.Unspecified).build(); + HAssert.assertNull(environment.apply(key)); + HAssert.assertTrue(environment.toMap().isEmpty()); + } + + @Test + public void inherit() { + final String key = "Key", value = "Value"; + final ModifiedEnvironment environment = ModifiedEnvironment.builder().base(new MapEnvironment(new MapBuilder<>(key, value).build())).modifier(key, EnvironmentModifier.Inherit).build(); + HAssert.assertEquals(value, environment.apply(key)); + HAssert.assertEquals(1, environment.toMap().size()); + } + + @Test + public void value() { + final String key = "Key", value = "Value", other = "Other"; + final ModifiedEnvironment environment = ModifiedEnvironment.builder().base(new MapEnvironment(new MapBuilder<>(key, value).build())).modifier(key, new EnvironmentValue(other)).build(); + HAssert.assertEquals(other, environment.apply(key)); + HAssert.assertEquals(1, environment.toMap().size()); + } + + @Test + public void caseInsensitive() { + final String key = "Key", value = "Value"; + final Map inputMap = new MapBuilder<>(key, value).build(); + final Map outputMap = ModifiedEnvironment.builder().base(new SystemEnvironment() { + @Override + protected Map getSystemEnvironment() { + return inputMap; + } + + @Override + protected boolean isCaseInsensitive() { + return true; + } + }).build().toMap(); + HAssert.assertEquals(value, outputMap.get(key)); + HAssert.assertEquals(value, outputMap.get(key.toUpperCase())); + HAssert.assertEquals(value, outputMap.get(key.toLowerCase())); + HAssert.assertInstanceOf(SortedMap.class, outputMap); + } +} diff --git a/ax-adt/src/main/java/com/g2forge/alexandria/adt/associative/map/HMap.java b/ax-java/src/main/java/com/g2forge/alexandria/java/core/helpers/HMap.java similarity index 56% rename from ax-adt/src/main/java/com/g2forge/alexandria/adt/associative/map/HMap.java rename to ax-java/src/main/java/com/g2forge/alexandria/java/core/helpers/HMap.java index cc2737af..ce2a0456 100644 --- a/ax-adt/src/main/java/com/g2forge/alexandria/adt/associative/map/HMap.java +++ b/ax-java/src/main/java/com/g2forge/alexandria/java/core/helpers/HMap.java @@ -1,8 +1,10 @@ -package com.g2forge.alexandria.adt.associative.map; +package com.g2forge.alexandria.java.core.helpers; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; import java.util.function.Function; import com.g2forge.alexandria.java.core.marker.Helpers; @@ -33,4 +35,19 @@ public static Map merge(Map... maps) { } return retVal; } + + public static Map copy(Map map) { + if (map instanceof SortedMap) { + final SortedMap cast = (SortedMap) map; + final TreeMap retVal = new TreeMap<>(cast.comparator()); + retVal.putAll(map); + return retVal; + } + return new LinkedHashMap<>(map); + } + + public static Map unmodifiableMap(Map map) { + if (map instanceof SortedMap) return Collections.unmodifiableSortedMap((SortedMap) map); + return Collections.unmodifiableMap(map); + } } diff --git a/ax-type/src/main/java/com/g2forge/alexandria/generic/type/java/structure/JavaStructureAnalyzer.java b/ax-type/src/main/java/com/g2forge/alexandria/generic/type/java/structure/JavaStructureAnalyzer.java index 3ec8da85..cf799358 100644 --- a/ax-type/src/main/java/com/g2forge/alexandria/generic/type/java/structure/JavaStructureAnalyzer.java +++ b/ax-type/src/main/java/com/g2forge/alexandria/generic/type/java/structure/JavaStructureAnalyzer.java @@ -14,7 +14,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; -import com.g2forge.alexandria.adt.associative.map.HMap; +import com.g2forge.alexandria.java.core.helpers.HMap; import com.g2forge.alexandria.java.core.helpers.HTree; import com.g2forge.alexandria.java.reflect.JavaProtection; import com.g2forge.alexandria.java.reflect.JavaScope;