Not sure if the title makes sense, but I am trying to return a Success message from a class that receives a linkedhashmap, however eclipse is giving me error when I try to compile the files, offering
Remove arguments to match 'logFile()'
Create constructor 'logFile(Map<String, String>)'
How do set it up to send a Map and revieve a String?
thx
Art
Code corrected as per #Jeff Storey below with error suppression for eclipse
calling class
eventLog.put(stringA,stringB);
logFile logStuff = new logFile();
successRtn = logFile.Process(eventLog);
// Do Stuff with SuccessRtn
logFile class
public class logFile {
static String Success = "Fail";
public static String Process(Map<String, String> eventlog){
// Do Stuff
Success = "Yeh!"
return Success;
}
public static void main(String[] args){
#SuppressWarnings("static-access")
String result = new logFile().Procces(eventLog);
System.out.println("result = " + result);
}
The main method is a special method whose signature must public static void main(String[] args) when being used as an entry point to your application. Create a second method that does the actual work, like this:
public class LogFile {
public String process(Map<String,String> eventLog) {
// do stuff
return success;
}
public void main(String[] args) {
// eventLog will probably be read from a filepath passed into the args
String result = new LogFile().process(eventLog);
System.out.println("result = " + result);
}
}
Note that a lot of your naming conventions are also non standard. Classes should begin with a capital letter and variables should begin with a lower case.
Related
I need to configure some attribute in ScriptEngine- or ScriptContext-level, to be used in Java methods.
So, how to get a reference to that ScriptContext in order to retrieve the value?
Example: setting the attribute:
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.getContext().setAttribute("param1", "paramValue", ScriptContext.ENGINE_SCOPE);
engine.put("MyWindow", engine.eval("Java.type(\"" + MyWindow.class.getName() + "\")"));
engine.eval("print(new MyWindow().test());");
}
MyWindow implementation: how to get that attribute?
public class MyWindow {
public String test() {
// how to get 'param1' value here
return "in test";
}
}
Pass it in:
engine.eval("print(new MyWindow().test(param1));");
// ^^^^^^
// vvvvvvvvvvvvv
public String test(String param1) {
// how to get 'param1' value here
return "in test";
}
Update
If you have code with a call stack like javaMethod1 -> JavaScript -> javaMethod2, and you want a value from javaMethod1 to be available to javaMethod2, without changing the JavaScript to pass it on, use a ThreadLocal.
Since your code is in main you could just use a static directly, but I'm assuming your context is more complex. The code below works even in multi-threaded contexts. The ThreadLocal can be stored anywhere, it just has to be static and available to both java methods.
public static void main(String[] args) throws Exception {
MyWindow.param1.set("paramValue");
try {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval("var MyWindow = Java.type(\"" + MyWindow.class.getName() + "\");" +
"print(new MyWindow().test());");
} finally {
MyWindow.param1.remove();
}
}
public class MyWindow {
public static final ThreadLocal<String> param1 = new ThreadLocal<>();
public String test() {
String value = param1.get();
return "in test: param1 = " + value;
}
}
Here is a small sample:
public class LocalClassSample {
public static void main(String[] args) {
class Utils {
public void printHello(String name) {
System.out.println("Hello " + name);
}
public String outHello(String name) {
return "hello " + name;
}
}
Utils util = new Utils();
util.printHello("World");
}
}
I put a break point at the last line. I am able to view util in the Variables window...
I try to view the same variable in the expressions window...it is unable to evaluate:
Update:
Even tried inspecting the variable in the Display View...it does not evaluate:
Expression eval a java expression like 'util.printHello("World")'
and return the result ("Hello World"). 'util' is not an 'expression' but just a variable name, if you want to inspect it, use the Variables view or the Inspect command.
Given the following code:-
//setup code and import statements, including:
private static String baseURL = Environment.getTestWebsiteURL();
public static String articleOneName = ArticleCreationTest.getArticleOneName();
public static String articleTwoName = ArticleCreationTest.getArticleTwoName();
public static String articleThreeName = ArticleCreationTest.getArticleThreeName();
public static String articleOnePath = ArticleCreationTest.getArticleOnePath();
public static String articleTwoPath = ArticleCreationTest.getArticleTwoPath();
public static String articleThreePath = ArticleCreationTest.getArticleThreePath();
public static String[] articlesPathArray = {articleOnePath, articleTwoPath, articleThreePath}
#BeforeClass
public static void setup() {
driver = Driver.getURL();
for (String s : articlesArray) {
if (s == null) {
//tell me which articles could not be found
System.out.println("Could not find an article for: " + s + " , perhaps it wasn't created in the prior test");
} else {
//assuming array holds some path values, append to the baseURL
driver.get(baseURL + s);
}
}
#Test...
//run some test assertions against the baseURL + path website page that is returned
I need the code to loop through wherever the path variable holds a value and run tests. The current solution is not helpful wherever the prior ArticleCreationTest fails to generate the article, because the variable simply contains null. So the text is: "Could not find an article for: null, perhaps it wasn't created in the prior test".
What I really need is to associate the articleName with the articlePath so the message is something like: "Could not find ArticleOne: perhaps is wasn't created", and then run the tests against all that were created. Perhaps some kind of hashmap or 2D array?
Based on the code given,
public static String articleOneName = ArticleCreationTest.getArticleOneName();
public static String articleTwoName = ArticleCreationTest.getArticleTwoName();
public static String articleThreeName = ArticleCreationTest.getArticleThreeName();
public static String articleOnePath = ArticleCreationTest.getArticleOnePath();
public static String articleTwoPath = ArticleCreationTest.getArticleTwoPath();
public static String articleThreePath = ArticleCreationTest.getArticleThreePath();
public static String[] articlesPathArray = {articleOnePath, articleTwoPath, articleThreePath}
It seems like, it is a list of articleNames and articlePaths
List<String> acticleNames = new ArrayList<String>();
List<String> acticlePaths = new ArrayList<String>();
The List will contain the Strings to be checked, which can be used for the tests.
I need the code to loop through wherever the path variable holds a
value and run tests
You can check this condition by checking if (s != null), currently you are checking for
if (s == null)
how do I get the read txt file into the main class?
//main class
public class mainClass {
public static void main(String[]args) {
load method = new load("Monster");
}
}
//scanner class
public class load {
public static void loader(String... aArgs) throws FileNotFoundException {
load parser = new load("resources/monsters/human/humanSerf.txt");
parser.processLineByLine();
log("Done.");
}
public load(String aFileName){
fFile = new File(aFileName);
}
public final void processLineByLine() throws FileNotFoundException {
//Note that FileReader is used, not File, since File is not Closeable
Scanner scanner = new Scanner(new FileReader(fFile));
try {
//first use a Scanner to get each line
while ( scanner.hasNextLine() ){
processLine( scanner.nextLine() );
}
}
finally {
scanner.close();
}
}
public void processLine(String aLine){
//use a second Scanner to parse the content of each line
Scanner scanner = new Scanner(aLine);
scanner.useDelimiter("=");
if ( scanner.hasNext() ){
String name = scanner.next();
String value = scanner.next();
log("Stat is : " + quote(name.trim()) + ", and the value is : " + quote(value.trim()) );
}
else {
log("Empty or invalid line. Unable to process.");
}
}
public final File fFile;
public static void log(Object aObject){
System.out.println(String.valueOf(aObject));
}
public String quote(String aText){
String QUOTE = "'";
return QUOTE + aText + QUOTE;
}
}
Which method do I call from the main class and what variables do I return from that method if I want the text from the file. If anyone has a website that can help me learn scanner(got this source code of the internet and only sort of understand it from JavaPractises and the sun tutorials) that would be great. thanks
First, you probably want to follow standard Java naming conventions - use public class MainClass instead of mainClass.
Second, for your methods, the public has a specific purpose. See here and here. You generally want to label methods as public only as necessary (in jargon, this is known as encapsulation).
For your question - in the Load class, you can append all the text from the file to a String, and add a public getter method in Load which will return that when called.
Add this at the start of Load:
public class Load {
private String fileText;
// ... rest of class
And add this getter method to the Load class. Yes, you could simply mark fileText as public, but that defeats the purpose of Object-Oriented Programming.
public getFileText(String aFileName){
return fileText;
}
Finally, use this new method for log. Note that there is no need to use Object.
private static void log(String line) {
System.out.println(line);
fileText += aObject;
}
You can now get the read file into the main class by calling method.getFileText()
Code was TL;DR
If you want to get all of the data from the load class's .txt file, then you need to write a method in load to get the lines. Something like this would work:
public String[] getFileAsArray() {
ArrayList<String> lines = new ArrayList<String>();
Scanner in = new Scanner(fFile);
while(in.hasNextLine())
lines.add(in.nextLine();
String[] retArr = new String[lines.size()];
return lines.toArray(retArr);
}
I am creating a helper class in parsing XML elements, so the developer do not need to know the exact name and capitalization of the XML fields.
private static class TagNames{
public static String RESOURCE_ID = "ResourceId";
public static String RESOURCE_NAME = "ResourceName";
public static String RESOURCE_PRICE = "ResourcePrice";
}
This makes it easier to do things like:
someXMLParser.getValueByTagName(TagNames.RESOURCE_ID);
My question is this. If I want to iterate over all the fields declared in class TagNames, how do I do that? Pseudocode:
For tag in TagNames:
someXMLParser.getValueByTagName(tag)
I know I will probably have to restructure all of this. But I can't figure out a way to make the names easily accessible as well as iterable, without any duplication.
Any suggestions?
You're literally asking for a solution based on reflection, but I think a Java Enum may be a better choice in this case. Building on Frederick's example:
public class EnumTest {
public enum Tags {
RESOURCE_ID("ResourceId"),
REOURCE_NAME("ResourceName"),
RESOURCE_PRICE("ResourcePrice");
private final String tagName;
Tags(String tagName) {
this.tagName = tagName;
}
public String getTagName() {
return tagName;
}
}
public static void main(String[] args) {
for(Tags tag : Tags.values()) {
System.out.println("const:" + tag.name()
+ " tagName:" + tag.getTagName());
}
// API user might do e.g.:
// document.getValueForTag(Tags.REOURCE_NAME);
}
}
Although I agree that you should probably use enums or ResourceBundles, here's a solution to your actual question. A method that generates a Map name -> value from all public constants in a given class (the only thing that's missing should be try / catch or throws)
public static Map<String, Object> getConstantValues(Class<?> clazz){
Map<String, Object> constantValues = new LinkedHashMap<String, Object>();
for(Field field : clazz.getDeclaredFields()){
int modifiers = field.getModifiers();
if(Modifiers.isPublic(mod)
&& Modifiers.isStatic(mod) && Modifiers.isFinal(mod)){
constantValues.put(field.getName(), field.get(null));
}
}
return constantValues;
}
You may want to consider using a ResourceBundle instead of a class to store the tag names. May require a little bit of reworking of your code but it will be easier to produce a list of tags compared to what you are doing now, and adding a new tag won't require much work other then adding a line to the properties file.
You can do this quite easily using enum and an accompanying array:
public class Main {
public enum TagName { RESOURCE_ID, REOURCE_NAME, RESOURCE_PRICE }
private static String[] tags = {"ResourceID", "ResourceName", "ResourcePrice"};
public static String getValueByTagName(TagName tag) {
return tags[tag.ordinal()];
}
public static void main(String[] args) {
System.out.println("Calling by getValueByTagName:");
System.out.println(getValueByTagName(TagName.RESOURCE_ID));
System.out.println("Calling TagName.values() for loop:");
for (TagName t : TagName.values()) {
System.out.println(getValueByTagName(t));
}
}
}
Using an enum is a good fit, especially if you use a custom constructor and the built in "values" method:
public class Main {
public static enum TagName {
RESOURCE_ID("ResourceId"),
RESOURCE_NAME("ResourceName"),
RESOURCE_PRICE("ResourcePrice"),
;
private String s;
private TagName(String s) { this.s = s; }
public String toString() { return this.s; }
public static String[] strings() {
List<String> ss = new ArrayList<String>();
for (TagName tagName : TagName.values()) {
ss.add(tagName.toString());
}
return ss.toArray(new String[ss.size()]);
}
}
public static void main(String[] args) {
// Use TagName.values() for the enums, or for strings...
for (String s : TagName.strings()) {
System.out.println(s);
}
}
}
This way you can simply add new tags and they'll automatically get picked up by the "strings" method; for extra performance you could compute that string array just once, statically, since you can't change the set of enums dynamically. You could get even fancier by auto-generating the tag strings from their constant values, if they are really normalized...