I'm trying to implement a HttpMessageConverter which would allow my program to talk over REST to an embedded smart controller.
The controller responds with strings such as:
ret=OK,htemp=27.0,hhum=-,otemp=27.0,err=0,cmpfreq=24
I have a Java object called SensorInfo.
public class SensorInfo {
String ret;
Double htemp;
String hhum;
Double otemp;
Integer err;
Integer cmpfreq;
// getters and setters
}
What's the best way of mapping the controller response to the above Java object?
You can simply split the string and assign each element as needed. You have:
ret=OK,htemp=27.0,hhum=-,otemp=27.0,err=0,cmpfreq=24
Lets assume you have that stored in a variable called myStr. Then all you need to do is this:
String[] strSplit = myStr.split(" ");
SensorInfo info = new SensorInfo();
info.ret = afterEquals(strSplit[0]);
info.htemp = Double.parse(afterEquals(strsplit[1]));
info.hhum = afterEquals(strSplit[2]);
info.otemp= Double.parse(afterEquals(strSplit[3]));
info.err = Integer.parse(afterEquals(strSplit[4]));
info.cmpfreq = Integer.parse(afterEquals(strSplit[5]));
You will declare a method to extract the part of the response after the equals sign to make the above work:
private String afterEquals(String input) {
input.substring(input.indexOf('=') + 1);
}
Note that this assumes the order of your response is fixed. If it isn't, you can easily modify this to look at each argument to see which variable to assign it to.
You should add error handling, as the following is not really error prone, but might help you:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ValueAssigner {
// ret=OK,htemp=27.0,hhum=-,otemp=27.0,err=0,cmpfreq=24
String ret;
Double htemp;
String hhum;
Double otemp;
Integer err;
Integer cmpfreq;
public static void main(String[] a) {
System.out.println(new ValueAssigner("ret=OK,htemp=27.0,hhum=-,otemp=27.0,err=0,cmpfreq=24").getCmpfreq());
}
ValueAssigner(String in) {
String[] split = in.split(",");
for (String s : split) {
Method method;
String[] keyValue = s.split("=");
try {
method = this.getClass().getMethod("set" + ucFirst(keyValue[0]), String.class);
method.invoke(this, keyValue[1]);
} catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException | SecurityException | NoSuchMethodException e) {
// e.printStackTrace();
// omitted here
}
}
}
private static String ucFirst(String in) {
return in.substring(0, 1).toUpperCase() + in.substring(1);
}
public String getRet() {
return ret;
}
public void setRet(String ret) {
this.ret = ret;
}
public Double getHtemp() {
return htemp;
}
public void setHtemp(String htemp) {
this.htemp = Double.parse(htemp);
}
public String getHhum() {
return hhum;
}
public void setHhum(String hhum) {
this.hhum = hhum;
}
public Double getOtemp() {
return otemp;
}
public void setOtemp(String otemp) {
this.otemp = Double.parse(otemp);
}
public Integer getErr() {
return err;
}
public void setErr(String err) {
this.err = Integer.parse(err);
}
public Integer getCmpfreq() {
return cmpfreq;
}
public void setCmpfreq(String cmpfreq) {
this.cmpfreq = Integer.parse(cmpfreq);
}
}
Related
I have Enum class as given below
public enum AlgorithmEnum {
SHA512("RSA", "SHA512", 1), SHA1("RSA", "SHA1", 1), SHA384("RSA", "SHA384", 1);
private String keyAlgorithm;
private String hashAlgorithm;
private Integer key;
private AlgorithmEnum(String keyAlgorithm, String hashAlgorithm, Integer key) {
this.keyAlgorithm = keyAlgorithm;
this.hashAlgorithm = hashAlgorithm;
this.key = key;
}
public String getKeyAlgorithm() {
return keyAlgorithm;
}
public void setKeyAlgorithm(String keyAlgorithm) {
this.keyAlgorithm = keyAlgorithm;
}
public String getHashAlgorithm() {
return hashAlgorithm;
}
public void setHashAlgorithm(String hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm;
}
public Integer getKey() {
return key;
}
public void setKey(Integer key) {
this.key = key;
}
}
I need to have method something like below which takes input as string and returns Enum
public AlgorithmEnum getAlgorithm(String algorithm){
//returns AlgorithmEnum object
}
I would call above method by passing "SHA512withRSA" as input for getAlgorithm method.
I need help in implementing the getAlgorithm method.
You can have something like:
public static AlgorithmEnum getAlgorithm(final String algorithm)
throws IllegalArgumentException
{
for (final AlgorithmEnum algorithmEnum : AlgorithmEnum.values())
{
if (algorithm.equalsIgnoreCase(String.format("%swith%s", algorithmEnum.getHashAlgorithm(), algorithmEnum.getKeyAlgorithm())))
{
return algorithmEnum;
}
}
throw new IllegalArgumentException("Unknown algorithm: " + algorithm);
}
However, I will not suggest to use this approach. Instead use 2 different arguments instead of a single String.
Assuming all string values passed to your method getAlgorithm() end with withRSA you could use the following to fetch the enum values :
public AlgorithmEnum getAlgorithm(String algorithm) {
return AlgorithmEnum.valueOf(algorithm.substring(0, algorithm.indexOf("withRSA")));
}
You can check if the given String contains a value that matches one of the enum attributes with some if statements:
public AlgorithmEnum getAlgorithm(String algorithm) {
if (algorithm.contains("SHA1")) {
return SHA1;
} else if (algorithm.contains("SHA512")) {
return SHA512;
} else if (algorithm.contains("SHA384")) {
return SHA384;
} else {
return null;
}
}
Please note that this will match Strings like "SHA512withoutRSA", too...
Maybe a method like
public AlgorithmEnum getAlgorithm(String keyAlgorithm, String hashAlgorithm)
would be better. However, you would have to provide two parameters then.
I'm leaving you an example of how I did on similar cases, you can easily adapt it to your needs:
private static Map<Integer, YourEnum> valuesById = new HashMap<>();
private static Map<String, YourEnum> valuesByCode = new HashMap<>();
static {
Arrays.stream(YourEnum.values()).forEach(value -> valuesById.put(value.reasonId, value));
Arrays.stream(YourEnum.values()).forEach(value -> valuesByCode.put(value.reasonCode, value));
}
public static YourEnum getByReasonId(int endReason) {
return valuesById.get(endReason);
}
Here I have the following classes below. How do I get my wordValidation() method to provide the wordContent to provide output only to the word found and its index.
For sample output using my test program below if I have a consonant word like "BCGAYYY", how do I provide output only to the wrong character in this case A(because A is not a consonat), to get an output like "BCGA" + index?
I have the method wordValidation() below however this provides the whole word and its index...
public abstract class Words {
private String wordDetail;
private String wordContent;
public Words(String wordDetail, String wordContent) throws InvalidWordException{
this.wordContent = wordContent;
this.wordDetail = wordDetail;
wordValidation();
}
public String getWordDetail() {
return this.wordDetail;
}
public String getWordContent() {
return this.wordContent;
}
public abstract String AcceptedCharacters();
public void wordValidation() throws InvalidWordException{
String content = getWordContent();
String theseletters = this.AcceptedCharacters();
for (int i = 0; i < content.length(); i++) {
char c = content.charAt(i);
if (theseletters.indexOf(c) == -1) {
throw new InvalidWordException(content, i);
}
}
}
public String toString(){
return getWordDetail() + getWordContent();
}
Checked Exception
public class InvalidWordException extends Exception {
public InvalidWordException (String wordContent, int theIndex) {
super("Wrong Word" + wordContent + theIndex);
}
}
Concrete Class 1
public class Vowels extends Words {
private String validVowels;
public Vowels(String wordDetail, String wordContent) throws InvalidWordException {
super(wordDetail, wordContent);
}
#Override
public String AcceptedCharacters() {
return validVowels = "AEIOU";
}
public static void main(String[] args) {
try {
Vowels vowel = new Vowels("First Vowel Check" ,"AEIOXAEI");
} catch (InvalidWordException ex) {
System.out.println(ex.getMessage());
}
}
}
concrete class 2
public class Consonants extends Words {
private String validConsonants;
public Consonants(String wordDetail, String wordContent) throws InvalidWordException{
super(wordDetail, wordContent);
}
#Override
public String AcceptedCharacters() {
return validConsonants ="BCDFGHJKLMNPQRSTVXZWY";
}
public static void main(String[] args) {
try {
Consonants consonants = new Consonants("First Consonant Check","BCGAYYY");
} catch (InvalidWordException ex) {
System.out.println(ex.getMessage());
}
}
}
test program
public static void main(String[] args) {
try {
Consonants consonants = new Consonants("First Consonant Check","BCGAYYY");
} catch (InvalidWordException ex) {
System.out.println(ex.getMessage());
}
}
Change throw new InvalidWordException(content, i);
to
throw new InvalidWordException(content.substring(0,i), i);
In Java, String objects are immutable. So you were passing the original content string as is. That's why it is not giving you your desired output.
Eclipse can auto-generate a toString() method from a object's fields. If those fields are objects then they too may have similarly auto-generated toString() methods.
e.g. a President object might look like this:
President [country=USA, name=Name [title=Mr, forename=Barack, surname=Obama], address=Address [houseNumber=1600, street=Pennsylvania Avenue, town=Washington]]
which is easier to read if I format it:
President [
country=USA,
name=Name [
title=Mr,
forename=Barack,
surname=Obama],
address=Address [
houseNumber=1600,
street=Pennsylvania Avenue,
town=Washington]]
What is the best way to parse this String to create a map of maps?
I've got a solution, but it's not pretty. I was hoping to be able to avoid the low level String manipulation somehow, but here it is:
import java.util.LinkedHashMap;
import java.util.Map;
public class MappedObject {
public String className;
public Map<String, String> leafFields = new LinkedHashMap<>();
public Map<String, MappedObject> treeFields = new LinkedHashMap<>();
#Override
public String toString() {
return "[className=" + className
+ (leafFields.isEmpty() ? "" : ", leafFields=" + leafFields)
+ (treeFields.isEmpty() ? "" : ", treeFields=" + treeFields)
+ "]";
}
public static MappedObject createFromString(String s) {
MappedObject mo = new MappedObject();
new Mapper(s).mapObject(mo);
return mo;
}
private static class Mapper {
private String s;
public Mapper(String s) {
this.s = s;
}
private String mapObject(MappedObject mo) {
mo.className = removeFirstNCharacters(s.indexOf(' '));
while (s.contains("=")) {
removeLeadingNonLetters();
String key = removeFirstNCharacters(s.indexOf('='));
removeFirstNCharacters(1); // remove the =
String leafValue = getLeafValue();
if (leafValue != null) {
mo.leafFields.put(key, leafValue);
if (s.startsWith("]")) { // that was the last field in the tree
return s;
}
} else {
MappedObject treeField = new MappedObject();
mo.treeFields.put(key, treeField);
s = new Mapper(s).mapObject(treeField);
}
}
return s; // s contains only close brackets - ]
}
private void removeLeadingNonLetters() {
int i = 0;
while (!Character.isLetter(s.charAt(i))) {
i++;
}
removeFirstNCharacters(i);
}
private String removeFirstNCharacters(int n) {
String value = s.substring(0, n);
s = s.substring(value.length());
return value;
}
private String getLeafValue() {
int endIndex = getEndIndex();
if (!s.contains("[") || s.indexOf('[') > endIndex) {
return removeFirstNCharacters(endIndex);
}
return null;
}
/** The end of the value, if it's a leaf field. */
private int getEndIndex() {
if(s.contains(",")) {
return Math.min(s.indexOf(','), s.indexOf(']'));
}
return s.indexOf(']');
}
}
}
I've got a problem with my programm. When i try to compile following i just receive the message:
Tutorium.java:15: error: <identifier> expected
public void settName(vorlesung.lectureName) {
^
So my Code:
Tutorium.java
public class Tutorium {
private Vorlesung vorlesung;
public String tName;
private int tNumber;
public int gettNumber() {
return this.tNumber;
}
public String gettName() {
return this.tName;
}
public void settName(vorlesung.lectureName) {
this.tName = vorlesung.lectureName;
}
public String toString() {
return (this.tName + ", " + this.tNumber);
}
public Tutorium(int tNumber){
this.tNumber = tNumber; } }
Vorlesung.java
public class Vorlesung {
public String lectureName;
private int lectureNumber;
private int lecture;
private Dozent dozent;
private String lecturerlName;
public String getlectureName(){
return this.lectureName;
}
public int lectureNumber(){
return this.lectureNumber;
}
public int lecture(){
return this.lecture;
}
public String getlecturer(){
this.lecturerlName = dozent.lecturerlName;
return this.lecturerlName;
}
public String toString() {
return (this.lectureName + ", " + this.lectureNumber);
}
public Vorlesung(String lectureName, int lecture) {
this.lectureName = lectureName;
this.lecture = lecture +1;
this.lectureNumber = this.lecture -1;
this.lecturerlName = lecturerlName;
}}
My Main-Method:
public class MainVorlesung {
public static void main(String[] args) {
Student student = new Student("STUDENTNAME", "STUDENTLASTNAME", 178, 1);
Vorlesung vorlesung = new Vorlesung("Programmieren", 13341);
Tutorium tutorium = new Tutorium(3);
Dozent dozent = new Dozent("LECTURERFIRSTNAME", "LECTURERLASTNAME", 815);
System.out.println(student.toString());
System.out.println(vorlesung.toString());
System.out.println(tutorium.toString());
System.out.println(dozent.toString());
}}
My goal is to set the value of tName equal the value of vorlesung.lectureName.
Why can't i do this that way?
I appreciate every help. :)
Thanks
For methods, the arguments that you pass in must have a declared value.
In this case, a String. So you need to change your method to this:
public void settName(String newLectureName) {
this.tName = newLectureName;
}
Read more about what a java method is and how to create one here: http://www.tutorialspoint.com/java/java_methods.htm
Change settName to
public void settName(String name) {
this.tName = name;
}
Since your goal is:
My goal is to set the value of tName equal the value of vorlesung.lectureName.
You should get rid of the setName method entirely since it will depend entirely on the vorlesung field and so should not be changeable. You should also get rid of the tName field, and instead change getName() to:
public class Tutorium {
private Vorlesung vorlesung;
// public String tName; // get rid of
private int tNumber;
public String gettName() {
if (vorlesung != null) {
return vorlesung.getlecturer();
}
return null; // or throw exception
}
// *** get rid of this since you won't be setting names
// public void settName(Vorlesung vorlesung) {
// this.tName = vorlesung.lectureName;
// }
I have just now noticed that your Tutorium class does not have and absolutely needs a setVorlesung(...) method.
public void setVorlesung(Vorlesung vorlesung) {
this.vorlesung = vorlesung;
}
I have to use getters and setters for this code and
actually i'm using two classes to get the result
here is Ndc class:
package java4u.com;
public class Ndc {
private String ndcQUAL;
private String ndcCODE;
private String ndcUNIT;
private String ndcQTY;
String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getndcQUAL() {
if(str.contains("N4"))
{
return "N4";
}
else
{
return "";
}
}
public void setndcQUAL(String getndcQUAL) {
this.ndcQUAL = getndcQUAL;
}
public String getndcCODE() {
if(str.contains("N4")){
int i=str.indexOf("N4");
str=str.substring(i+2,i+13);
return str;
}
else
{
return "";
}
}
public void setndcCODE(String getndcCODE) {
this.ndcCODE = getndcCODE;
}
public String getndcUNIT() {
if(str.contains("N4")) {
str=str.substring(i+13,i+15);
return str;
}else
{
return "";
}
}
public void setndcUNIT(String getndcUNIT) {
this.ndcUNIT = getndcUNIT;
}
public String getndcQTY() {
if(str.contains("N4")) {
do {
int i=str.indexOf(getndcUNIT());
str=str.substring(i,i++);
return str;
} while(str.length()<=35 || str.contains("N4") || str.contains("TPL"));
else
{
return "";
}
}
public void setndcQTY(String getndcQTY) {
this.ndcQTY = getndcQTY;
}
}
here i'm using str variable and the string will be entered during runtime and the condition is if string contains "N4" value then the loop should be continue else return space.
and I have four methods in this program and
getNdcQUAL() method should return "N4" if string contains "N4" value
and getNdcCODE() method should display next 11 digits after the "N4" for this case I shouldn't mention str.substring(2,13)..I should find the position of NdcQUAL and from there to next 11 digits will be print..
and getNdcUNIT() method should display next two bytes qualifier after the 11 digits for this case also I should find the position of NdcCODE and from there to 2 digits
and finally getNdcQTY() method should return the data after the NdcUNIT for this case also I should find the position of NdcUNIT and from there to untill one of the condition is met
here is my main class
package java4u.com;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor.GetterSetterReflection;
public class Test {
public static String getStr(String str)
{
return str;
}
public static void main(String args[]) {
Ndc ndc=new Ndc();
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
try {
System.out.println("enter a string:");
br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
couldn't understand how to pass the string value from Ndc.java to Test.java also couldn't get how to pass other methods from Ndc.java to Test.java
here is the sample output
str=N412345678923UN2345.677
it should return
N4
12345678923
UN
2345.67
please help me!!!!!!
Since you don't have a constructor. You need to manually set the str
If this N412345678923UN2345.677 is the br.readLine(). Then you need to set it in the for your NDC object
String str = br.readLine();
ndc.setStr(str); // now the str is set in your ndc object.
System.out.println(ndc.getndcCODE());
System.out.println(ndc.getndcUNIT());
System.out.println(ndc.getndcCQTY());
You should first pass the string like this :
ndc.setndcQUAL(yourString);
then get the required value :
System.out.print(ndc.getndcQUAL());
Your approach has one major flaw - you need to execute the methods in a predefined order, else it will extract wrong data. You can however use your setStr(String str) method to initialize all proper fields and then just use your getter methods to return the values you've set within your setStr(...) method:
public class Ndc
{
private String ndcQUAL;
private String ndcCODE;
private String ndcUNIT;
private String ndcQTY;
public void setStr(String str)
{
int pos = 0;
if (str.contains("N4"))
{
pos = str.indexOf("N4");
this.ndcQUAL = str.substring(pos, pos+=2);
this.ndcCODE = str.substring(pos, pos+=11);
this.ndcUNIT = str.substring(pos, pos+=2);
String data = str.substring(pos);
// trim the data at the end corresponding to the provided class logic
int p = data.length();
if (data.contains("N4"))
{
p = data.indexOf("N4");
}
else if (data.contains("TLP"))
{
p = data.indexOf("TLP");
}
if (p > 35)
p = 35;
this.ndcQTY = data.substring(0, p);
}
else
this.ndcQUAL = "";
}
public String getndcQUAL()
{
return this.ndcQUAL;
}
public String getndcCODE()
{
return this.ndcCODE;
}
public String getndcUNIT()
{
return this.ndcUNIT;
}
public String getndcQTY()
{
return this.ndcQTY;
}
}
To break the loop if no valid N4 string was entered, you first have to define a kind of loop first and check the getndcQUAL() return value if it equals N4 after you've assigned the input string to setStr(...):
public class Test
{
public static void main(String args[])
{
Ndc ndc=new Ndc();
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
try
{
do
{
System.out.println("enter a string:");
ndc.setStr(br.readLine());
System.out.println("QUAL: "+ndc.getndcQUAL());
System.out.println("CODE: "+ndc.getndcCODE());
System.out.println("UNIT: "+ndc.getndcUNIT());
System.out.println("QTY: "+ndc.getndcQTY());
}
while("N4".equals(ndc.getndcQUAL()));
}
catch (IOException e)
{
e.printStackTrace();
}
}
}