JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

I can't help but feel that has gone way over the top for the original spec/scope. Even without error handling its 242 lines, many of which just cover perfectly good System.out methods, but even so miss out on others that overload for all the primitive types. I think it's a mistake to try to replace System.out... why bother? It's the only class and method that everyone has already encountered in their first "hello world" program.

Here's my take - apart from the file input thing (see use case in previous post), it just does what the spec asks - user input as bullet proof as possible and if not, fails well. Easy to use, and complete with JavaDoc
(I wouldn't normally post a lot of code while discussion is still going on, but I'm away from my desk for 8 days from tomorrow, so this is my last chance.)

/**
 * This is an API utility for novice Java students to get simple user input in their programs.
 * <br> Each "get" method takes a String that is output to System.out as a prompt to the user.
 * <br> User input is parsed as tolerantly as possible. Invalid input is rejected and re-tried.
 * <br> After three consecutive failed trys a runtime exception is thrown.
 * <br> An alternative constructor allows input to be taken from a test data file.
 *
 * @author DaniWeb members
 */
public class UserInput {

    /**
     * Just some test/demo code for this class …
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

ps - how about this use case:

// run multiple test cases
UserInput console = new UserInput();
do {
   String fileName = console.getString{"enter data file name");
   UserInput file = new UserInput(fileName);
   // run test case with input from file
} while (console.isYes("run more test data?");
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

I agree with all that except the static bit at the beginning. Creating classes with just static members is one of those things beginners do because they haven't got the OO thing yet. If we're going to set a good example, then, in my opinion, we don't use all static.
For me the clincher is if/when you do have a test data file or a log file. These fit naturally into the idea of multiple constructors. Maybe in this exact case it's not an open and shut case, but as an example of how to think about Java classes fo me it's a no-brainer.
Yes, you can use command line arguments, but UserInput won't have the main method, so you still need a way for main to create a UserInput with those values.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Hi guys
Sorry for the delay in replying, but my internet has been out since Saturday night.

@assertnull

I agree. As originally identified by David the goal is to make things as simple as possible for novices. Inevitably that will involve some of the implementation using non-novice code (e.g. re-throwing a checked exception as an unchecked so the user doesn’t need to handle it). As it happens, I don’t think the implementation requires anything too obscure (no generics, reflection, rmi or whatever), so whatever code it does include could be usable as an example of good practice. Of course the API itself and its documentation are what really matters.

@David

I think we’re all heading the same way here. I fully understand what your java and Python code is illustrating. I’m just trying to take your idea and help develop it into good Java with great “not crashing” behaviour. We’re going to get the best result by inviting others to comment and contribute, and by taking note of their good ideas.

Over the years I think I have fielded more novice problems with Scanner than any other Java topic. Its API is too complex for simple cases, it forces the user into catching exceptions in an inner loop when they are nowhere near ready, and has horrible gotchas like rejecting 12,000 as a number, or the infamous nextInt(), nextLine() trap. I’m into this project because it’s an opportunity to use those experiences to avoid everything that’s wrong with Scanner.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

As a further illustration of how, in my opinion, these things should be done, here's an example of using standard JavaDoc to share the external (public) design of an API (and yes, I sneaked the input-from-a-file thing back in, but you can ignore that)

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

In what way is that "more limited"? The scope looks the same, and the other criteria I suggested seem implied by the objective anyway.

ps: I understand why you are posting all that code, but I doubt that anyone will take the time to read it all at this stage! "Less is more".

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

I’m all in favour of this idea. I’ve seen far too many posts here from beginners struggling or failing with Scanner, so an alternative is much needed.

David has has posted a whole load of code, but I'm going to ignore that for a moment and try to continue the discussion towards a consensus statement of the objectives, scope, success criteria etc

Here’s an opening suggestion:

Objective: This is an API utility for novice Java students to get simple user input in their programs.
Scope: Handle prompted String, int and double input from the system console. Handle yes/no input.
Criteria:

  1. Easiest possible use for a complete Java novice (e.g. require no knowledge of error handling).
  2. As bombproof as possible (e.g. deal sensibly with malformed input, unexpected eof).
  3. Unrecoverable errors fail hard and fast with a good explanation (e.g. throw an unchecked exception with an explicit description of the problem).
  4. API and internal code to be an example of best standard Java practice.
  5. Any extensions to the initial scope must not have any adverse impact on it.

(ps: agreed that runtime efficiency is not relevant)

Opinions?…

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Sorry, it's a dull Sunday morning and I couldn't resist working on my Regex skills a bit.
Here's what I came up with...

        String data = "(   4.5 , 8.9 ) (76.4,  9)   (67.3  , 0.3) ";
        // shortest string between ( and ,
        Pattern p1 = Pattern.compile("\\(.*?,"); 
        Matcher m1 = p1.matcher(data);

        // shortest string between , and )
        Pattern p2 = Pattern.compile(",.*?\\)"); 
        Matcher m2 = p2.matcher(data);

        while (m1.find() & m2.find()) {

            // extract the strings between the (, and ,) delimiters...
            String v1 = m1.group();
            String v2 = m2.group();
            System.out.println("\"" + v1 + "\"     \"" + v2 + "\"");

            // remove the opening & closing delimiters...
            v1 = v1.substring(1, v1.length() - 1);
            v2 = v2.substring(1, v2.length() - 1);
            System.out.println("\"" + v1 + "\"     \"" + v2 + "\"");

            // trim any surrounding spaces and parse...
            double d1 = Double.parseDouble(v1.trim());
            double d2 = Double.parseDouble(v2.trim());
            System.out.println(d1 + ", " + d2 + "\n");
        }

Obviously that's coded for explanation and tracing rather than compactness, but it shows how it all works pretty well, I think.

Edit: I revisited this a bit later, and prefer this version. It uses a Regex to break out all the strings between a ( and a ), but then uses split to break those up ready for parsing...

        Matcher m = Pattern.compile("\\(.*?\\)").matcher(data);
        while (m.find()) {
            String[] parts = m.group().split("[\\(\\),]");
            double d1 = Double.parseDouble(parts[1].trim());
            double d2 = Double.parseDouble(parts[2].trim());
            System.out.println(d1 + ", " + d2 + "\n");
        }
AssertNull commented: Got me headed in the right direction +5
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

That all makes sense.
One advantage of the DIY solution is that you get to chose how to deal with malformed input rather than being stuck with whatever uninformative thing Scanner may do.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

OK. From what you had said ("I cannot assume that there will be white space") I assumed that the white space was not a delimiter, only the parens and the commas were valid delimiters, so basically you can:

with "( 4.5 , 8.9 ) (76.4, 9) (67.3 , 0.3) "
delete all white space "(4.5,8.9)(76.4,9)(67.3,0.3)"
delete all close parens "(4.5,8.9(76.4,9(67.3,0.3"
split on open parens to get x,y pairs "4.5,8.9", "76.4,9", "67.3,0.3"
(ignore the "" before the first open paren, or just delete the first open paren)
split the pairs on comma "4.5" "8.9 " "76.4" "9" "67.3" "0.3"
parse the values as doubles

... or something like that. A real regex samurai would know how to get all the texts between all pairs of open and close parens.

(I'm no fan of Scanner - it was supposed to make things easy for beginners, but it doesn't even do that. It's almost always easier to read whole lines and parse them yourself)

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

I'm not good at regex, so I often start by removing all the white space (one simple method call) so what remains is easier to parse.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Client line 19 you use write, which just writes the low byte of its int parameter, but in the client you readInt, which neeeds 4 bytes, so the readInt is still waiting for the last 3 bytes.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

No, the instance of the class.
So if win2 needs to dispose win1 as well you can do something like

JFrame win1 = new Window1();
...
JFrame win2 = new Window2(win1); // pass a ref to win1 into win2 so win2 can call win1's methods

so Window2's constructor would look like

class Window2 extends JFrame {
...
private Window1 win1;

public Window2(Window1 win1) { // constructor
     this.win1 = win1;
}

now any method/event handler in win2 can call win1's methods to dispose() it or whatever

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

You will need the window with the back button to have a reference to the other window that needs to be closed.
Then you can call that window's dispose method...

JFrame otherWindow = // a reference to the other window

backButton.addActionListener(e -> {
     otherWindow.dispose();
     this.dispose();
});
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Yaaayeee!
Safe at last!

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

(JamesCherrill will be pleased,lol!)

:)
It's nothing to do with whether I (or anyone else) will be pleased. It's more a question of self-preservation

Auto-update Notice and End of Public Updates for Oracle JDK 7
As outlined in the Oracle JDK Support Roadmap, after April 2015, Oracle will not post further updates of Java SE 7 to its public download sites. Customers who need continued access to critical bug fixes and security fixes as well as general maintenance for Java SE 7 or older versions can get long term support through Oracle Java SE Support.

http://www.oracle.com/technetwork/java/eol-135779.html

So unless you want to pay for long term support it's just you against the hackers and virus merchants, all on your own.

Until you get Java 8.....

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Well done!
In general, yes, install the latest SDK and wait for everything to re-build, then change the settings for each project where you want to use JDK 8 features. At least yur JKD7 code will still compile & run using Java 7 rules & syntax, but without the unfixed bugs in JDK.JRE7
.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

You can just write/read them as objects (casting to String at the receiving end).
Alternatively you can use writeUTF/readUTF which give the same results but may be slightly more efficient

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Mixing stream types on a single socket is guaranteed to cause chaos, so pick one type and stick to it. Object streams are the obvious way to go because they are most capable and simplest overall.
You can create a simple protocol to allow you to send different kinds of objects by preceeding the object with an identifier that says what's coming next. In broad outline the receiving end could like like:

enum MessageType (CHAT, IMAGE  etc

while (true) {
    MessageType nextMessageType = (MessageType) myObjectInputStream.readObject();
    switch (MessageType) {
        case CHAT:  readUTF() into a String, or maybe use a Message class and readObject() then cast to Message
        case IMAGE:  readObject() and cast to Image
        etc
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

When you call parseDouble passing a string that cannot be parsed as a number Java will throw a NumberFormatException
You can put your parseDouble inside a try block and catch the exception - your catch block will be executed if and only if the string does not represent a valid number.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

I thought this question was how to handle a Java Object (that happens to be a Boolean) in cpp code?

If it's a Java question then you need to cast the Object to Boolean (maybe checking first that it is an instanceof Boolean). Java will handle conversion between a Boolean object and a boolean primitive (eg true) automatically - it's called unboxing

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Try printing sqlString to check its syntax. Run that exact string at an sql prompt and see what it does.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

It works Ok for zero when I run it.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

(why was this showing "zero replies" after I replied before?)

edit: and now it's only showing one?

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Can you explain further?
Once you have set up the socket connection you have two Streams available (one going each way) so either end can send whatever it wants to the other. What is worrying you exactly?

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

You just copy/pasted your assignment without even a moment taken to explain what help you need. That's highly disrespectful to the many people who give their time to help others here.

There are lots of people here who will freely give their time to help you become the best Java programmer you can be. There's nobody here who is interested in helping you cheat or doing your homework for you.

DaniWeb Member Rules (which you agreed to when you signed up) include:
"Do provide evidence of having done some work yourself if posting questions from school or work assignments"
http://www.daniweb.com/community/rules

Post what you have done so far and someone will help you from there.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

In other words how would your new formatter know the end of a comment? It would have to make guesses such as "Hmm, a // might end when I find ???" I get the feeling an AI class would have to be made.

The JLS specifies Java's syntax with great precision. It's entirely deterministic, no AI needed. Comments beginning with 2 slashes are delimited by the next end of line, so any process that removes end of lines can corrupt the code, so you can't just put it all on one line. No amount of AI could fix that

Before looking for end comment delimiters you need to exclude literal strings.
Before looking for start comment delimiters you need to exclude literal strings and comments.
(to identify the end of a literal you need to ignore escaped literal " chars inside the literal, of course)

I think you have to process the input one or two chars at a time in a simple state machine (the important states being: in code, in a literal, in a comment) . Now you can respond to semicolons or curly brackets in code only. Also, in code only, you can replace all runs of white space by a simple blank char. Once you have that then breaking statements onto separate lines, and indenting by the right amount is simple.

rproffitt commented: From AI to aiyee! +10
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Instead of drawing directly to the panel's Graphics, create a new Image and draw to its Graphics. Then just copy that to the panel using drawImage and also save it as a jpeg

ps: Updating the random numbers inside paintComponent is a really bad idea. You have no direct control over when it is called, and it may be called when you don't expect, eg when the user re-sizes the window, or drags it onto a second monitor, or various other reasons that you have no access to.
You have to update them only when your program logic explicitly requires a new set of rectangles. That would also be the best time to create your own Image with those new rectangles, so your paintComponent just has to draw the latest Image to its own Graphics

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

You could build a simple form with an entry fields (or drop-down lists) for each column in the database. Whatever the user enters you use as search criteria.
You could have a check box next to each field, and if it's checked you summarise the results by summing over each distinct value for that field. Or just a sinle check box to sum all the results to a single result?

You can start with a really simple subset (maybe just 1 or 2 fields, no summing) and build up from there. If you have it working for 2 fields then going to n fields is trivial.

You could start by hard-wiring all the fields etc, but maybe as a later development you could build the form dynamically based on the table's actual columns

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Congratulations!

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

You define the function with 3 parameters, but call it with 2

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

OK guys, this is starting to go off-topic. Everyone has had a say, so let's get back to the original question re tutorials for OO etc please.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

I tend to agree with that. My typical code also has many classes, but not necessarily many subclasses. In practice I think it's obvious when you should use subclasses - just look for is-a-kind-of relationships in the problem domain. The other time I use subclasses is when I discover common functionality between different classes, in which case I may factor it out into a common superclass - although I'm more likely to use composition rather than inheritance, or use Java 8's more capable interfaces rather than a superclass.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

We don't have tutorials as such here - mostly because there are so many tutorials on the web already.
As always I recommend the original Sun/Oracle tutorials. They are the most complete, the most correct, and the most up-to-date.
http://docs.oracle.com/javase/tutorial/reallybigindex.html

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

ps: If you are using JFuzzyLogic, then the approriate method is called getValue()

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

You are using classes that are not part of standard Java, and so we have no documentation for them.
In general you can't cast to a primitive type (int etc) because these are not classes. Only their corresponding classes (Integer etc) can be directly converted to primitives by Java ("unboxing").
Presumably the Variable class has methods to return its values as doubles or whatever - you will need to read the doc to find them.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

As far as I can see you need a variable (pointer) when retrieving the values (line 6), but not another HashMap.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

After a quick look at that code I see three HashMaps. Only one seems to get anything put in it, and only one (not the same) gets printed. Makes no sense to me.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

That just confirms that you need a multi-pronged test strategy involving users, UI testers, DBAs etc.

If your architecture is layered well then backend bugs should have been found during unit testing and subsystem testing. Maybe you are leaving too much testing until too late in the process?

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Yes.. it iterates through the array for you. it's called an "enhanced for loop". Google for details & examples.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

To understand this you need to remember:

int[] arrayA = ... creates a reference variable arrayAthat holds a pointer to an array
new int[3] creates an actuial array of 3 elements
so int[] arrayA = new int[3]; creates an array and creates a pointer to it.

line 2 creates a reference variable (pointer) called arrayB, but it does NOT create a new array. It sets the pointer to refer to the existing array that was created on line 1

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Considering names like Gary Del Barco vs Sarah Michele Geller, or Richard Wayne Van Dyke vs Doris Mary Ann Kappelhoff (a.k.a.Doris Day), I suspect what you are asking is impossible without the use of human-level A.I.

(Not to mention Edda Kathleen van Heemstra Hepburn-Ruston, a.k.a. Audrey Hepburn)

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Without knowing the values of the two times I can't comment.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

OK, it's just that you used Object in your first post

When you say "got errors", exactly what error messages do yu see?

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

You seem to be calling those methods as if they were class methods for the Object class... which they're not.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
nitin1 commented: Hehe yup +4
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Your earlierccode snippet is OK, althoug you may as well just divide by the number of mSec in a day. There may be some really obscure traps in there because Date objects are in millisecs so you have to be vary careful about the time-of-day part of the object (especially when changing to/from DST). Personally I suggested what I did because
a) it goes with the current date/time support rather than the inferior earlier one
and
b} its going to work properly
and
c the code reads so clearly that even a non-Java newbie could guess what it means. I'm the world's biggest fan of easy-toread-and-understand code. In fact I'm obsessed with it.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

Use Date's toInstant() method to convert your Dates to Instants, then proceed as above.
return ChronoUnit.DAYS.between(date1.toInstant(), date2.toInstant());
Couldn't be easier.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

In Java 8 all your problems are solved!
It includes a completely new package for handling dates, times, intervals etc based on everything that was wrong with the old classes, and stealing a lot from Joda time
You just need the ChronoUnit.between method with two Instant objects
Theres a really simple example here:
http://docs.oracle.com/javase/tutorial/datetime/iso/period.html
.. but unbelievably there's a bug in the example (gap is declared as the wrong type, should be long), so here's a working example that illustrates just how neat the new classes are...

        Instant instant1, instant2; 
        long interval;

        instant1 = Instant.now();
        instant2 = Instant.now().plus(48, ChronoUnit.HOURS);

        interval = ChronoUnit.DAYS.between(instant1,instant2);

        System.out.println(instant1 +" - " + instant2 + " = " +  interval);

Don't worry about leap years etc, these classes use the most correct algorithms for dates known to man.

JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster

"There is also Class.forName is used" - is that how you interpret
"In previous versions of JDBC, to obtain a connection, you first had to initialize your JDBC driver by calling the method Class.forName." ?
It's obsolete!

There is a probem loading the class, so the first thing to do is to make sure you are not using some obsolete method to load it.

ps Class.forNameis a method, not a keyword. That's a very important difference.