String to Object conversions, - java

From time to time I'm in a situation where I need to convert String values to objects. And often I end up with a custom method.
Here's an example:
#Nullable
public static Object valueOf(Class pParamType, String pValue)
{
if (pValue == null) return null;
if ("null".equals(pValue)) return null;
if (String.class.equals(pParamType)) return pValue;
if (Number.class.equals(pParamType)) return Double.valueOf(pValue);
if (Long.class.equals(pParamType) || Long.TYPE.equals(pParamType)) return Long.valueOf(pValue);
if (Double.class.equals(pParamType) || Double.TYPE.equals(pParamType)) return Double.valueOf(pValue);
if (Integer.class.equals(pParamType) || Integer.TYPE.equals(pParamType)) return Integer.valueOf(pValue);
if (Byte.class.equals(pParamType) || Byte.TYPE.equals(pParamType)) return Byte.valueOf(pValue);
if (Short.class.equals(pParamType) || Short.TYPE.equals(pParamType)) return Short.valueOf(pValue);
if (Float.class.equals(pParamType) || Float.TYPE.equals(pParamType)) return Float.valueOf(pValue);
if (Date.class.equals(pParamType))
{
try
{
return Formatter.parse(pValue, DATE_PATTERN);
}
catch (Exception e)
{
throw new IllegalArgumentException("Illegal date format");
}
}
if (Boolean.class.equals(pParamType) || Boolean.TYPE.equals(pParamType))
{
return Boolean.valueOf(pValue);
}
throw new IllegalArgumentException("Parameters of type [" + pParamType.getName() + "] are not supported");
}
I do realize that it's impossible to convert to just any object. But most java.lang classes do have a valueOf method in place
But I hate to repeat myself, and I have the feeling that there should be something out there that does the same thing already, and probably even covers more.
My question is:
Does the jdk offer a similar utility class or method in the java framework ?
Alternatively what do other frameworks offer ? (e.g. apache commons, spring, guava, ...)

Using reflection you can try to find a constructor with String argument and invoke the constructor
public static void main(String[] args) throws Exception{
System.out.println(valueOf(String.class, ""));
System.out.println(valueOf(Long.class, "1"));
System.out.println(valueOf(Integer.class, "1"));
System.out.println(valueOf(Byte.class, "1"));
System.out.println(valueOf(Short.class, "1"));
System.out.println(valueOf(Double.class, "1.1"));
System.out.println(valueOf(Float.class, "1.1"));
System.out.println(valueOf(Boolean.class, "true"));
}
public static Object valueOf(Class pParamType, String pValue) throws Exception
{
if (pValue == null) return null;
if ("null".equals(pValue)) return null;
Constructor constructor = pParamType.getConstructor(String.class);
if (constructor!=null) {
return constructor.newInstance(pValue);
}
//... keep the logic for Date
throw new IllegalArgumentException("Parameters of type [" + pParamType.getName() + "] are not supported");
}

Related

How do load a Service without using ServiceLoader.Provider class (for J1.8 compatibility)

I'm trying to back-port to J1.8 an application written for J9 (Update4j); it uses ServiceLoader.Provider class and its methods.
The original code is:
public static <T extends Service> T loadService(ModuleLayer layer, ClassLoader classLoader, Class<T> type,
String classname) {
if (classname != null && !StringUtils.isClassName(classname)) {
throw new IllegalArgumentException(classname + " is not a valid Java class name.");
}
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
ServiceLoader<T> loader;
List<Provider<T>> providers = new ArrayList<>();
if (layer != null) {
loader = ServiceLoader.load(layer, type);
providers.addAll(loader.stream().collect(Collectors.toList()));
}
loader = ServiceLoader.load(type, classLoader);
providers.addAll(loader.stream().collect(Collectors.toList()));
if (classname != null) {
// an explicit class name is used
// first lets look at providers, to locate in closed modules
for (Provider<T> p : providers) {
if (p.type().getName().equals(classname))
return p.get();
}
// nothing found, lets load with reflection
try {
Class<?> clazz = classLoader.loadClass(classname);
if (type.isAssignableFrom(clazz)) {
// What do you mean?? look 1 line above
#SuppressWarnings("unchecked")
T value = (T) clazz.getConstructor().newInstance();
return value;
} else {
// wrong type
throw new IllegalArgumentException(classname + " is not of type " + type.getCanonicalName());
}
} catch (RuntimeException e) {
throw e; // avoid unnecessary wrapping
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
if (providers.isEmpty()) {
throw new IllegalStateException("No provider found for " + type.getCanonicalName());
}
List<T> values = providers.stream().map(Provider::get).collect(Collectors.toList());
long maxVersion = Long.MIN_VALUE;
T maxValue = null;
for (T t : values) {
long version = t.version();
if (maxVersion <= version) {
maxVersion = version;
maxValue = t;
}
}
return maxValue;
}
}
How can you achieve the same result in J1.8? Is there a best-practice?
Unfortunately J1.8 does not have ServiceLoader.Provider and its utility methods. Should I iterate and select? Is there a reference I can study?
Thanks
There’s something you can improve or simplify. I wouldn’t waste resources to check the validity of the class name argument but postpone it until the class truly hasn’t found. Or, since the restrictions on class names at JVM level are much less than in Java source code, I wouldn’t check the name at all, as checking whether a matching class exist is already enough.
There is no point in iterating over all providers and adding them to a List, just to iterate over the list and search for a maximum version, when we could search for the maximum version right in the first iteration, without the List.
Note that for both cases, searching for a service with a given name and for searching for the maximum version, we can use the Stream API.
For the reflection fallback, catching ReflectiveOperationException instead of Exception removes the need to catch and re-throw RuntimeException. Also, knowing about Class.cast(…) and Class.asSubclass(…) helps avoiding unchecked casts.
public static <T extends Service> T loadService(
Object layer, ClassLoader classLoader, Class<T> type, String classname) {
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
Stream<T> s = StreamSupport.stream(
ServiceLoader.load(type, classLoader).spliterator(), false);
if(classname == null)
return s.max(Comparator.comparingLong(T::version))
.orElseThrow(() -> new IllegalStateException(
"No provider found for " + type.getCanonicalName()));
Optional<T> o = s.filter(t -> t.getClass().getName().equals(classname)).findAny();
if(o.isPresent()) return o.get();
try {
// nothing found, lets load with reflection
Class<?> clazz = classLoader.loadClass(classname);
// we could also use a single
// return clazz.asSubclass(type).getConstructor().newInstance();
// if we can live with a ClassCastException instead of IllegalArgumentException
if(!type.isAssignableFrom(clazz)) {
throw new IllegalArgumentException(
classname + " is not of type " + type.getCanonicalName());
}
return type.cast(clazz.getConstructor().newInstance());
} catch(ReflectiveOperationException e) {
if(!StringUtils.isClassName(classname)) { // debatable whether needed
throw new IllegalArgumentException(
classname + " is not a valid Java class name.");
}
throw new RuntimeException(e);
}
}
Well, I do not know if this is the best practice but this solves:
public static <T extends Service> T loadService(Object layer, ClassLoader classLoader, Class<T> type, String classname) {
if (classname != null && !StringUtils.isClassName(classname)) {
throw new IllegalArgumentException(classname + " is not a valid Java class name.");
}
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
ServiceLoader<T> loader;
loader = ServiceLoader.load(type, classLoader);
Iterator<T> iterator = loader.iterator();
if (classname != null) {
// an explicit class name is used
// first lets iterate on providers, to locate in closed modules
while (iterator.hasNext()) {
T p = iterator.next();
if (p.getClass().getName().equals(classname))
return p;
}
// nothing found, lets load with reflection
try {
Class<?> clazz = classLoader.loadClass(classname);
if (type.isAssignableFrom(clazz)) {
// What do you mean?? look 1 line above
#SuppressWarnings("unchecked")
T value = (T) clazz.getConstructor().newInstance();
return value;
} else {
// wrong type
throw new IllegalArgumentException(classname + " is not of type " + type.getCanonicalName());
}
} catch (RuntimeException e) {
throw e; // avoid unnecessary wrapping
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
if (!iterator.hasNext()) {
throw new IllegalStateException("No provider found for " + type.getCanonicalName());
}
List<T> values = new ArrayList();
while (iterator.hasNext()) {
T p = iterator.next();
values.add(p);
}
long maxVersion = Long.MIN_VALUE;
T maxValue = null;
for (T t : values) {
long version = t.version();
if (maxVersion <= version) {
maxVersion = version;
maxValue = t;
}
}
return maxValue;
}
}
Hoping this could help someone downgrading Update4j to J1.8.
I forked the original project and may be I'll release my public fork for J1.8 later, when it will be completely working.

Scanning File with String and int Java

So i have a .dat file that is a list. Each line starts with a letter as a command for my alarm clock program and some are followed by numbers in time format (XX:XX). I need to scan the letter arr[0] so the program knows which method to implement and then separate the integers from the colon to have arr[1] and arr[2]. I can't seem to figure out how to do both.
Example :T 25:00
while (scan.hasNextLine()){
String[] data = scan.nextLine().split(" ");
if (data[0] == "D"){
myClock.getTime();
}
else if (data[0] == "A"){
myClock.getAlarmTime();
}
else if (data[0] == "T"){
myClock.setTime(data[1], data[2]);
}
else if (data[0] == "S"){
myClock.setAlarmTime(data[1], data[2]);
}
else if (data[0] == "O"){
myClock.setAlarmOn(true);
}
else if (data[0] == "F"){
myClock.setAlarmOn(false);
}
else{
myClock.quit();
tells me I have incompatible types and that .String cannot be converted to int. So how do I convert or scan the two separately?
Instead of
String str[] = scan.nextLine().split(" ");
place
String str[] = scan.nextLine().split(" |:");
...............
if (str[0].equals("T"))
myClock.setTime(Integer.parseInt(str[1], Integer.parseInt(str[2]);
One more issue is if (data[0] == "T" ) means compaing strings
In java, we should use equals() for checking strings equality whether both are same or not.
Instead of
if (data[0] == "T" )
use
if (data[0].equals( "T" ))
If your error is at this line myClock.setAlarmTime(data[1], data[2]);, try to convert it to int.
Mby your functions for setAlarmTime and setTime need ints and you are passing Strings, compiler normally advise this.
Try this:
myClock.setAlarmTime(Integer.valueOf(data[1]), Integer.valueOf(data[2]));
Also, you want to separate this T 25:00to this: { "T","25", "00" }
And with this line String[] data = scan.nextLine().split(" "); you will get: { "T","25:00" }
You need to split again your data[1] before do setAlarmTime and setTime with:
String[] timeSplit = data[1].split(":");
myClock.setAlarmTime(Integer.valueOf(timeSplit[0]), Integer.valueOf(timeSplit[1]));
loosely based on #Boris the Spider comment
public class EnumCommand {
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("csv.dat"));
String s;
while ((s = br.readLine()) != null) {
StringTokenizer st = new StringTokenizer(s);
MyCommand.valueOf(st.nextToken()).execute(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private enum MyCommand {
D {
#Override
public void execute(String predicate) {
//getTime
}
},
A {
#Override
public void execute(String predicate) {
//getAlarm Time
}
},
T {
#Override
public void execute(String predicate) {
//setTime .. Parse here for time
System.out.println(predicate);
}
},
S {
#Override
public void execute(String predicate) {
//set alarm Time Parse here for time
System.out.println(predicate);
}
},
O {
#Override
public void execute(String predicate) {
//On alarm
}
},
F {
#Override
public void execute(String predicate) {
//Off alarm
}
};
public abstract void execute(String predicate);
}
}

Is Java jackson ObjectWriter.ObjectWriter.writeValueAsString(obj); stable?

I am currently writing test cases using TestNg. I populate objects using PodamFactory. I have following test case structure.
#Test
public void testIt(){
ARespObject resp = PodamFactory.manufacturePojo(ARespObject.class);
String responseXml = new JaxbStringTransformer().transform(resp);
// a new object with all the same data
ARespObject respActual = responder.getObj(responseXml);
Assert.assertTrue(TestUtils.areEqual(respActual , resp));
}
public static <T extends Object> boolean areEqual(T sourceObj, T target) {
if (sourceObj == null && target == null) {
return true;
}
if (sourceObj == target) {
return true;
}
if (sourceObj.getClass() != target.getClass()) {
return false;
}
if (sourceObj != null && target != null) {
return stringifyObject(sourceObj).equals(stringifyObject(target));
}
return false;
}
public static String stringifyObject(Object obj) {
String result = "";
ObjectWriter ow = new JaxbJacksonObjectMapper().writer().withDefaultPrettyPrinter();
try {
result = ow.writeValueAsString(obj);
} catch (JsonGenerationException e1) {
LOG.error(e1);
} catch (JsonMappingException e1) {
LOG.error("JsonMappingException: " + e1);
} catch (IOException e1) {
LOG.error("IOException: " + e1);
}
return result;
}
I need to know if writeValueAsString(obj) will always provide same structure for both objects(i.e. its output will be stable) and following
stringifyObject(sourceObj).equals(stringifyObject(target));
is a valid check. I am concerned about whether it will ever give me different ordering of variables inside the ARespObject.
Rather than formatting the objects to strings for comparison, convert them to "tree model" (JsonNode implementations). ObjectNode implements equals/hashCode/toString etc to reasonably imitate JSON equivalence, so it will disregard the order of properties for example.
ObjectMapper mapper = new ObjectMapper();
JsonNode treeNode = mapper.convertValue(obj, JsonNode.class);
(typically you will actually get an ObjectNode back, but you can just probably just use the JsonNode interface)
The tree model classes will also perform a simple JSON formatting for toString() output, so "expected" and "actual" printouts should be readable (although not as pretty as with the pretty printer)
I would recommend against using the string representation of an object to test for equality. You should instead use the .equals method of the objects you want to test.

Recursive function not working for to get innermost exception message

I have written this method
private string FindInnerExceptionMessage(Exception ex)
{
string exceptionMsg = string.Empty;
if (ex.InnerException == null)
{
exceptionMsg = ex.Message;
}
else
{
ex = ex.InnerException;
FindInnerExceptionMessage(ex);
}
return exceptionMsg;
}
However, after that FindInnerExceptionMessage it is stepping to return exceptionMsg and not logging the exact exception message
You don't actually assign the return value of your recursive call to anything. As a result, your first call will return String.Empty because the value of FindInnerExceptionMessage(ex.InnerException) is never assigned as the return value (unless the exception passed to the first call has no inner exception, in which case it will work). Try something like this:
private string FindInnerExceptionMessage(Exception ex)
{
string exceptionMsg = string.Empty;
if (ex.InnerException == null)
{
exceptionMsg = ex.Message;
}
else
{
exceptionMsg = FindInnerExceptionMessage(ex.InnerException);
}
return exceptionMsg;
}

validation function problem

Hello
I am not able to get the correct validation.I think there is some error in this code so can anyone please help me solving this problem.
public static boolean validateFee(String value) {
boolean isvalid = true;
try {
int fee = 0;
if (value != null && !value.isEmpty()) {
fee = Integer.parseInt(value);
}
} catch (NumberFormatException ne) {
// ne.printStackTrace();
isvalid = false;
return isvalid;
}
return isvalid;
}
}
I am actaully using this code for validation of fee in which i m using a regex as [0-9]+.
This code i m using it in a common function.Actually validation call is done in the servlet as follows:
private Boolean validateFee(HttpSession session, PropertiesHandler props, String number) {
Boolean isvalid = true;
HashMap hashMap = new LinkedHashMap();
number = ApplicationConstants.FEE_PATTERN;
if (!Validation.validateFee(number)) {
isvalid = false;
hashMap.put("time", props.getText("error.fee.invalid.type"));
}
session.setAttribute("errorMessage", hashMap);
System.out.println("Map size " + hashMap.size());
logger.info("Exit validateTIme"); return isvalid;
}
I think there is no error in that but i have a doubt in this function.I am facing a problem like if i give number to the fee also its taking validation.please help me out
Currently it allows value of null or "" to count as being valid - is that deliberate?
Note that your current code can be rewritten more simply:
public static boolean validateFee(String value) {
try {
if (value != null && !value.isEmpty()) {
Integer.parseInt(value);
}
return true;
} catch (NumberFormatException ne) {
return false;
}
}
Now if you want null/empty to count as invalid, I'd rewrite it as:
public static boolean validateFee(String value) {
if (value == null || value.isEmpty()) {
return false;
}
try {
Integer.parseInt(value);
return true;
} catch (NumberFormatException ne) {
return false;
}
}
trim your string and then pass it to.
StringUtils.isNumeric(StringUtils.trimToNull(fees));
You can directly use StringUtils.isNumeric()
I recommend you use commons-lang StringUtils class, your validate method is re-written
public static boolean validateFee(String value) {
return StringUtils.isNumeric(StringUtils.trimToNull(value));
}
And you remove ApplicationConstants.FEE_PATTERN completely. The problem you are currently facing is that your servlet overwrites its input value with ApplicationConstants.FEE_PATTERN. Your servlet method is re-written
private Boolean validateFee(HttpSession session, PropertiesHandler props, String number) {
final Boolean valid = Validation.validateFee(number);
if (!valid) {
final HashMap hashMap = new LinkedHashMap();
hashMap.put("time", props.getText("error.fee.invalid.type"));
session.setAttribute("errorMessage", hashMap);
}
}

Categories

Resources