Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Assigning values to variables from a text file  RSS feed

 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi guys,

I am currently working on a project in which I have a set of employees. Each employee works for a certain department, and has a certain status (available or unavailable), start of shift, end of shift. I want to assign jobs to these employees. When employees start their task, they become unavailable and when they finish their tasks, they become available again.

I want the java application to read some basic information of these employees: Their ID, their department, start time, end time etc. I made a simple textfile called Employees.txt
Example of this text:
8601,sales,9:00,19:00
8602,maintenance,10:00,20:00
8603,maintenance,19:00,23:00


I want to import these in my TestClass, and assign these values to the employees. With some help from other topics, I made a start, see java code below.
I want to make sure that all information in the array/arrayList is coupled to the class Employee. How can I make this part of the code work? And how can I refer to each employee in the array/arraylist? Would it be possible to use the driver ID as an object name? What I mean here is that I can easily say: , thus assigning methods to particular objects by employee_ID.



 
K. Tsang
Bartender
Posts: 3648
16
Firefox Browser Java Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well are you able to read the file? Was there any exception when you run it?

You didn't put anything into the arraylist.


Say to got your employee list, now the question becomes how do you determine the status? Base on the current time and compare that to the file's start/end time?
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Status would be available at start of shift. When activity is assigned to employee, status changes to unavailable.

I am still in doubt how to model time. I want to make 'simulations' over a day, and then in hindsight determine amount of idle time/utilized time.
 
Knute Snortum
Sheriff
Posts: 4087
112
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have you written an Employee class? Can you post it if so?
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes I did. Since I just started, it is far from complete, but it might give you an idea of how I want to design this class and what I expect objects of this class to do.

 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sander Hoovenaar wrote:Yes I did. Since I just started, it is far from complete, but it might give you an idea of how I want to design this class and what I expect objects of this class to do.

OK, well one thing I always reckon - and there may be those who disagree with me - is that a class should know how to construct its own objects in whatever form is needed.

Now you have an input file with lines of data that equate to a single employee; therefore your Employee class should know how to construct objects from a line of data, viz:and then your "read" loop becomes something like:
HIH

Winston
 
Campbell Ritchie
Marshal
Posts: 55772
163
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am sure Winston will shoot me for using a Scanner, but there is an alternative approach:-You have marked your fields as parameters and constants, which they are not. All those fields should have private access. The time fields should not be Strings. Don't use CAPITAL_LETTERS_AND_UNDERSCORES in variable names, unless they really are constants.
 
Junilu Lacar
Sheriff
Posts: 11165
160
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For a small program like this, the approach of having an Employee object be responsible for parsing input may be fine. However, on larger applications, the approach becomes unwieldy and smelly, particularly when Open-Closed Principle gets violated when you need to add different means of getting input for Employee attributes. An Employee object is a Domain object. Input is closer to infrastructure and external interactions, either with human users or other applications.

Again, this program seems small enough that having a direct interface to the outside world from a Domain object is not very troublesome. Just note that it can become an anti-pattern when it starts breaking design principles like OCP.
 
Junilu Lacar
Sheriff
Posts: 11165
160
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
An alternative to having the Employee be responsible for parsing files and initializing Employee objects is to assign that responsibility to a class that would be more tightly coupled to the input file and its format, say an EmployeeFileReader. This way, should the file format change for some reason, you would logically have to change this class rather than the Employee class. This keeps the Employee class insulated from any changes to the input file format.
 
Junilu Lacar
Sheriff
Posts: 11165
160
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The same reasoning can be applied to keeping track of the employee's task status. A task is temporal in nature, thus it's better modeled as a Moment-Interval. Perhaps an EmployeeTask class that establishes a relationship between Employee and Task objects based on moment-intervals of time. This opens up more possibilities for expanding the capabilities of the program. For example, if you had Employee keep track of the task/status information, it quickly becomes messy when you're asked to provide a historical view of the tasks that a certain employee has completed in the last week or month. You can't readily calculate that with the proposed design. Giving the responsibility of keeping track of tasks they completed to an Employee is smelly, even without seeing the code.

However, if you keep a list of EmployeeTask objects, you can easily query that list for elements pertaining to a specific employee that fell within a specified interval of time, then do whatever other calculations you need to do with that subset of elements.
 
Junilu Lacar
Sheriff
Posts: 11165
160
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One thing you can do to keep the appearance of an "intelligent" Employee domain object is to use delegation. That is, an Employee can delegate the responsibility of tracking its tasks and task status to a Tasks object.

Essentially, you're modeling like this:
An Employee has Tasks (delegate)
An Employee can tell you if he's available to perform a Task by asking its Tasks delegate whether there's a current task. If there is no current task, then the Employee can answer, "Yes, I'm available."

In code, that might look something like this:
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:An alternative to having the Employee be responsible for parsing files and initializing Employee objects is to assign that responsibility to a class that would be more tightly coupled to the input file and its format, say an EmployeeFileReader.

Yes, I can sort of understand that.
Mind you, it begs the question whether it shouldn't actually be Employee.FileReader.

Also: a change to a file format could indicate a change to the Employee class itself (eg, to add an attribute), or vice-versa - a change to the Employee class mandates a change to your file format - so you wouldn't want to separate them too much.

Winston
 
Campbell Ritchie
Marshal
Posts: 55772
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:. . . a class that would be more tightly coupled to the input file and its format, say an EmployeeFileReader. . . .
Good idea. That shows the problems with reading from files; you have to couple a class to the format of the file.
 
Junilu Lacar
Sheriff
Posts: 11165
160
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
Mind you, it begs the question whether it shouldn't actually be Employee.FileReader.

Also: a change to a file format could indicate a change to the Employee class itself (eg, to add an attribute), or vice-versa - a change to the Employee class mandates a change to your file format - so you wouldn't want to separate them too much.

Absolutely spot on observations.

This is why it's good to do development with a buddy so things like this can come out in discussions. Or two buddies (nodding head at Campbell)
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for all the information, although I do not understand everything completely, to be honest. I have changed the naming of several variables (Also employee has become a driver )

I am still a novice, but I am eager to learn. I would like to change things step by step and check all the changes I make instead of jumping into the deep. First, I would like to make the reader work. I have used the readLine method that Winston proposed. I have kept the ReadFile in my main method and applied some changes to the driver/employee class.
I have compiled the following now:



How can I check (beside that it compiles) that it actually has put in the data well?

Would I be able to do the following things with the arraylist?
- Determine what drivers in the list have a certain status
- if for instance drivers are available for certains tasks, I would like to assign these tasks to them and therefore change their status.



 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sander Hoovenaar wrote:I am still a novice, but I am eager to learn. I would like to change things step by step and check all the changes I make instead of jumping into the deep.

Excellent idea. Keep it up.

Do one thing at a time, and make sure it works, before you start on the next one.

How can I check (beside that it compiles) that it actually has put in the data well?

My suggestion would be to implement a toString() method for your Driver class. Then you can print out the contents of DriversAvailable (which, BTW, should be 'driversAvailable') with driversAvailable.toString().

Winston
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That worked very fine. Thanks

I decided to make a class named Zone, after why Strings are bad: http://www.coderanch.com/t/659830/Wiki/Strings-Bad

Since zone is used for several purposes (not only for the class Employee/driver), I decided to make a subclass called driverZone. Now I am wondering how I can assign a specific zone to the employees (after reading from the text file). In total, there are 5 zones, each with its own zoneID, zoneName and other characteristics.
First, I thought about wrapping it, but I would not know how to wrap it then. IT does not allow me to wrap the string to the object-type. Maybe it is plain simple, but I cannot seem to come up with a good solution.





Could you give a hint?

 
Knute Snortum
Sheriff
Posts: 4087
112
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would think it would depend on what arrayLine[1] is. Say it is a DriverZone name. You could create a constructor like this:

Then your Driver code could look like this:
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sander Hoovenaar wrote:Could you give a hint?

OK, well my first question is: What is a "Zone"?

Second question: Does a DriverZone differ from a "vanilla" Zone and, if so, how and why?

The reason I ask is that maybe Zone should be an interface, and DriverZone simply an implementation of that interface; but without a bit more information, it's difficult to advise.

One thing I would say: If you have a "zone ID", then you probably have a "zone" ... whatever that is.

Winston
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A zone is a working area, similar to a province or district.
Employees can be stationed in such an area, and jobs are located in an area as well.

 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
About modelling time as a String. I found this earlier to calculate time differences, and thought it would be useful. I would like to determine in hindsight the time an operation took, but I also want to estimate times, e.g. simply adding 2 hours to a start time.


Would you suggest a different type than String? Why?


Edit: Btw, the values were just entered to check whether this simple calculation worked ;)
 
Knute Snortum
Sheriff
Posts: 4087
112
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you have Java 8, I would suggest using LocalTime.
 
Carey Brown
Bartender
Posts: 3009
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sander Hoovenaar wrote:About modelling time as a String. I found this earlier to calculate time differences, and thought it would be useful. I would like to determine in hindsight the time an operation took, but I also want to estimate times, e.g. simply adding 2 hours to a start time.

Would the time comparison ever involve crossing over midnight? If so, you may need a date/time representation instead.
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The time is only needed for one day, thus not crossing midnight. I could not find a method in LocalTime that is able to find the difference between two time instances (let's say 14:00 and 15:00, resulting in 01:00), or am I missing something? The description in the api is in most cases what I need.

I do not cope with time zones, dates are not important (I'll run each day seperately). What I do want is to:
- be able to add/substract for instance 30 minutes to a certain time
- be able to calculate the difference between two time instants
- to sum all time that an employee is working on tasks throughout his working day (part of the time he will be idle, breaks, etc)


I found that the period class does not make sense, since it copes with days, weeks, months and years mostly.
I think I could use the duration class, but that would mean that I have to translate every time instance to nano-seconds.

Is there any other Time Class I am missing. If not, how will I be able to calculate with the time instants?
 
Knute Snortum
Sheriff
Posts: 4087
112
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In Java 8, the difference between two times is called a Duration.
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I thought about moving the creation of the list DriversAvailable to the Class Driver. I believe I read that it is best to put methods as close to the classes where they belong to.
To make it work I made the method static. In this way I can call on this method by refering to the Class instead of an object. Thought that this would make sense (is that correct?) See first code below.

Now my problem is, is that I do not know how to refer to this list in my main method.






The reference driversAvailable in line 3 gives the error (cannot be resolved to a variable).
How do I solve this?
 
Carey Brown
Bartender
Posts: 3009
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Change to

Then when you call this, put the return value in a variable you have access to.
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Carey for your reply. This solution does not work. The error I receive now is: 'The type List is not generic; it cannot be parameterized with arguments <Driver>
I have imported List, but this does not change the problem.
 
Campbell Ritchie
Marshal
Posts: 55772
163
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Does that mean you have a different List class in your own folder? Try removing that or moving it somewhere else.
 
Stephan van Hulst
Saloon Keeper
Posts: 7817
142
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Or better yet, don't name your types the same as existing ones in the commonly used standard packages, which I personally consider to be java.lang, java.util, java.math, java.time, java.io, java.nio.file and java.awt.

If you are importing packages containing types with conflicting names, you have to explicitly import the type you need:
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Still have difficulties, despite minor changes to the import statements. My code now:



The error message I receive is 'This method must return a result of type List<Driver>'


 
Carey Brown
Bartender
Posts: 3009
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow. The error message is telling you exactly what is wrong. It says you are missing a 'return'. So, return the list you've built.
 
Carey Brown
Bartender
Posts: 3009
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, your variable "DriversAvailable" should begin with a lower case.
 
Campbell Ritchie
Marshal
Posts: 55772
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can avoid exceptions while doing input if you use a trick Rob Spoor taught me a long time ago: use a Scanner and its hasNextXXX methods:-I am sure that code belongs in a method in its own utility class, and you return the int found. That technique will completely obviate any risk of exceptions.
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Carey Brown wrote:Wow. The error message is telling you exactly what is wrong. It says you are missing a 'return'. So, return the list you've built.

Sorry that I did not see that coming. I am fairly new to java, and my understanding of java messages is limited. Will not forget this one now though

I was able to read what is in an ArrayList when I created it in the Main method-class. I overrided the toString() method.
How am I able to display this ArrayList in the main-method class?
- The return statement does not display the list in my main-method class/.
- Converting the List to a String in the return statement does not work
- Trying to print it in main-method class does not work, since this class does not know of any list with that name.

 
Stephan van Hulst
Saloon Keeper
Posts: 7817
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you post all the code relevant to this problem, it will make more clear what you're trying to do. Let us know what's not working.
 
Ronald Hoovenaar
Ranch Hand
Posts: 53
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What I did before was:
Making the arrayList in the main-method class. I could easily do calculations with the data from the arraylist:


I could also display the contents of the list easily, since I had a toString-method in the Driver-class. The code for this in my main-method class was:


How would I be able to do these things now?
 
Stephan van Hulst
Saloon Keeper
Posts: 7817
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You want to print a list?
 
Knute Snortum
Sheriff
Posts: 4087
112
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How am I able to display this ArrayList in the main-method class?

Say you have a method like this:

Then in main() you can do something like:
  System.out.println(doSomething());
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!