passing parameters through hashmap to function in java - java

i was trying to build a command line tool alike in java, for example, if i write down in console "dir c:/....", it will activate my Dir class and will get the "c:/...." path as a parameter to the Dir class, and doing so with hashmap.
i dont know how to pass parameters through the commandline and hashmap,
is it even possible?
every command has it's own class, which implements the main "Command" interface, with a doCommand() function.
after running the start() function in the CLI class, it should take commands and do the requested command.
Command Interface:
public interface Command {
public void doCommand();
}
my CLI class:
public class CLI {
BufferedReader in;
PrintWriter out;
HashMap<String, Command> hashMap;
Controller controller;
public CLI(Controller controller, BufferedReader in, PrintWriter out,
HashMap<String, Command> hashMap) {
this.in = in;
this.out = out;
this.hashMap = hashMap;
}
public void start() {
new Thread(new Runnable() {
#Override
public void run() {
try {
out.println("Enter a command please:");
String string = in.readLine();
while (!string.equals("exit")) {
Command command = hashMap.get(string);
command.doCommand();
string = in.readLine();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
}
lets take for example my DirCommmand, as i said before, which should recognize the "dir" string through my hashMap configuration, and should pass the next word as a string parameter for the path
public class DirCommand implements Command {
#Override
public void doCommand() {
System.out.println("doing dir command...");
}
}
and my hashmap configuration:
hashMap.put("dir", new DirCommand());
which sets in a diffrent class the hashMap configuration and pass it to the CLI class's hashMap object at the start of the project.
i would love for some help because i have no idea how to do so.

First of all, in order to pass the parameters to doCommand, what I would do is use a variable param list, like:
public interface Command {
public void doCommand(String... params);
}
Second, I would split the input string on spaces as:
String[] result = command.split(" ");
Finally, the command would be the result[0] and the rest you would pass to the doCommand method.

Related

how to avoid switch statement?

I'm trying to learn client/server in java
until now i got the basics.
here how to accept and serve out many clients
public class Server {
ServerSocket serverSocket;
public void startServer() throws IOException {
serverSocket= new ServerSocket(2000);
while (true){
Socket s= serverSocket.accept();
new ClientRequestUploadFile(s).start(); //here is the first option.
}
}
}
Now suppose i have too many type of options the client can request.
the code will be as follow :
public void startServer() throws IOException {
serverSocket= new ServerSocket(2000);
while (true){
Socket s= serverSocket.accept();
DataInputStream clientStream= new DataInputStream(s.getInputStream());
String requestName=clientStream.readUTF();
switch (requestName){
case "ClientRequestUploadFile": new ClientRequestUploadFileHandler(s).start();break;
case "clientRequestCalculator": new clientRequestCalculatorHandler(s).start();break;
case "clientRequestDownloadFile": new clientRequestDownloadFileHandler(s).start();break;
}
}
}
if there 100 of options,is there any way to avoid switch statement(design-patterns maybe)?
keep in mind that may occur new option in the future.
This seems like an example where something like the Command pattern would be appropriate.
Basically, you want a way to map a given command (in this case, a String), into executing the appropriate behavior.
The simplest way to do this would be to create a Command interface like so:
interface Command {
void execute();
}
Then you can create a Map<String, Command> that holds your commands and maps each incoming String into some helper class that implements Command and does the thing you want to happen when you see that command. Then you would use it something like:
commandMap.get(requestName).execute();
This will, however, require a bit of on-the-fly setup at program startup to build the Map with the command strings and the Command objects. This is a very dynamic way of setting up the mapping, which may be a good or bad thing depending on how often your command set changes.
If your commands are more static, a more elegant way to set this up would be to use an enum to define the various commands and their behaviours. Here's a fairly simple and generic example of how you could do that:
public class CommandPatternExample {
public static void main(String[] args) throws Exception {
CommandEnum.valueOf("A").execute(); // run command "A"
CommandEnum.valueOf("B").execute(); // run command "B"
CommandEnum.valueOf("C").execute(); // IllegalArgumentException
}
interface Command {
void execute();
}
enum CommandEnum implements Command {
A {
#Override
public void execute() {
System.out.println("Running command A");
}
},
B {
#Override
public void execute() {
System.out.println("Running command B");
}
};
}
}
As pointed out in the comments, there's no way to get around having the command to helper object mapping somewhere in your code. The main thing is to not have it in your business logic, which makes the method hard to read, but rather in its own class somewhere.
So what you have is a large-ish switch block that in the end start()s some piece of code. The recommended way is to use existing interfaces, so that would be a Runnable (containing a void method with no parameters, just like your start()).
If you refactor the whole block out into a method, it would have two inputs: the Socket and the the requestName - so its signature would look like this:
Runnable getRequestCommand(Socket s, String request)
which would contain your switch block and returned something like
if ("ClientRequestUploadFile".equals(request)) {
return new ClientRequestUploadFileHandler(s);
}
// etc
Again using preexisting interfaces, this is a BiFunction<Socket, String, Runnable> (it requires the request string and the socket as input and returns the handler runnable).
Now you can split each individual case and create such a function:
BiFunction<Socket, String, Runnable> upload = (s, req) -> {
return "ClientRequestUploadFile".equals(req)
? new ClientRequestUploadFileHandler(s)
: null;
}
If you do the same for the other cases and store these in a Collection<BiFunction<Socket, String, Runnable>> (let's call it handlers), your getRequestCommand() method above looks like
Runnable requestHandler = null;
for (BiFunction<Socket, String, Runnable> handler : handlers) {
requestHandler = handler.apply(s, request);
if (requestHandler != null) { break; } // found the match
}
return requestHandler;
Now your switch actually also starts the created Runnable, so you can also if (requestHandler != null) { requestHandler.run(); } here and not return it back to the caller. As a single line, this is handlers.stream().map(h -> h.apply(s, request)).findFirst(Objects::nonNull).ifPresent(Runnable::run).
Anyway, now you're stuck with creating all the BiFunction<>s in the original class, but you can externalize them, eg. to an enum.
enum RequestHandler {
FILE_UPLOAD("ClientRequestUploadFile", ClientRequestUploadFileHandler::new),
CALCULATE("clientRequestCalculator", ClientRequestCalculatorHandler::new),
// ...
;
// the String that needs to match to execute this handler
private String request;
// creates the runnable if the request string matches
private Function<Socket, Runnable> createRunnable;
private RequestHandler(String r, Function<Socket, Runnable> f) {
request = r; createRunnable = f;
}
// and this is your handler method
static void runOnRequestMatch(Socket socket, String request) {
for (RequestHandler handler : values()) {
Runnable requestHandler = request.equals(handler.request)
? handler.createRunnable.apply(socket)
: null;
if (requestHandler != null) {
requestHandler.run();
break;
}
}
}
}
And in your client code, you'd get
// ...
Socket s= serverSocket.accept();
DataInputStream clientStream= new DataInputStream(s.getInputStream());
String requestName=clientStream.readUTF();
RequestHandler.runOnRequestMatch(s, requestName);
Now you've ended up with far more code than before, but the handling itself is removed from the class accepting the socket, so better single responsibility; this allows you to add functionality by adding a value to the enum without needing to touch your original code.
A simpler version would be to create the functions collection in a method by simply doing
Collection<BiFunction<Socket,String,Runnable>> createMappings() {
return Arrays.asList(
createMapping("ClientRequestUploadFile", ClientRequestUploadFileHandler::new),
createMapping("clientRequestCalculator", ClientRequestCalculatorHandler::new),
);
}
private BiFunction<Socket,String,Runnable> createmapping(String req, Function<Socket, Runnable> create) {
return (s, r) -> req.equals(r) ? create.apply(s) : null;
}

Testing a method by overriding a private class variable as an initial step before refactoring

What is the best way of writing a unit test for a method, such as my setProperties (see below), that uses a private configuration variable (config). I tried but failed to override it using reflection and Makito, but without success. I realize that changing the design to make the code easier to test is best, but I want to created some unit tests before I refactor the code.
public class MainClass {
private final java.lang.String config = "app.properties";
public TestClass() {
try {
setProperties();
} catch (Exception e) {
e.printStackTrace();
}
}
public void setProperties() throws Exception {
try {
InputStream input = new BufferedInputStream(new FileInputStream(config));
..
..
} catch (Exception exception) {
throw exception;
}
}
}
Do refactor a tiny bit by extracting a method with a parameter that takes an input stream. Call this new method (probably package-protected) from the old one. Write tests against the new method. Then do more refactorings.
This is an indication of a broken design; don't hard-code things like this. Better yet, determine what the appropriate responsibility for this class is, and, in decreasing order of preference:
pass in an object with the configuration properties, strongly typed
pass in a Map with the configuration properties
pass in an InputStream for the properties file
As File objects are never available from a jar, you shouldn't ever make interfaces like this more specific than InputStream or Reader, so that you can always pass in streams from your jar classpath.
So you can use Properties class in Java for this. Please have a look at this code.
public class PropertyUtil {
private static Properties prop;
private static Logger logger = Logger.getLogger(PropertyUtil.class);
private PropertyUtil() {
}
public void setProperty() {
String filePath = System.getenv("JAVA_HOME") + "/lib" + "/my_file.properties";
prop = new Properties();
try (InputStream input = new FileInputStream(filePath)) {
prop.load(input);
} catch (IOException ex) {
logger.error("Error while reading property file " + ex);
}
}
public static String getProperty(String key) {
if (prop.containsKey(key)) {
return prop.getProperty(key);
} else {
return null;
}
}
public static <T> T getProperty(String key, Class<T> claz) {
if (claz.getName().equals(Integer.class.getName())) {
return claz.cast(Integer.parseInt(prop.getProperty(key)));
}
if (claz.getName().equals(Long.class.getName())) {
return claz.cast(Long.parseLong(prop.getProperty(key)));
}
if (claz.getName().equals(Boolean.class.getName())) {
return claz.cast(Boolean.parseBoolean(prop.getProperty(key)));
}
if (claz.getName().equals(Double.class.getName())) {
return claz.cast(Double.parseDouble(prop.getProperty(key)));
}
if (claz.getName().equals(String.class.getName())) {
return claz.cast(prop.getProperty(key));
}
return null;
}

Get output console tail and save to string Java?

I use the apache tailer for read end of line, if there is adding new line inside file log the program will print just end of line, it's like "tail -f" from linux, i have the output tail to send with String.
Can i get the output tail and save to string for my code below ?
public class LogTailTest {
/**
* TailerListener implementation.
*/
static public class ShowLinesListener extends TailerListenerAdapter {
#Override
public void handle(String line) {
System.out.println(line);
}
}
public static void main(String args[]) {
TailerListener listener = new ShowLinesListener();
File file = new File("/home/ubuntu/Desktop/test.log");
Tailer tailer = new Tailer(file, listener, 10000, true, true);
tailer.run();
try {
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
tailer.stop();
}
}
When i run above program it's direct to output console
You define what to do every time a new line is tailed by your program. This behaviour is defined in the method handle of class ShowLinesListener:
#Override
public void handle(String line) {
System.out.println(line);
}
All you have to do is change this line
System.out.println(line);
to do what you want with it. As you are already using commons-io library (that's where the TailerListener and TailerListenerAdapter classes are defined), you can use FileUtils.writeStringtoFile method to write the contents of the line just tailed to another file.
Your class would look like this:
public class LogTailTest {
/**
* TailerListener implementation.
*/
static public class ShowLinesListener extends TailerListenerAdapter {
#Override
public void handle(String line) {
FileUtils.writeStringtoFile(new File("/path/to/file"),
line,
Charset.defaultCharset())
}
}

PyLucene JCC: implement a Java interface in python and receive Java thread callbacks through it

I'm playing around with my new toy, JCC 2.21, and am having trouble implementing callbacks in a python script. I have wrapped the following simple Java thread API and am calling it from python 2.7 (CPython), but when I call the JccTest.addJccTestListener(JccTestListener) method, the JVM reports a null argument.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class JccTest implements Runnable {
private final Object listenersLock = new Object();
private final List<JccTestListener> listeners = new ArrayList<JccTestListener>();
private final AtomicBoolean running = new AtomicBoolean(false);
private final AtomicBoolean finished = new AtomicBoolean(false);
public void start() {
if (running.compareAndSet(false, true)) {
new Thread(this).start();
}
}
public void stop() {
finished.set(true);
}
public void addJccTestListener(JccTestListener l) {
if (l == null) {
throw new IllegalArgumentException("argument must be non-null");
}
synchronized (listenersLock) {
listeners.add(l);
}
}
public void removeJccTestListener(JccTestListener l) {
synchronized (listenersLock) {
listeners.remove(l);
}
}
#Override
public void run() {
System.out.println("Start");
while (!finished.get()) {
System.out.println("Notifiying listeners");
synchronized (listenersLock) {
for (JccTestListener l : listeners) {
System.out.println("Notifiying " + String.valueOf(l));
l.message("I'm giving you a message!");
}
}
System.out.println("Sleeping");
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
continue;
}
}
running.set(false);
System.out.println("Stop");
}
public static void main(String[] args) throws InterruptedException {
JccTest test = new JccTest();
test.addJccTestListener(new JccTestListener() {
#Override
public void message(String msg) {
// called from another thread
System.out.println(msg);
}
});
test.start();
Thread.sleep(10000);
test.stop();
}
}
public interface JccTestListener {
public void message(String msg);
}
Generated wrapper with:
python -m jcc --jar jcc-test.jar --python jcc_test --build --install
And then executed this script (equivalent to the main method of JccTest):
import jcc_test
import time, sys
jcc_test.initVM(jcc_test.CLASSPATH)
test = jcc_test.JccTest()
class MyListener(jcc_test.JccTestListener):
def __init__(self):
pass
def message(self, msg):
print msg
test.addJccTestListener(MyListener())
test.start()
time.sleep(10)
test.stop()
sys.exit(0)
Which results in:
"python.exe" jcc_test_test.py
Traceback (most recent call last):
File "jcc_test_test.py", line 16, in <module>
test.addJccTestListener(MyListener())
jcc_test.JavaError: java.lang.IllegalArgumentException: argument must be non-null
Java stacktrace:
java.lang.IllegalArgumentException: argument must be non-null
at com.example.jcc.JccTest.addJccTestListener(JccTest.java:32)
Besides the null listener instance, is doing something like this even possible with CPython? I've read that in its implementation only one thread may execute the python script at a time, which might (?) be a problem for me. Doing something like this with Jython was trivial.
I'm rather new to python so please be gentle.
Figured it out. You need to define a pythonic extension for a java class to make this work. The detailed procedure is described in JCC documentation (Writing Java class extensions in Python) and is rather simple.
First, code a class that implements your interface and add some magic markers that are recognized by JCC and affect what the wrapper generator will generate.
public class JccTestListenerImpl implements JccTestListener {
// jcc specific
private long pythonObject;
public JccTestListenerImpl() {}
#Override
public void message(String msg) {
messageImpl(msg);
}
// jcc specific
public void pythonExtension(long pythonObject) {
this.pythonObject = pythonObject;
}
// jcc specific
public long pythonExtension() {
return this.pythonObject;
}
// jcc specific
#Override
public void finalize() throws Throwable {
pythonDecRef();
}
// jcc specific
public native void pythonDecRef();
public native void messageImpl(String msg);
}
The markers are denoted by my comments and must appear verbatim in any class that is to be extended in python. My implementation delegates the interface method to a native implementation method, which will be extended in python.
Then generate the wrapper as usual:
python -m jcc --jar jcc-test.jar --python jcc_test --build --install
And finally make a python extension for the new class:
import jcc_test
import time, sys
jvm = jcc_test.initVM(jcc_test.CLASSPATH)
test = jcc_test.JccTest()
class MyListener(jcc_test.JccTestListenerImpl):
## if you define a constructor here make sure to invoke super constructor
#def __init__(self):
# super(MyListener, self).__init__()
# pass
def messageImpl(self, msg):
print msg
listener = MyListener()
test.addJccTestListener(listener)
test.start()
time.sleep(10)
test.stop()
sys.exit(0)
This now works as expected with callbacks coming in.
"python.exe" jcc_test_test.py
Start
Notifiying listeners
Notifiying com.example.jcc.JccTestListenerImpl#4b67cf4d
I'm giving you a message!
Sleeping
Notifiying listeners
Notifiying com.example.jcc.JccTestListenerImpl#4b67cf4d
I'm giving you a message!
Sleeping
Process finished with exit code 0

How can I pass a variable to an inner thread class?

I want to load an image at periodic intervals to an imageitem. My outer class is generating the URL and I need to pass it to the innerclass. How do I achieve this?
public class MapTimer extends TimerTask{
public void run() {
System.out.println("Map starting...");
String URL=null,serverquery=null;
try {
sendMessage(this.message);
item.setLabel(item.getLabel()+"start");
serverquery=receiveMessage();
item.setLabel(item.getLabel()+"stop");
URL = getURL(serverquery); // my url to be passed to innerclass
System.out.println("URl is "+serverquery);
item.setLabel(URL+item.getLabel());
Thread t = new Thread() {
public void run() {
item.setLabel(item.getLabel()+"6");
try {
Image image = loadImage(URL); // using url
System.out.println("GEtting image....");
item = new ImageItem(null, image, 0, null);
form.append(item);
display.setCurrent(form);
} catch (IOException ioe) {
item.setLabel("Error1");
}
catch (Exception ioe) {
item.setLabel("Error1");
}
}
};
t.start(); // write post-action user code here
}
catch(Exception e){
System.out.println("Error3"+e);
}
}
}
How do I pass the URL to my innerthread class?
You have to declare the variable final or don't use a variable but a field in the class.
public class YourClass {
private String url;
public void yourMethod {
url = getURL(serverquery);
System.out.println("URl is "+serverquery);
item.setLabel(URL+item.getLabel());
Thread t = new Thread() {
public void run() {
item.setLabel(item.getLabel()+"6");
try {
Image image = loadImage(url); // using url
System.out.println("GEtting image....");
item = new ImageItem(null, image, 0, null);
form.append(item);
display.setCurrent(form);
} catch (IOException ioe) {
item.setLabel("Error1");
}
catch (Exception ioe) {
item.setLabel("Error1");
}
}
};
t.start(); // write post-action user code here
}
}
It should work if your URL is contained in a final reference. This means that the reference won't move. Consequently, you can't initialize it to null and then call getURL, you need to declare it at this point:
final String URL = getURL(serverquery);
I found that there are (at least) 2 major ways of doing this on whever your thread gets the information or recieves the information (in your case URL)
1) gets the informations:
what you want to do is keep a reference of the object containing the data you need (like URL) in your Thread, and when your ready the Thread gets the next item/URL to load.
public class MapTimer extends TimerTask{
public void run() {
...
}
private URLGenerator urlGenerator = null;
public MapTimer(URLGenerator urlGen){
...
}
This will give you the option to get the next URL when your thread is free (with a if(urlGen != null) of course)
2) Receives Information
Works better for cases where the thread is called only when the rest of the program wants to (user inputing data etc)
public class MapTimer extends TimerTask{
public void run() {
...
}
private URL urlToLoad = null;
public void setURL(URL urlToLoad){
...
//store and wake up thread
}
this way your thread recieve with a setter the data it needs to run, processes it then waits for the next data to be send to it (of course you need to be careful of thread issues like multiple calls etc.)
Hope this helps you
Jason
Just make the field a static variable belonging to the class and not any object instance of the class, like this:
public YourClass {
private static String url;
//...
}
Please note however that the static variable will be shared among all object instances of the class.

Categories

Resources