Primitive.java
package Hoot.Runtime.Names;
import java.io.*;
import java.util.*;
import java.time.*;
import java.math.*;
import java.time.format.*;
import java.lang.reflect.*;
import static java.lang.Math.*;
import static java.lang.reflect.Modifier.*;
import org.apache.commons.lang3.StringUtils;
import static org.apache.commons.lang3.StringUtils.*;
import Hoot.Runtime.Faces.Valued;
import Hoot.Runtime.Faces.Logging;
import Hoot.Runtime.Faces.IntegerValue;
import Hoot.Runtime.Behaviors.HootRegistry;
import static Hoot.Runtime.Names.Name.Dot;
import static Hoot.Runtime.Names.Keyword.Arrayed;
import static Hoot.Runtime.Functions.Exceptional.*;
import static Hoot.Runtime.Functions.Utils.*;
import java.util.Map.Entry;
/**
* Knows primitive Java types.
*
* @author nik <nikboyd@sonic.net>
* @see "Copyright 2010,2021 Nikolas S Boyd."
* @see "Permission is granted to copy this work provided this copyright statement is retained in all copies."
*/
public class Primitive implements Logging {
// system level logging
public static void printError(String message) { System.err.println(message); }
public static void printLine(String message) { System.out.println(message); }
public static void print(String message) { System.out.print(message); }
public static void printLine() { System.out.println(); }
static final String LongReport = "%,d";
public static String printLong(long longValue) { return String.format(LongReport, longValue); }
public static final String WriteMode = "rw";
public static final String CreateMode = "create";
public static final String AppendMode = "append";
public static final String TruncateMode = "truncate";
public static RandomAccessFile writeFile(String fileName, String openMode) {
File file = new File(fileName);
if (file.exists()) {
return nullOrTryLoudly(() -> {
RandomAccessFile result = new RandomAccessFile(file, WriteMode);
if (!AppendMode.equals(openMode)) { result.setLength(0); } // truncate file
return result;
});
}
else {
return nullOrTryLoudly(() -> { return new RandomAccessFile(file, WriteMode); });
}
}
public static final String ReadMode = "r";
public static RandomAccessFile readFile(String fileName) { return readFile(fileName, ReadMode); }
public static RandomAccessFile readFile(String fileName, String fileMode) {
return nullOrTryLoudly(() -> {
File file = new File(fileName);
if (!file.exists()) return null;
return new RandomAccessFile(file, fileMode);
});
}
public static boolean isStatic(Field f) { return STATIC == (f.getModifiers() & STATIC); }
public static boolean isStatic(Method m) { return STATIC == (m.getModifiers() & STATIC); }
public static int minimumPriority() { return Thread.MIN_PRIORITY; }
public static int maximumPriority() { return Thread.MAX_PRIORITY; }
public static int normalPriority() { return Thread.NORM_PRIORITY; }
public static void waitMilliseconds(IntegerValue duration) { runQuietly(() -> Thread.sleep(duration.intValue())); }
static final DateTimeFormatter PreferredTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSS");
public static String printTime(LocalDateTime timestamp) { return timestamp.format(PreferredTimeFormat); }
public static String printTimeNow() { return printTime(LocalDateTime.now()); }
public static String formatTime(LocalDateTime timestamp, String pattern) {
return timestamp.format(DateTimeFormatter.ofPattern(pattern)); }
public static int hierarchyDepth(Class<?> aClass) {
int count = 0; Class<?> testClass = aClass;
while (testClass != null) { count++; testClass = testClass.getSuperclass(); }
return count; }
public static int length(byte[] bytes) { return bytes.length; }
public static <T> int length(T[] elements) { return elements.length; }
public static String reverse(String value) { return StringUtils.reverse(value); }
public static List<String> tokenize(String value, String separators) {
return map(Collections.list(tokens(value, separators)), token -> (String)token); }
public static StringTokenizer tokens(String value, String separators) {
return new StringTokenizer(value, separators); }
public static String systemValue(String valueName) { return System.getProperty(valueName); }
public static String systemValue(String valueName, String defaultValue) {
return System.getProperty(valueName, defaultValue); }
public static Double radiansPerDegree() { return (Math.PI / 180.0f); }
public static Double degreesPerRadian() { return (180.0f / Math.PI); }
private static final int NegativeUnity = -1;
public static int negativeUnity() { return NegativeUnity; }
static final String DigitValue = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static String printDecimal(long... values) { // upper, lower, scale
StringBuilder b = new StringBuilder();
long upper = values[0];
long lower = values[1];
long scale = values[2];
long d = (long)Math.pow(10, scale);
long n = upper * d;
n += lower >> 1; n /= lower;
if (upper < 0L) {
b.append('-'); n = 0 - n;
}
long quo = n / d;
long rem = n % d;
int s = (int)scale;
b.append(quo);
b.append('.');
while (s-- > 0) {
rem = rem * 10L;
int digit = (int)(rem / d);
b.append(DigitValue.charAt(digit));
rem = rem % d;
}
b.append('s');
b.append(scale);
return b.toString();
}
@SuppressWarnings("UseSpecificCatch")
public static boolean class_hasMethod(Class<?> aClass, String methodName) {
try {
return hasOne(aClass.getMethod(methodName));
}
catch (Exception e) {
return false;
}
}
public static java.net.URL locateClass(Class<?> aClass) {
return aClass.getProtectionDomain().getCodeSource().getLocation();
}
public static Object newInstance(Class<?> aClass) {
try {
return aClass.newInstance();
}
catch (IllegalAccessException | InstantiationException ex) {
printError(aClass.getCanonicalName() + " can't create a new instance");
return HootRegistry.Nil();
}
}
public static int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
public static Integer[] rationalize(int num, int den) {
int n = den < 0 ? -num : num;
int d = abs(den);
int gcd = gcd(n, d);
if (d == gcd) {
Integer[] results = { n / gcd, 1 };
return results;
}
if (1 == gcd) {
Integer[] results = { n, d };
return results;
}
Integer[] results = { n / gcd, d / gcd };
return results;
}
public static double truncate(double value) { return (value < 0.0d ? Math.ceil(value) : Math.floor(value)); }
public static BigDecimal decimalFrom(long numerator, long denominator, int scale) {
return new BigDecimal(numerator)
.divide(new BigDecimal(denominator),
scale, RoundingMode.HALF_UP); }
public static final Primitive Reporter = new Primitive();
public static BigInteger[] integersFrom(Double... ds) {
BigInteger[] results = {
BigDecimal.valueOf(ds[0]).toBigInteger(),
BigDecimal.valueOf(ds[1]).toBigInteger() };
Reporter.whisper(results[0].toString());
Reporter.whisper(results[1].toString());
return results; }
public static BigInteger[] fractionalize(double value, int sig) {
double limit = Math.pow( 10.0d, sig );
double n1 = truncate(value); double n2 = 1.0d;
double d1 = 1.0d; double d2 = 0.0d;
double i = n1; double x = 0.0d;
double f = value - n1;
while (f != 0.0d) {
double dn = 1.0d / f;
i = truncate(dn); f = dn - i;
x = n2; n2 = n1;
n1 = ( n1 * i ) + x;
x = d2; d2 = d1;
d1 = ( d1 * i ) + x;
if (limit < d1) {
if (n2 == 0.0d) {
return integersFrom(n1, d1);
}
else {
return integersFrom(n2, d2);
}
}
}
return integersFrom(n1, d1);
}
public static Long[] parseDecimal(String value) {
int point = value.indexOf( '.' );
int sMark = value.indexOf( 's' );
String iString = value.substring( 0, point );
String fString = value.substring( point + 1, sMark );
String sString = value.substring( sMark + 1 );
long scale = 0;
long numerator = 0;
long denominator = 1;
for( int i = 0; i < fString.length(); i++ ) denominator *= 10;
Long[] results = { numerator, denominator, scale };
// integer digits + fraction digits / scale of 10s
runQuietly(() -> {
results[2] = Long.parseLong(sString);
results[0] = Long.parseLong(iString + fString);
});
return results;
}
public static int invertBits(int bits) { return ~bits; }
public static long invertBits(long bits) { return ~bits; }
public static int xorBits(int a, int b) { return a ^ b; }
public static long xorBits(long a, long b) { return a ^ b; }
public static Double elementaryMaxDouble() { return java.lang.Double.MAX_VALUE; }
public static Double elementaryMinDouble() { return java.lang.Double.MIN_VALUE; }
public static Float elementaryMaxFloat() { return java.lang.Float.MAX_VALUE; }
public static Float elementaryMinFloat() { return java.lang.Float.MIN_VALUE; }
public static Long elementaryMaxLong() { return java.lang.Long.MAX_VALUE; }
public static Long elementaryMinLong() { return java.lang.Long.MIN_VALUE; }
public static Integer elementaryMaxInteger() { return java.lang.Integer.MAX_VALUE; }
public static Integer elementaryMinInteger() { return java.lang.Integer.MIN_VALUE; }
public static Short elementaryMaxShort() { return java.lang.Short.MAX_VALUE; }
public static Short elementaryMinShort() { return java.lang.Short.MIN_VALUE; }
public static Boolean elementaryFalse() { return java.lang.Boolean.FALSE; }
public static Boolean elementaryTrue() { return java.lang.Boolean.TRUE; }
public static float getFloat(String value) { return Float.parseFloat(value); }
public static final String Dollar = "$";
public static final String Pound = "#";
public static String getLiteral(String value) {
if (isEmpty(value)) return Empty;
if (value.startsWith(Dollar)) return quoteWith(SingleQuote, value.substring(1));
if (value.startsWith(Pound)) return quoteWith(NativeQuote, value.substring(1));
if (value.startsWith(SingleQuote)) return quoteNatively(value);
return value; }
public static final String SingleQuote = "'";
public static String quoteLiterally(String value) { return quoteWith(SingleQuote, value); }
public static String trimQuotes(String quote, String value) { return StringUtils.strip(value, quote); }
public static String trimQuotes(String value) { return StringUtils.strip(value, NativeQuote); }
public static String trimQuoted(String value) { return StringUtils.strip(value, SingleQuote); }
public static final String NativeQuote = "\"";
public static final String DoubledQuotes = "''";
public static String quoteNatively(String value) {
return quoteWith(NativeQuote, trimQuotes(SingleQuote, value).replace(DoubledQuotes, SingleQuote)); }
public static String quoteWith(String quote, String value) {
return (isEmpty(value) ? quote + quote : quote + value + quote); }
public static Valued shallowCopyOf(Valued v) { return v; }
public static Valued deepCopyOf(Valued v) { return v; }
protected static final String[] ElementPackages = { "java.", "javax.", };
protected static final List<String> ElementaryPackages = wrap(ElementPackages);
public static final String[] SerializedNames = { "Cloneable", "Serializable", "CharSequence", "Comparable", };
public static final List<String> SerializedTypes = wrap(SerializedNames);
protected static final Map<String, String> ConversionTypes = emptyWordMap();
protected static final Map<String, String> PrimitiveWrappers = emptyWordMap();
protected static final Map<String, String> PrimitiveUnwrappers = emptyWordMap();
protected static final Map<String, String> ElementaryWrappers = emptyWordMap();
protected static final Map<String, String> ElementaryUnwrappers = emptyWordMap();
protected static final Map<String, Class> PrimitiveTypes = emptyMap(Class.class);
protected static final List<String> Primitives = emptyList(String.class);
public static final Class<?> JavaRoot = java.lang.Object.class;
static {
initializePrimitiveTypes();
initializePrimitiveWrappers();
initializeObjectWrappers();
}
protected static void initializePrimitiveTypes() {
PrimitiveTypes.put("void", void.class);
PrimitiveTypes.put("boolean", boolean.class);
PrimitiveTypes.put("byte", byte.class);
PrimitiveTypes.put("char", char.class);
PrimitiveTypes.put("int", int.class);
PrimitiveTypes.put("short", short.class);
PrimitiveTypes.put("long", long.class);
PrimitiveTypes.put("float", float.class);
PrimitiveTypes.put("double", double.class);
PrimitiveTypes.put("string", String.class);
PrimitiveTypes.put("decimal", java.math.BigDecimal.class);
}
protected static void initializePrimitiveWrappers() {
PrimitiveWrappers.put("boolean", "Boolean");
PrimitiveWrappers.put("byte", "Number");
PrimitiveWrappers.put("char", "Number");
PrimitiveWrappers.put("short", "Number");
PrimitiveWrappers.put("int", "Number");
PrimitiveWrappers.put("long", "Number");
PrimitiveWrappers.put("float", "Float");
PrimitiveWrappers.put("double", "Double");
PrimitiveUnwrappers.put("boolean", "asPrimitive");
PrimitiveUnwrappers.put("byte", "primitiveByte");
PrimitiveUnwrappers.put("char", "primitiveCharacter");
PrimitiveUnwrappers.put("short", "primitiveShort");
PrimitiveUnwrappers.put("int", "primitiveInteger");
PrimitiveUnwrappers.put("long", "primitiveLong");
PrimitiveUnwrappers.put("float", "asPrimitive");
PrimitiveUnwrappers.put("double", "asPrimitive");
Primitives.addAll(PrimitiveWrappers.keySet());
Primitives.add("void");
}
protected static void initializeObjectWrappers() {
ConversionTypes.put("Int", "int");
ConversionTypes.put("Byte", "byte");
ConversionTypes.put("java.lang.Byte", "byte");
ConversionTypes.put("java.lang.Boolean", "boolean");
ConversionTypes.put("java.lang.String", "java.lang.String");
ElementaryWrappers.put("java.math.BigDecimal", "Fixed");
ElementaryWrappers.put("java.lang.Boolean", "Boolean");
ElementaryWrappers.put("java.lang.Float", "Float");
ElementaryWrappers.put("java.lang.Double", "Double");
ElementaryWrappers.put("java.lang.Character", "Character");
ElementaryWrappers.put("java.lang.String", "String");
ElementaryWrappers.put(JavaRoot.getCanonicalName(), "Object");
ElementaryWrappers.put("Boolean", "Boolean");
ElementaryWrappers.put("String", "String");
ElementaryWrappers.put("Float", "Float");
ElementaryWrappers.put("Double", "Double");
ElementaryWrappers.put("Object", "Object");
ElementaryUnwrappers.put("java.math.BigDecimal", "asPrimitive");
ElementaryUnwrappers.put("java.lang.Boolean", "asPrimitive");
ElementaryUnwrappers.put("java.lang.String", "asPrimitive");
// can any others be predetermined?
}
public static Class typeNamed(String typeName) {
return PrimitiveTypes.getOrDefault(typeName.toLowerCase(), null); }
public static String simplifiedType(String typeName) { return typeName.replace(Arrayed, Empty).toLowerCase(); }
public static Class getPrimitiveType(String typeName) { return PrimitiveTypes.get(typeName); }
public static String convertType(String typeName) {
String result = convertsType(typeName) ? ConversionTypes.get(typeName) : typeName;
return result; }
public static boolean convertsType(String typeName) {
return !typeName.isEmpty() && ConversionTypes.containsKey(typeName); }
public static boolean isPrimitiveType(String typeName) {
return !typeName.isEmpty() &&
Primitives.contains(simplifiedType(typeName)) &&
!ElementaryWrappers.containsKey(typeName); }
public static boolean isElementaryType(String typeName) {
return !typeName.isEmpty() && ElementaryWrappers.containsKey(typeName); }
public static boolean isEraseableType(String typeName) {
return !typeName.isEmpty() &&
(PrimitiveWrappers.containsKey(simplifiedType(typeName)) ||
ElementaryWrappers.containsKey(typeName)); }
public static boolean fromElementaryPackage(String typeName) {
return !typeName.isEmpty() && typeName.contains(Dot) ?
matchAny(ElementaryPackages, prefix -> simplifiedType(typeName).startsWith(prefix)) :
matchAny(ElementaryPackages, prefix -> prefix.startsWith(simplifiedType(typeName))); }
public static final String[] EmptyArray = { };
public static String[] wrapsFrom(String typeName) {
if (PrimitiveWrappers.containsKey(typeName)) {
String[] result = { PrimitiveWrappers.get(typeName), PrimitiveUnwrappers.get(typeName) };
return result;
}
if (ElementaryWrappers.containsKey(typeName)) {
String[] result = { ElementaryWrappers.get(typeName), ElementaryUnwrappers.get(typeName) };
return result;
}
String[] empty = EmptyArray;
return empty;
}
public static <K, T> K findKey(T value, Map<K,T> map) {
for (Entry<K,T> entry : map.entrySet()) {
if (entry.getValue().equals(value)) return entry.getKey();
}
return null;
}
public static final String Blank = " ";
} // Primitive