Question

Maybe there is a method that does this that I don't know about - I doubt it though - but I'm trying to convert an array of strings to an array of Objects. Here is the problem: I'm reading a file in from the command line. The file represents several classes of the following types each with their own data fields. Vehicle is the parent class of all who follow: Vehicle,Car,American Car, Foreign car, Truck, Bicycle.

I have no problem reading the file into a string array. However I need to create objects of all these types and store them in an array of type Vehicle[]. For example a portion of the file looks like this:

  • Vehicle
  • Kim Stanley Robinson
  • 2344 court drive
  • (221)885-7777
  • stackoverflow@overflow.com
  • American Car
  • John Bunyon
  • 1010 binary lane
  • (221)885-55643
  • bgt.com
  • convertable
  • made in detroit
  • union plant

Where Class type is the first line followed by, Owner's Name, address, phone number, email address...Each type has fields particular to it. So a foreign car is not made in Detroit. Each of these fields appear on a separate line in the file. So what I've done is read the entire file into a string array. However, I need to find my types in the array of strings,create objects of those types, and store them in a Vehicle array. My main problem is that each data field is on a separate line. How should I approach this problem? This is java code by the way.

Was it helpful?

Solution

Initially reading the data into a String array is fine. Then you need to loop through that array, and based on the "first line" of each loop ("Vehicle", "American car" etc) you will know how many subsequent elements of the array belong to the same.

Something like this (i'll let you fill in the blanks yourself):

int i = 0;
ArrayList<vehicle> vehicles = new ArrayList();
while (i < data.length)
{
  if (data[i].equalsIgnoreCase("vehicle"))
  {
    Vehicle vehicle = new Vehicle();
    vehicle.setOwner(data[++i]);
    ...
    vehicles.add(vehicle);
  }
  else if (data[i].equalsIgnoreCase("american car"))
  {
    ...
  }
  i++;
}

OTHER TIPS

question is unclear. Do you want to know how to parse the file and use the words on each line to create a object of it?

pseudo:

Vehicle_ptr myVeh = null;
for each line in file
switch line
{
case vehicle: myVeh = new Vehicle();
case American Car : myVeh = new AmericanCar();
default:
if (line.startswithaninteger && (myVeh != NULL)) myVeh.address = line;
etcetc.
}

Tips: use typeidentifiers in the textfile.for example: car:americancar address:12345 bla etcetc

Or use a serializer

You could read the file as you are doing just now but when you read a string that is a Class type create an instance of the correct Vehicle type. It would appear that you would then know that the next x lines of the file are properties of that particular type so you would read the properties and set them on your Vehicle instance. You then have your Vehicle instance to add to the Vehicle array.

I would use a Factory pattern that creates Adapters. The factory would take the string (Vehicle, American Car) and the adapter would take the string array and current index. The adapter would be responsible to knowing how many indices to read and return the concrete object (or an interface).

IAdapter adapter = AdapterFactory.Create( "American Car" );
Object concreteObject = adapter.Popluate( stringArray, currentIndex );

Now, if you have control over how the data is stored, you might want to look into standard serialization, even JSON, to make processing easier.

It seems to me you need a factory pattern to build your set of vehicle types from the inputs. The factory can look after determining where one car specification starts and another one ends. It'll then determine the set of fields for a car, and determine the car type. It can then call the appropriate constructor, passing in all the related fields.

This means that a constructor of (say) an American car specifies all the fields that it's interested in. A European car constructor would do the same. Each constructor can assert on what it's been given so you don't create any cars incorrectly.

The factory will look after parsing and separating the inputs, and determining what is to be built. Each type of car's constructor looks after info for that car only, and performs the appropriate asserts.

The factory will maintain the list of cars created, and return that list (of America/European/Japanese) upon completion.

In pseudo-code:

whilst(!done) {
   fields.add(fieldFromFile);

   if (carSpecificationCompleted) {
       type = getType(fields);
       if (type == 'American') {
          car = new AmericanCar(fields);
       }
       else if (type == 'European') {
          car = new EuropeanCar(fields);
       }
       cars.add(car);
       clearStoredFields();
   }
}

Do you have control of the file being passed in? If so, might I suggest formatting it using XML and then parsing it using JDOM? It would make your life easier in terms of parsing. For example, you could format all vehicle entries like this:



    <node type="vehicle>
       <attributes location="detroit" color="red" />
    </node>

Or whatever format you come up with. The benefit of this is you can then read in only the vehicles (or whatever you want), or use XPath or some other technology to efficiently get the info you want/need and load it to the proper datatype.

Disregard this advice if you have no control over file formatting.

When you have the choice, change your file format.

You can serialize your object by using xstream. Then you only have to store the complete Java object without checking if some value is existing.

I'd use the Builder pattern here instead of Factory. No big difference but find it a bit easier when the parameters vary like it seems to do in his example.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top