Data structure problem

  • Thread starter steve_marjoribanks
  • Start date
S

steve_marjoribanks

Ok, I'm afraid I haven't got any source code or anything for this
because I've only just started writing this method and I'm a bit
stuck!!!

Basically, I have an XML file which may have any number of 'Layer'
elements within a 'layers' element. Within the Layer elements are
'layerTop' and 'layerBottom' methods like this:

<layers>
<Layer>
<layerTop>
<Points>
<pos>string</pos>
<pos>string</pos>
etc..
</Points>
</layerTop>
<layerBottom>
<Points>
<pos>string</pos>
<pos>string</pos>
etc..
</Points>
</layerBottom>
</Layer>
<Layer>
...
etc...
....
</Layer>
...
...
etc..
...
</layers>


Ok, I am using JDOM and have coded an iterator to iterate through the
'Layer' elements and I have the code to iterate through the <pos>
elements from another part of my aplication.
Each of the groups of 'pos' values (strings) need to be stored in a
different array (or other data structure). That is, there should be
arrays called 'firstLayerTop', 'firstLayerBottom', 'secondLayerTop',
'secondLayerBottom' etc each containg the strings from the 'pos'
elements.

This would be fine, but the problem is that I don't know how many
'Layer' elements there will be within the XML file! How can I allow for
there to be any number of 'Layer' elements and still retrieve and store
the 'pos' data (in a logical, easily retrievable manner).

I've had a good long think about it but just can't think of a solution.
Any help would be greatly appreciated!

Thanks

Steve
 
R

Rhino

Ok, I'm afraid I haven't got any source code or anything for this
because I've only just started writing this method and I'm a bit
stuck!!!

Basically, I have an XML file which may have any number of 'Layer'
elements within a 'layers' element. Within the Layer elements are
'layerTop' and 'layerBottom' methods like this:

<layers>
<Layer>
<layerTop>
<Points>
<pos>string</pos>
<pos>string</pos>
etc..
</Points>
</layerTop>
<layerBottom>
<Points>
<pos>string</pos>
<pos>string</pos>
etc..
</Points>
</layerBottom>
</Layer>
<Layer>
...
etc...
....
</Layer>
...
...
etc..
...
</layers>


Ok, I am using JDOM and have coded an iterator to iterate through the
'Layer' elements and I have the code to iterate through the <pos>
elements from another part of my aplication.
Each of the groups of 'pos' values (strings) need to be stored in a
different array (or other data structure). That is, there should be
arrays called 'firstLayerTop', 'firstLayerBottom', 'secondLayerTop',
'secondLayerBottom' etc each containg the strings from the 'pos'
elements.

This would be fine, but the problem is that I don't know how many
'Layer' elements there will be within the XML file! How can I allow for
there to be any number of 'Layer' elements and still retrieve and store
the 'pos' data (in a logical, easily retrievable manner).

I've had a good long think about it but just can't think of a solution.
Any help would be greatly appreciated!
Your situation sounds like a good candidate for the Collections classes. Are
you aware of them? The tutorial on them can be found at
http://java.sun.com/docs/books/tutorial/collections/index.html. You should
be able to set up some sort of nested structure that lets you store XML data
with these classes. I don't know your data structure well enough to give you
a specific suggestion but if you skim the first part of the tutorial, I
think you'll fgure out something suitable.
 
J

James McGill

Your situation sounds like a good candidate for the Collections classes.

It also sounds like a job for JAXB, or Castor, or even XStream, among
the many options for idiomatic binding of Java objects to XML.

Perhaps it's my golden hammer, but I certainly go straight to data
binding (I like Castor) before I even consider doing it the hard way
(e.g., JDOM or SAX).

In a situation where the goal is raw throughput performance, I would
build a parser out of the lowest level building blocks as appropriate,
but whenever I deal with XML I/O it's generally the case that data
integrity and simplicity of the code are far more important
considerations than 'performance'. And even at that, I've found the
Castor marshaller/unmarshaller to perform perfectly well (measured in
milliseconds, well within the headroom for something like a Webapp or an
EJB.)
 
S

steve_marjoribanks

Thanks Rhino, I was thinking that I might have to use something like
that but being a Java newbie I think the whole collections thing is
quite daunting at first! I'm struggling to get my head round the
problem at the moment! I was thinking of using a hashmap of arrays does
this make sense? If I use a temporary array within the iteration to
store the values of 'pos' and then at the end of each iteration loop
put that array in the hastable using the associated numbered key, could
that work?
It also sounds like a job for JAXB, or Castor, or even XStream, among
the many options for idiomatic binding of Java objects to XML.

Data binding would be good, but as part of the application I also need
to know the tree structure of the XML file and so I thought it would be
best to try and use JDOM througout.
 
P

Patricia Shanahan

Thanks Rhino, I was thinking that I might have to use something like
that but being a Java newbie I think the whole collections thing is
quite daunting at first! I'm struggling to get my head round the
problem at the moment! I was thinking of using a hashmap of arrays does
this make sense? If I use a temporary array within the iteration to
store the values of 'pos' and then at the end of each iteration loop
put that array in the hastable using the associated numbered key, could
that work?


ArrayList is often easier than an array for collecting values.

To create an array, you need to know how big it will be. You can create
an ArrayList and add entries as you find you need them.

Patricia
 
J

James McGill

To create an array, you need to know how big it will be. You can
create
an ArrayList and add entries as you find you need them.

And if you really need an array at the end of your routine, you can
convert an ArrayList to an array, but the syntax for this conversion
will definitely confuse a newbie. It might be worth giving an example.
I'd do it, but I'm afraid I'd get it wrong in my current state :)
 
S

steve_marjoribanks

Problem solved!! Managed to do it in the end using a HashMap. I created
the keys within the iteration by using an iteration counter to track
how many elements had already been processed, stored the values in an
array and then assigned the key and the array to the HashMap, and it
works :)
Here's the code if anyone's interested, probably not the most elegant
code you'll see today but it does the job ;-)


HashMap<String, float[]> layerPointArrays = new HasMap<String,
float[]>();

public void geologicalCrossSection(Element groundProfile)
{
int numberOfPoints = 0;
int numberOfLayers = 0;

// try
// {
Element geologicalCrossSection =
groundProfile.getChild("geologicalCrossSection", geotechml);
Element layers = geologicalCrossSection.getChild("layers",
geotechml);
List layersList = layers.getChildren("Layer", geotechml);
Iterator iterator1 = layersList.iterator();
numberOfLayers = layersList.size();
int layerNumber = 1;
while (iterator1.hasNext())
{
Object obj1 = iterator1.next();
Element layerElement = (Element) obj1;
Element layerTop = layerElement.getChild("layerTop", geotechml);
Element pointsTop = layerTop.getChild("Points", geotechml);
List posValuesTop = pointsTop.getChildren("pos", gml);
Iterator iterator2 = posValuesTop.iterator();
numberOfPoints = posValuesTop.size();
float[] layerTopPointsX = new float[numberOfPoints];
float[] layerTopPointsY = new float[numberOfPoints];
int i=0;
while (iterator2.hasNext())
{
Object obj = iterator2.next();
Element posElement = (Element) obj;
String pos = posElement.getText();
String[] posXY = pos.split(" ");
layerTopPointsX = Float.parseFloat(posXY[0]);
layerTopPointsY = Float.parseFloat(posXY[1]);
i++;
}
String hashLabel = "layer" + layerNumber + "TopX";
layerPointArrays.put(hashLabel, layerTopPointsX);
hashLabel = "layer" + layerNumber + "TopY";
layerPointArrays.put(hashLabel, layerTopPointsY);

Element layerBottom = layerElement.getChild("layerBottom",
geotechml);
if (layerBottom != null)
{
Element pointsBottom = layerBottom.getChild("Points", geotechml);
List posValuesBottom = pointsBottom.getChildren("pos", gml);
Iterator iterator3 = posValuesBottom.iterator();
numberOfPoints = posValuesBottom.size();
float[] layerBottomPointsX = new float[numberOfPoints];
float[] layerBottomPointsY = new float[numberOfPoints];
int j=0;
while (iterator3.hasNext())
{
Object obj = iterator3.next();
Element posElement = (Element) obj;
String pos = posElement.getText();
String[] posXY = pos.split(" ");
layerBottomPointsX[j] = Float.parseFloat(posXY[0]);
layerBottomPointsY[j] = Float.parseFloat(posXY[1]);
j++;
}
hashLabel = "layer" + layerNumber + "BottomX";
layerPointArrays.put(hashLabel, layerBottomPointsX);
hashLabel = "layer" + layerNumber + "BottomY";
layerPointArrays.put(hashLabel, layerBottomPointsY);
}
else
{
// Do nothing
}
layerNumber++;
}
// }
// catch (NullPointerException exception)
// {
// ErrorDialogBox edb = new ErrorDialogBox();
// edb.dialogBox("Error: " + exception.getMessage(), "Error");
// }
 
S

steve_marjoribanks

Ok, new problem!!

I am retrieving the arrays from the hashmap in the above code, so i'll
get an array of the X point coords and an array of the Y point coords
for each 'layer'.

I want to draw the line represented by these points in a JPanel so I am
using a GeneralPath and looping through the arrays to get the
coordinates and draw the line. This would all be fine if there was only
one 'layer'.

If there is more than one how can I identify each line? Athe the moment
I have the following code to retrieve the values:


// get number of soil layers
int numberOfLayers = XMLParser.numberofLayers;
for (int i=1; i<=numberOfLayers; i++)
{
String hashLabel = "layer" + i + "TopX";
float[] topDataX = XMLParser.layerPointArraysTop.get(hashLabel);
hashLabel = "layer" + i + "TopY";
float[] topDataY = XMLParser.layerPointArraysTop.get(hashLabel);



and then I will use something like this to draw the line,



GeneralPath ??? = new GeneralPath();
???.moveTo(XMLParser.phreaticSurfacePointsX[0],
XMLParser.phreaticSurfacePointsY[0]);
for (int i=1; i<=XMLParser.phreaticSurfacePointsx.length; i++)
{
???.lineTo(XMLParser.phreaticSurfacePointsX,
XMLParser.phreaticSurfacePointsY);
}


But my question is, how can I give a name, (??? in the example above)
to each layer?
I don't think it will let me draw more than one line otherwise because
all the lines will have the same name if I specify a name, yet it is
not possible to change the variable name is it?!

Thanks,
Steve
 
S

steve_marjoribanks

Oops, ignore the obvious typo of me using different array name in the
above code, the last ones should read XMLParser.layerPointArraysTop as
well!!!

ps. XMLParser is the class where the HashMap is declared;
 
S

steve_marjoribanks

Correction to my correction! Should be topDataX and topDataY!! 3rd
time right :-S, damn i',m having a crap day!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,787
Messages
2,569,629
Members
45,329
Latest member
InezZ76898

Latest Threads

Top