I want to parse a string in order to get the value of an attribute.For example i have the following String:
calling_number=+385317KFWVM, call_direction=I, conversation_duration=29,
Each attribute and its value is separated by commas.I have declared the name and the type of each attribute in a class named MessageBean.
public static void main(String[] args){
try {
MessageBean attributes_bean = MessageBean.parse("calling_number=+385317KFWVM, call_direction=I, conversation_duration=29,");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public class MessageBean {
private String calling_number;
private String call_direction;
private int conversation_duration;
public static MessageBean parse(String line) throws UnsupportedEncodingException {
MessageBean bean = new MessageBean();
line = URLDecoder.decode(line, "utf-8");
bean.setCalling_number(MessageBean.getParameter(line, "calling_number"));
bean.setCall_direction(MessageBean.getParameter(line, "call_direction"));
bean.setConversation_duration(Integer.parseInt(MessageBean.getParameter(line, "conversation_duration")));
return bean;
}
private static String getParameter(String line, String name) {
String value = "";
Pattern p = Pattern.compile(name + "=([^,]*),");
Matcher m = p.matcher(line);
if (m.find()) {
value = m.group(1);
}
return value;
}
}
I expect my result to be +385317KFWVM, I, 29 .
Instead i get 385317KFWVM, I, 29 which means that i miss the + sign.I understand that there is a problem with my regular expression.I have tried everything like \+ but i still don't get the right results.Any help?
When you run URLDecoder.decode(line, "utf-8") the + is removed from your string.
Related
I am trying to open a csv file using openCSV, iterate over every column and if the userID is different write a new JavaBean pair at the end of the file.
The problem is that the reader only checks the first column of my file and not the whole file. While created, the file contains only a header and nothing else. The program will check every column and if the sudoID is different it will write it to the file. If the sudoID in the first line is equal to the the one imported from my main class it will recognise it and not write it. But if this -same- sudoID is in the second row it will not recognise it and will write it again.
For instance, if my CSV looks like this it will work:
"Patient_id Pseudo_ID",
"32415","PAT106663926"
If it looks like this it will re-write the sudoID:
"Patient_id Pseudo_ID",
"32416","PAT104958880"
"32415","PAT106663926"
Thanks!
My Code:
public class CSVConnection {
#SuppressWarnings({ "deprecation", "resource", "rawtypes", "unchecked" })
public String getID(String sID,String pseudoID) throws IOException, CsvDataTypeMismatchException, CsvRequiredFieldEmptyException{
try {
CsvToBean csv = new CsvToBean();
String csvFilename = "CsvFile.csv";
Writer writer= new FileWriter(csvFilename,true);
CSVReader csvReader = new CSVReader(new FileReader(csvFilename),',','"',1);
ColumnPositionMappingStrategy strategy = new ColumnPositionMappingStrategy();
strategy.setType(PatientCSV.class);
String[] columns = new String[] {"patID","pseudoID"};
strategy.setColumnMapping(columns);
//Set column mapping strategy
StatefulBeanToCsv<PatientCSV> bc = new StatefulBeanToCsvBuilder<PatientCSV>(writer).withMappingStrategy(strategy).build();
List patList = csv.parse(strategy, csvReader);
for (Object patObj : patList) {
PatientCSV pat = (PatientCSV) patObj;
if(((PatientCSV) patObj).getPatID().equals(sID)){
return pat.getPseudoID();
}
else
{
PatientCSV pat1 = new PatientCSV();
pat1.setPatID(sID);
pat1.setPseudoID(pseudoID);
patList.add(pat1);
/*Find a way to import it to the CSV*/
bc.write(pat1);
writer.close();
return pseudoID;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void main(String [] args) throws IOException, CsvDataTypeMismatchException, CsvRequiredFieldEmptyException{
CSVConnection obj = new CSVConnection();
String sID="32415";
String pseudoID="PAT101830150";
obj.getID(sID,pseudoID);
}
}
and the Java Bean :
public class PatientCSV {
private String patID;
private String pseudoID;
public String getPatID() {
return patID;
}
public void setPatID(String patID) {
this.patID = patID;
}
public String getPseudoID() {
return pseudoID;
}
public void setPseudoID(String pseudoID) {
this.pseudoID = pseudoID;
}
public PatientCSV(String patID, String pseudoID) {
super();
this.patID = patID;
this.pseudoID = pseudoID;
}
public PatientCSV() {
super();
// TODO Auto-generated constructor stub
}
public String toString()
{
return "Patient [id=" + patID + ", pseudoID=" + pseudoID + "]";
}
}
Lets inspect your for loop
for (Object patObj : patList) {
PatientCSV pat = (PatientCSV) patObj;
if(((PatientCSV) patObj).getPatID().equals(sID)){
return pat.getPseudoID();
}
else
{
PatientCSV pat1 = new PatientCSV();
pat1.setPatID(sID);
pat1.setPseudoID(pseudoID);
patList.add(pat1);
/*Find a way to import it to the CSV*/
bc.write(pat1);
writer.close();
return pseudoID;
}
}
So in the case you mention it is not working as expected, meaning that the line that matches your input is the second line:
"Patient_id Pseudo_ID",
"32416","PAT104958880"
"32415","PAT106663926"
So you call: getID("32415", "PAT106663926")
What happens in your loop is:
You take the first element of your csv patients, the one with id: 32416,
check if it matches with the id given as input to your method, 32415.
It does not match so it goes to the else part. There it creates the new patient (with the same patID and pseudoID as the 2nd row of your csv) and stores it in the file.
So by now you should have 2 entries in your csv with the same data "32415","PAT106663926".
I think that this is the error, in your for loop you should check against all entries if there is a match, and then create the patient and store it to the csv.
An example:
PatientCSV foundPatient = null;
for (Object patObj : patList) {
PatientCSV pat = (PatientCSV) patObj;
if(((PatientCSV) patObj).getPatID().equals(sID)){
foundPatient = pat;
}
}
if (foundPatient == null) {
foundPatient = new PatientCSV();
foundPatient.setPatID(sID);
foundPatient.setPseudoID(pseudoID);
patList.add(foundPatient);
/*Find a way to import it to the CSV*/
bc.write(foundPatient);
writer.close();
}
return foundPatient.getPseudoID();
P.S. The above example is written very quickly, just to give you the idea what needs to be done.
I want to make a class in Java called URLTransformer.
Let's say I have a blog entry and want to format my text (e.g. because some words are in Swedish).
This is my code right now:
public class URLTransformer {
public static void main(String[] args) {
String basurl = "http://www.mybloggsys.com/user_abc/";
String[] rubriker = {
"Nu Kommer Vintern till aland",
"Onskningar ar nagot man vill uppna",
"Just English Letters"
};
for (String rubrik : rubriker) {
String rubrik2=rubrik.toLowerCase().replace(" ", "_").replace("Å", "a").replace("å", "a").replace("ä", "a").replace("Ö", "o");
URLTransformer transformer = new URLTransformer();
URLTransformer(basurl, rubrik2);
String url = transformer.getURL();
String aElement = transformer.getAElement();
System.out.println(rubrik2);
System.out.println(url);
System.out.println(aElement);
}
URLTransformer transformer = new URLTransformer();
}
private String getAElement() {
// TODO Auto-generated method stub
return null;
}
private String getURL() {
// TODO Auto-generated method stub
return null;
}
private static void URLTransformer(String basurl, String rubrik2) {
// TODO Auto-generated method stub
}
}
Now, I can get Eclipse to execute this code but I get a lot of "Null" messages. Is it possible to not get it or does it even matter after compiling my code? In my homework task, the final code should look exactly like this:
Nu kommer Vinter till Åland
http://www.mybloggsys.com/user_abc/nu_kommer_vintern_till_aland
Nu Kommer Vintern till Åland
Önskningar är något man vill uppnå
(url link)/onskningar_ar_nagot_man_vill_uppna
Önskningar är något man vill uppnå
Just English Letters
(url link)/just_english_letters
Just English Letters
Any help will be greatly appreciated, it feels like it almost works just this </a> element thing and null messages that are left.
Here is the code for you:
public class URLTransformer {
private String baseurl;
private String baseString;
// Constructor of the class that uses a base url and a base string
public URLTransformer(String baseurl, String baseString) {
super();
this.baseurl = baseurl;
this.baseString = baseString;
}
// Method that return the href calculated
private String getHref() {
// transform the string to remove non english characters with _ instead of spaces
return baseurl + baseString.toLowerCase().replace(" ", "_").replace("Å", "a").replace("å", "a").replace("ä", "a").replace("Ö", "o");
}
// return a <a> link with a call to the href link method
private String getAElement() {
StringBuilder aElement = new StringBuilder();
aElement.append("<a href=\"");
aElement.append(getHref());
aElement.append("\">");
aElement.append(baseString);
aElement.append("</a>");
return aElement.toString();
}
public static void main(String[] args) {
String basurl = "http://www.mybloggsys.com/user_abc/";
String[] rubriker = { "Nu Kommer Vintern till aland", "Onskningar ar nagot man vill uppna", "Just English Letters" };
// iterate over the
for (String rubrik : rubriker) {
URLTransformer transformer = new URLTransformer(basurl, rubrik); // creation of the class object that is able to make a link from the string
System.out.println(rubrik); // prints the provided string
System.out.println(transformer.getHref()); // use of the getHref method to get an url from the string
System.out.println(transformer.getAElement()); // display of the <a> element
}
}
}
Note : I've added comments to the code and see my comment below to have explanations on what was wrong with the provided code.
Has anyone an idea about what is wrong with my attempt to call a method from a C# dll in my Java code?
Here is my example:
Java code:
public class CsDllHandler {
public interface IKeywordRun extends Library {
public String KeywordRun(String action, String xpath, String inputData,
String verifyData);
}
private static IKeywordRun jnaInstance = null;
public void runDllMethod(String action, String xpath, String inputData,
String verifyData) {
NativeLibrary.addSearchPath(${projectDllName},
"${projectPath}/bin/x64/Debug");
jnaInstance = (IKeywordRun) Native.loadLibrary(
${projectDllName}, IKeywordRun.class);
String csResult = jnaInstance.KeywordRun(action, xpath, inputData,
verifyData);
System.out.println(csResult);
}
}
And in C#:
[RGiesecke.DllExport.DllExport]
public static string KeywordRun(string action, string xpath, string inputData, string verifyData) {
return "C# here";
}
The Unmanaged Exports nuget should be enough for me to call this method (in theory) but I have some strange error:
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokePointer(Native Method)
at com.sun.jna.Function.invokePointer(Function.java:470)
at com.sun.jna.Function.invokeString(Function.java:651)
at com.sun.jna.Function.invoke(Function.java:395)
at com.sun.jna.Function.invoke(Function.java:315)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy0.KeywordRun(Unknown Source)
at auto.test.keywords.utils.CsDllHandler.runDllMethod(CsDllHandler.java:34)
at auto.test.keywords.runner.MainClass.main(MainClass.java:24)
Well, after another day of research and "trial and error" I have found the cause of my problem and a solution.
The cause was that my C# dll had a dependency on log4net.dll. For running a static method from a standalone C# dll the code from the question is all you need.
The solution for using C# dll with dependencies is to create another dll with no dependency and to load the original dll in this adapter with reflection. In Java you should load the adapter dll with jna and call any exported method. I was able not only to execute methods from the adapter but also to configure log4net with reflection and Java
Here is my code:
(C#)
public class CSharpDllHandler {
private static Logger log = Logger.getLogger(CSharpDllHandler.class);
public interface IFrameworkAdapter extends Library {
public String runKeyword(String action, String xpath, String inputData,
String verifyData);
public String configureLog4net(String log4netConfigPath);
public String loadAssemblies(String frameworkDllPath,
String log4netDllPath);
}
private static IFrameworkAdapter jnaAdapterInstance = null;
private String jnaSearchPath = null;
public CSharpDllHandler(String searchPath) {
this.jnaSearchPath = searchPath;
// add to JNA search path
System.setProperty("jna.library.path", jnaSearchPath);
// load attempt
jnaAdapterInstance = (IFrameworkAdapter) Native.loadLibrary(
"FrameworkAdapter", IFrameworkAdapter.class);
}
public String loadAssemblies(String frameworkDllPath, String log4netDllPath) {
String csResult = jnaAdapterInstance.loadAssemblies(frameworkDllPath,
log4netDllPath);
log.debug(csResult);
return csResult;
}
public String runKeyword(String action, String xpath, String inputData,
String verifyData) {
String csResult = jnaAdapterInstance.runKeyword(action, xpath,
inputData, verifyData);
log.debug(csResult);
return csResult;
}
public String configureLogging(String log4netConfigPath) {
String csResult = jnaAdapterInstance
.configureLog4net(log4netConfigPath);
log.debug(csResult);
return csResult;
}
public String getJnaSearchPath() {
return jnaSearchPath;
}
}
In the main method just use something like this:
CSharpDllHandler dllHandler = new CSharpDllHandler(
${yourFrameworkAdapterDllLocation});
dllHandler.loadAssemblies(
${yourOriginalDllPath},${pathToTheUsedLog4netDllFile});
dllHandler.configureLogging(${log4net.config file path});
dllHandler.runKeyword("JAVA Action", "JAVA Xpath", "JAVA INPUT",
"JAVA VERIFY");
dllHandler.runKeyword("JAVA Action2", "JAVA Xpath2", "JAVA INPUT2",
"JAVA VERIFY2");
In C# I have the desired methods on the original dll:
public static string KeywordRun(string action, string xpath, string inputData, string verifyData) {
log.Debug("Action = " + action);
log.Debug("Xpath = " + xpath);
log.Debug("InputData = " + inputData);
log.Debug("VerifyData = " + verifyData);
return "C# UserActions result: "+ action+" "+xpath+" "+inputData+" "+verifyData;
}
and all the magic is in the DLL Adapter:
namespace FrameworkAdapter {
[ComVisible(true)]
public class FwAdapter {
private const String OK="OK";
private const String frameworkEntryClassName = "${nameOfTheDllClass with method to run }";
private const String log4netConfiguratorClassName = "log4net.Config.XmlConfigurator";
private static Assembly frameworkDll = null;
private static Type frameworkEntryClass = null;
private static MethodInfo keywordRunMethod = null;
private static Assembly logDll = null;
private static Type logEntryClass = null;
private static MethodInfo logConfigureMethod = null;
private static String errorMessage = "OK";
[RGiesecke.DllExport.DllExport]
public static string loadAssemblies(string frameworkDllPath, string log4netDllPath) {
try {
errorMessage = LoadFrameworkDll(frameworkDllPath, frameworkEntryClassName);
LoadFrameworkMethods("KeywordRun", "Setup", "TearDown");
errorMessage = LoadLogAssembly(log4netDllPath, log4netConfiguratorClassName);
if (errorMessage.CompareTo(OK) == 0)
errorMessage = LoadLogMethods("Configure");
}
catch (Exception e) {
return e.Message;
}
return errorMessage;
}
[RGiesecke.DllExport.DllExport]
public static string configureLog4net(string log4netConfigPath) {
if (errorMessage.CompareTo("OK") == 0) {
StringBuilder sb = new StringBuilder();
sb.AppendLine("Try to configure Log4Net");
try {
FileInfo logConfig = new FileInfo(log4netConfigPath);
logConfigureMethod.Invoke(null, new object[] { logConfig });
sb.AppendLine("Log4Net configured");
}
catch (Exception e) {
sb.AppendLine(e.InnerException.Message);
}
return sb.ToString();
}
return errorMessage;
}
[RGiesecke.DllExport.DllExport]
public static string runKeyword(string action, string xpath, string inputData, string verifyData) {
StringBuilder sb = new StringBuilder();
object result = null;
try {
result = keywordRunMethod.Invoke(null, new object[] { action, xpath, inputData, verifyData });
sb.AppendLine(result.ToString());
}
catch (Exception e) {
sb.AppendLine(e.InnerException.Message);
}
return sb.ToString();
}
private static String LoadFrameworkDll(String dllFolderPath, String entryClassName) {
try {
frameworkDll = Assembly.LoadFrom(dllFolderPath);
Type[] dllTypes = frameworkDll.GetExportedTypes();
foreach (Type t in dllTypes)
if (t.FullName.Equals(entryClassName)) {
frameworkEntryClass = t;
break;
}
}
catch (Exception e) {
return e.InnerException.Message;
}
return OK;
}
private static String LoadLogAssembly(String dllFolderPath, String entryClassName) {
try {
logDll = Assembly.LoadFrom(dllFolderPath);
Type[] dllTypes = logDll.GetExportedTypes();
foreach (Type t in dllTypes)
if (t.FullName.Equals(entryClassName)) {
logEntryClass = t;
break;
}
}
catch (Exception e) {
return e.InnerException.Message;
}
return OK;
}
private static String LoadLogMethods(String logMethodName) {
try {
logConfigureMethod = logEntryClass.GetMethod(logMethodName, new Type[] { typeof(FileInfo) });
}
catch (Exception e) {
return e.Message;
}
return OK;
}
private static void LoadFrameworkMethods(String keywordRunName, String scenarioSetupName, String scenarioTearDownName) {
///TODO load the rest of the desired methods here
keywordRunMethod = frameworkEntryClass.GetMethod(keywordRunName);
}
}
}
Running this code will provide all the logged messages from the original C# DLL to the Java console output (and to a file if configured). In a similar way, we can load any other needed dll files for runtime.
Please forgive my [very probable wrong] way of doing things in C# with reflection, I'm new to this language.
my tsv file contains :
tax_id GeneID Symbol
9606 1 A1BG
TsvReader.java
private static CellProcessor[] getProcessors() {
final CellProcessor[] processors = new CellProcessor[] {
new NotNull(), // tax_id
new NotNull(), // GeneID
new NotNull(), // Symbol
};
return processors;
}
private static void readCsvBeanReader() throws Exception {
ICsvBeanReader beanReader = null;
try {
beanReader = new CsvBeanReader(new FileReader(CSV_FILENAME),
CsvPreference.TAB_PREFERENCE);
// the header elements are used to map the values to the bean (names
// must match)
final String[] header = beanReader.getHeader(true);
final CellProcessor[] processors = getProcessors();
TsvEntities tsv_ent;
while ((tsv_ent = beanReader.read(TsvEntities.class, header,
processors)) != null) {
System.out.println(String.format("tsv_ent=%s",tsv_ent));
}
} finally {
if (beanReader != null) {
beanReader.close();
}
}
}
TsvEntities.java
package com.tsvreader;
public class TsvEntities {
private Integer tax_id;
private Integer GeneID;
private String Symbol;
public TsvEntities() {
}
public TsvEntities(final Integer tax_id, final Integer GeneID, final String Symbol){
this.tax_id = tax_id;
this.GeneID= GeneID;
this.Symbol=Symbol;
}
public Integer getTax_id() {
return tax_id;
}
public void setTax_id(Integer tax_id) {
this.tax_id = tax_id;
}
public Integer getGeneID() {
return GeneID;
}
public void setGeneID(Integer geneID) {
this.GeneID = geneID;
}
public String getSymbol() {
return Symbol;
}
public void setSymbol(String symbol) {
this.Symbol = symbol;
}
#Override
public String toString() {
return String
.format("TsvEntities [tax_id=%s, GeneID=%s, Symbol=%s]",getTax_id(), getGeneID(), getSymbol());
}
EXception :
Exception in thread "main" org.supercsv.exception.SuperCsvReflectionException: unable to find method setTax_id GeneID Symbol(java.lang.String) in class com.tsvreader.TsvEntities - check that the corresponding nameMapping element matches the field name in the bean, and the cell processor returns a type compatible with the field
context=null
at org.supercsv.util.ReflectionUtils.findSetter(ReflectionUtils.java:183)
at org.supercsv.util.MethodCache.getSetMethod(MethodCache.java:95)
at org.supercsv.io.CsvBeanReader.populateBean(CsvBeanReader.java:158)
at org.supercsv.io.CsvBeanReader.read(CsvBeanReader.java:207)
at com.tsvreader.TsvReader.readCsvBeanReader(TsvReader.java:59)
at com.tsvreader.TsvReader.main(TsvReader.java:17)
From a first glance I would say that your problem is that public void setTax_id(Integer tax_id) takes one Integer parameter but SuperCsv expects it to take a String. You should provide a setTax_id method that takes a String. The same should also be true for setGeneID.
Edit:
The first part was incorrect. Seems like the header of your file is not parsed correctly. SuperCsv interprets the whole line as the method name. Check that the first line correctly separated.
(From your question it seems that the first line is separated by spaces rather than tabs.)
I'm using java.util.resourcebundle to format my JSTL messages and this works fine:
I use the class MessageFormat you can see here. Now I want to encapsulate this to a method that is just getParametrizedMessage(String key, String[]parameters) but I'm not sure how to do it. Now there is quite a lot of work to display just one or two messages with parameters:
UserMessage um = null;
ResourceBundle messages = ResourceBundle.getBundle("messages");
String str = messages.getString("PF1");
Object[] messageArguments = new String[]{nyreg.getNummer()};
MessageFormat formatter = new MessageFormat("");
formatter.applyPattern(messages.getString("PI14"));
String outputPI14 = formatter.format(messageArguments);
formatter.applyPattern(messages.getString("PI15"));
String outputPI15 = formatter.format(messageArguments)
if(ipeaSisFlag)
if(checkIfPCTExistInDB && nyreg.isExistInDB()) {
//um = new ExtendedUserMessage(MessageHandler.getParameterizedMessage("PI15", new String[]{nyreg.getNummer()}) , UserMessage.TYPE_INFORMATION, "Info");
um = new ExtendedUserMessage(outputPI15 , UserMessage.TYPE_INFORMATION, "Info");
…and so on. Now can I move this logic to a static class MessageHandler.getParameterizedMessage that now is not working and looking like this:
private final static String dictionaryFileName="messages.properties";
public static String getParameterizedMessage(String key, String [] params){
if (dictionary==null){
loadDictionary();
}
return getParameterizedMessage(dictionary,key,params);
}
private static void loadDictionary(){
String fileName = dictionaryFileName;
try {
dictionary=new Properties();
InputStream fileInput = MessageHandler.class.getClassLoader().getResourceAsStream(fileName);
dictionary.load(fileInput);
fileInput.close();
}
catch(Exception e) {
System.err.println("Exception reading propertiesfile in init "+e);
e.printStackTrace();
dictionary=null;
}
}
How can I make using my parametrized messages as easy as calling a method with key and parameter?
Thanks for any help
Update
The logic comes from an inherited method that in in the abstract class that this extends. The method looks like:
protected static String getParameterizedMessage(Properties dictionary,String key,String []params){
if (dictionary==null){
return "ERROR";
}
String msg = dictionary.getProperty(key);
if (msg==null){
return "?!Meddelande " +key + " saknas!?";
}
if (params==null){
return msg;
}
StringBuffer buff = new StringBuffer(msg);
for (int i=0;i<params.length;i++){
String placeHolder = "<<"+(i+1)+">>";
if (buff.indexOf(placeHolder)!=-1){
replace(buff,placeHolder,params[i]);
}
else {
remove(buff,placeHolder);
}
}
return buff.toString();
}
I think I must rewrite the above method in order to make it work like a resourcebundle rather than just a dictionary.
Update 2
The code that seems to work is here
public static String getParameterizedMessage(String key, Object [] params){
ResourceBundle messages = ResourceBundle.getBundle("messages");
MessageFormat formatter = new MessageFormat("");
formatter.applyPattern(messages.getString(key));
return formatter.format(params);
}
I'm not really sure what you're trying to achive, here's what I did in the past:
public static final String localize(final Locale locale, final String key, final Object... param) {
final String name = "message";
final ResourceBundle rb;
/* Resource bundles are cached internally,
never saw a need to implement another caching level
*/
try {
rb = ResourceBundle.getBundle(name, locale, Thread.currentThread()
.getContextClassLoader());
} catch (MissingResourceException e) {
throw new RuntimeException("Bundle not found:" + name);
}
String keyValue = null;
try {
keyValue = rb.getString(key);
} catch (MissingResourceException e) {
// LOG.severe("Key not found: " + key);
keyValue = "???" + key + "???";
}
/* Message formating is expensive, try to avoid it */
if (param != null && param.length > 0) {
return MessageFormat.format(keyValue, param);
} else {
return keyValue;
}
}