import java.io.*; 
//import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.StringTokenizer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;


// For Java3D stuff
import javax.vecmath.*;


// import java content classes generated by binding compiler
import DDLSchema.*;

 
public class DDD {
     
	Matrix3d []	rotM;
	String [] rotMnames;
	JAXBContext jc;
	Unmarshaller u;

	int nRotMatrices;
	int nVolumes;
	int nPosParts;
	
	String filecontext;

	Vector constants;

	String [] volumeNames;
	String [] volumeShapes;
	float [][] volumeParams;

	String [] posParent;
	String [] posChild;
	String [] posCopy;
	boolean [] posRotationPresent;
	boolean [] posTranslationPresent;
	int [] posRotation;
	double [] posTranslationX;
	double [] posTranslationY;
	double [] posTranslationZ;

	double deg2rad = (Math.PI / 180.);

	public void clear() {
		volumeNames = null;
		volumeShapes = null;
		volumeParams = null;
		posParent = null;
		posChild = null;
		posRotationPresent = null;
		posTranslationPresent = null;
		posRotation = null;
		posTranslationX = null;
		posTranslationY = null;
		posTranslationZ = null;
	}

	public double evaluateExpression(String text) {
		String savetext = new String(text);

		while(text.indexOf("[") > -1) {
			int i1 = text.indexOf("[");
			int i2 = text.indexOf("]");
			
			if(i2 == -1 || i2 < i1) {
				System.err.println("Error evaluating "+savetext);
				return 0;
			}
			
			String cons = text.substring(i1+1,i2);

			if(cons.indexOf(":") == -1) {
				cons = filecontext+":"+cons;
			}

			double value = 0;

			for(int i=0;i<constants.size();i++) {
				DDDConstant con = (DDDConstant) constants.get(i);
				if(con.name.equals(cons)) {
					value = con.value;
					break;
				}
			}

			text = text.substring(0,i1)+value+text.substring(i2+1);
		}

		System.out.println("Expression "+savetext+" = "+text);

		return eval(text);

	}


	double eval(String text) {

		System.out.println("Eval: "+text);
		text = text.trim();
		while(text.indexOf("(") > -1) {
			int i1 = text.indexOf("(");
			int ib = 1;
			for(int i=i1+1;i<text.length();i++) {
				if(text.substring(i,i+1).equals("(")) ib++;
				if(text.substring(i,i+1).equals(")")) ib--;
				if(ib == 0) {
					double value = eval(text.substring(i1+1,i));
					text = text.substring(0,i1) + value + text.substring(i+1);
					break;
				}
			}
		}

		// remove all blanks from the string
		while(text.indexOf(" ") > -1) {
			int i1 = text.indexOf(" ");
			text = text.substring(0,i1-1) + text.substring(i1+1);
		}

		// Now we have an expression without brackets, which we need to evaluate
		// First get the operands

		StringTokenizer ST = new StringTokenizer(text,"+-/*");
		int nOperands = ST.countTokens();

		if(nOperands == 1) {
			return Double.valueOf(text).doubleValue();
		}

		String [] operand = new String[nOperands];

		nOperands = 0;
		while(ST.hasMoreTokens()) {
			operand[nOperands++] = new String(ST.nextToken());
		}


	
		// need to treat the operators in precedence
		// first *

		while(text.lastIndexOf("*") > -1) {
			int i1 = text.lastIndexOf("*");
			String textRight = text.substring(i1+1);
			String textLeft = text.substring(0,i1);
			double valueRight = 0;
			double valueLeft = 0;
			int is = 0;
			int ie = 0;
			for(int i=0;i<nOperands;i++) {
				if(textRight.startsWith(operand[i])) {
					valueRight = Double.valueOf(operand[i]).doubleValue();
					ie = i1 + operand[i].length();
					break;
				}
				if(textLeft.endsWith(operand[i])) {
					valueLeft = Double.valueOf(operand[i]).doubleValue();
					is = i1 - operand[i].length();
					continue;
				}
			}			
			// calculate the new value and replace it in the string
			valueLeft *= valueRight;
			text = text.substring(0,is) + valueLeft + text.substring(ie);
		}

		// now /

		while(text.lastIndexOf("/") > -1) {
			int i1 = text.lastIndexOf("/");
			String textRight = text.substring(i1+1);
			String textLeft = text.substring(0,i1);
			double valueRight = 0;
			double valueLeft = 0;
			int is = 0;
			int ie = 0;
			for(int i=0;i<nOperands;i++) {
				if(textRight.startsWith(operand[i])) {
					valueRight = Double.valueOf(operand[i]).doubleValue();
					ie = i1 + operand[i].length();
					break;
				}
				if(textLeft.endsWith(operand[i])) {
					valueLeft = Double.valueOf(operand[i]).doubleValue();
					is = i1 - operand[i].length();
					continue;
				}
			}			
			// calculate the new value and replace it in the string
			valueLeft /= valueRight;
			text = text.substring(0,is) + valueLeft + text.substring(ie);
		}

		// now -

		while(text.lastIndexOf("-") > -1) {
			int i1 = text.lastIndexOf("-");
			String textRight = text.substring(i1+1);
			String textLeft = text.substring(0,i1);
			double valueRight = 0;
			double valueLeft = 0;
			int is = 0;
			int ie = 0;
			for(int i=0;i<nOperands;i++) {
				if(textRight.startsWith(operand[i])) {
					valueRight = Double.valueOf(operand[i]).doubleValue();
					ie = i1 + operand[i].length();
					break;
				}
				if(textLeft.endsWith(operand[i])) {
					valueLeft = Double.valueOf(operand[i]).doubleValue();
					is = i1 - operand[i].length();
					continue;
				}
			}			
			// calculate the new value and replace it in the string
			valueLeft -= valueRight;
			text = text.substring(0,is) + valueLeft + text.substring(ie);
		}

		// now +

		while(text.lastIndexOf("+") > -1) {
			int i1 = text.lastIndexOf("+");
			String textRight = text.substring(i1+1);
			String textLeft = text.substring(0,i1);
			double valueRight = 0;
			double valueLeft = 0;
			int is = 0;
			int ie = 0;
			for(int i=0;i<nOperands;i++) {
				if(textRight.startsWith(operand[i])) {
					valueRight = Double.valueOf(operand[i]).doubleValue();
					ie = i1 + operand[i].length();
					break;
				}
				if(textLeft.endsWith(operand[i])) {
					valueLeft = Double.valueOf(operand[i]).doubleValue();
					is = i1 - operand[i].length();
					continue;
				}
			}			
			// calculate the new value and replace it in the string
			valueLeft += valueRight;
			text = text.substring(0,is) + valueLeft + text.substring(ie);
		}

		System.out.println("Returning: "+text);
		
		return Double.valueOf(text).doubleValue();

	}	


	public double dt2double(String text) {
		// for decoding angles
		String number = text.substring(0,text.indexOf("*"));
		return Double.valueOf(number).doubleValue();
	}

	public double lt2double(String text) {
		// for decoding lengths

		// first check if embedded constants
		if(text.indexOf("[") > -1) return evaluateExpression(text);

		text = text.trim();
		String number = text.substring(0,text.indexOf("*"));
		String units = text.substring(text.indexOf("*")+1);
		double value = Double.valueOf(number).doubleValue();
		// convert to centimetres
		if(units.equals("m")) {
			value *= 100.;
		} else if(units.equals("mm")) {
			value *= 0.1;
		} else if(units.equals("fm")) {
			// femtometers = 10-9
			value /= 10000000.0;
		} else if(units.equals("mum")) {
			// micrometers = 10-6
			value /= 10000.0;
		} else if(units.equals("cm")) {
		} else {
			System.err.println("Error decoding "+text);
		}

		return value;
	}

    public static void main( String[] args ) {

		DDD app = new DDD();

	}

	public DDD() {

        try {

            jc = JAXBContext.newInstance("DDLSchema");            
            
        } catch( JAXBException je ) {
            je.printStackTrace();
        }
    }

	public void loadRotations() {

		if(jc == null) return;

        try {

            // create an Unmarshaller
            u = jc.createUnmarshaller();
            
            // unmarshal a po instance document into a tree of Java content

			System.out.println("Decoding rotations.xml");

			ClassLoader cl = ResourceAnchor.class.getClassLoader();

			InputStream is = cl.getResourceAsStream("rotations.xml");
			
			if(is == null) {
				System.out.println("rotations.xml not loaded as resource");
				return;
			}
							

            DDDefinition ddd = (DDDefinition) u.unmarshal( is );


			java.util.List sectionList = ddd.getSection();

			System.out.println("XML contains "+sectionList.size()+" sections");

			for(int i=0;i<sectionList.size();i++) {

				SectionType section = (SectionType) sectionList.get(i);
				System.out.println("Section "+i+" Label "+section.getLabel());

				try {
					// try cast to a Rotation section
					RotationSectionType rotationSection = (RotationSectionType) section;
					System.out.println("Rotation Section");

					java.util.List rotationList = rotationSection.getRotation();
					java.util.List refRotationList = rotationSection.getReflectionRotation();

					nRotMatrices = rotationList.size() + refRotationList.size();

					System.out.println(" PosPart Section contains "+nRotMatrices+" rotations");

					rotM = new Matrix3d[nRotMatrices];
					rotMnames = new String[nRotMatrices];

					int irot;

					for(irot=0;irot<rotationList.size();irot++) {

						RotationType rotType = (RotationType) rotationList.get(irot);

						rotMnames[irot] = new String(rotType.getName());

						double thetaX = (double) deg2rad * dt2double(rotType.getThetaX());
						double phiX   = (double) deg2rad * dt2double(rotType.getPhiX());

						double thetaY = (double) deg2rad * dt2double(rotType.getThetaY());
						double phiY   = (double) deg2rad * dt2double(rotType.getPhiY());

						double thetaZ = (double) deg2rad * dt2double(rotType.getThetaZ());
						double phiZ   = (double) deg2rad * dt2double(rotType.getPhiZ());

						rotM[irot] = new Matrix3d();
						rotM[irot].setIdentity();

						rotM[irot].m00 = Math.cos(phiX) * Math.sin(thetaX);
						rotM[irot].m10 = Math.sin(phiX) * Math.sin(thetaX);
						rotM[irot].m20 = Math.cos(thetaX);

						rotM[irot].m01 = Math.cos(phiY) * Math.sin(thetaY);
						rotM[irot].m11 = Math.sin(phiY) * Math.sin(thetaY);
						rotM[irot].m21 = Math.cos(thetaY);

						rotM[irot].m02 = Math.cos(phiZ) * Math.sin(thetaZ);
						rotM[irot].m12 = Math.sin(phiZ) * Math.sin(thetaZ);
						rotM[irot].m22 = Math.cos(thetaZ);


					}

					for(irot=rotationList.size();irot<nRotMatrices;irot++) {

						RotationType rotType = (RotationType) refRotationList.get(irot-rotationList.size());

						rotMnames[irot] = new String(rotType.getName());

						double thetaX = (double) deg2rad * dt2double(rotType.getThetaX());
						double phiX   = (double) deg2rad * dt2double(rotType.getPhiX());

						double thetaY = (double) deg2rad * dt2double(rotType.getThetaY());
						double phiY   = (double) deg2rad * dt2double(rotType.getPhiY());

						double thetaZ = (double) deg2rad * dt2double(rotType.getThetaZ());
						double phiZ   = (double) deg2rad * dt2double(rotType.getPhiZ());

						rotM[irot] = new Matrix3d();
						rotM[irot].setIdentity();

						rotM[irot].m00 = Math.cos(phiX) * Math.sin(thetaX);
						rotM[irot].m10 = Math.sin(phiX) * Math.sin(thetaX);
						rotM[irot].m20 = Math.cos(thetaX);

						rotM[irot].m01 = Math.cos(phiY) * Math.sin(thetaY);
						rotM[irot].m11 = Math.sin(phiY) * Math.sin(thetaY);
						rotM[irot].m21 = Math.cos(thetaY);

						rotM[irot].m02 = Math.cos(phiZ) * Math.sin(thetaZ);
						rotM[irot].m12 = Math.sin(phiZ) * Math.sin(thetaZ);
						rotM[irot].m22 = Math.cos(thetaZ);


					}

					System.out.println(nRotMatrices+" rotations decoded");

					continue;
				} catch (ClassCastException e) {

					
				}
			}
            
        } catch( JAXBException je ) {
            je.printStackTrace();
        //} catch( IOException ioe ) {
        //   ioe.printStackTrace();
        }
	}

	public int getNumMatrices() {
		return nRotMatrices;
	}

	public Matrix3d [] getRotMatrices() {
		return rotM;
	}

	public int getNumVolumes() {
		return nVolumes;
	}

	public String getVolumeName(int i) {
		return volumeNames[i];
	}

	public String getVolumeShape(int i) {
		return volumeShapes[i];
	}

	public float [] getVolumeParams(int i) {
		return (float []) volumeParams[i];
	}

	public int getNumPosParts() {
		return nPosParts;
	}

	public String getPosParent(int i) {
		return posParent[i];
	}

	public String getPosCopy(int i) {
		return posCopy[i];
	}

	public String getPosChild(int i) {
		return posChild[i];
	}

	public int getPosRotation(int i) {
		return posRotation[i];
	}

	public Vector3d getPosTranslation(int i) {
		return new Vector3d(posTranslationX[i],posTranslationY[i],posTranslationZ[i]);
	}


	public boolean getPosRotationPresent(int i) {
		return posRotationPresent[i];
	}

	public boolean getPosTranslationPresent(int i) {
		return posTranslationPresent[i];
	}


	public void open(String filename) {

		String fileprefix = "";

        try {

			System.out.println("\nDecoding "+filename);

			ClassLoader cl = ResourceAnchor.class.getClassLoader();

			InputStream is = cl.getResourceAsStream(filename);
			
			if(is == null) {
				System.out.println(filename+" not loaded as resource");
				return;
			}
							
			filecontext = filename.substring(0,filename.indexOf("."));

            //DDDefinition ddd = (DDDefinition) u.unmarshal( new FileInputStream(filename) );
            DDDefinition ddd = (DDDefinition) u.unmarshal( is );

			java.util.List sectionList = ddd.getSection();

			System.out.println("XML contains "+sectionList.size()+" sections");

			for(int i=0;i<sectionList.size();i++) {

				SectionType section = (SectionType) sectionList.get(i);
				System.out.println("Section "+i+" Label "+section.getLabel());

				try {
					// try cast to a Constants section

					ConstantsSectionType constantsSection = (ConstantsSectionType) section;
					System.out.println("Constants Section");

					java.util.List conList = constantsSection.getConstant();

					System.out.println(" Constants Section contains "+conList.size()+" constants");

					if(constants == null) {
						constants = new Vector();
					}

					for(int j=0;j<conList.size();j++) {

						ParameterType thiscon = (ParameterType) conList.get(j);
						String name = new String(filecontext+":"+thiscon.getName());
						double value = lt2double(thiscon.getValue());

						DDDConstant con = new DDDConstant(name,value);

						constants.addElement(con);

						System.out.println(name+" = "+value);

					}
					continue;

				} catch (ClassCastException e) {
					System.out.println("cast failed: try next section");
				}


				try {
					// try cast to a PosPart section

					PosPartSectionType posPartSection = (PosPartSectionType) section;
					System.out.println("PosPart Section");

					java.util.List posList = posPartSection.getPosPart();

					System.out.println(" PosPart Section contains "+posList.size()+" pos parts");

					nPosParts = posList.size();

					posParent = new String[nPosParts];
					posChild = new String[nPosParts];
					posCopy = new String[nPosParts];
					posRotationPresent = new boolean[nPosParts];
					posRotation = new int[nPosParts];
					posTranslationPresent = new boolean[nPosParts];
					posTranslationX = new double[nPosParts];
					posTranslationY = new double[nPosParts];
					posTranslationZ = new double[nPosParts];

					for(int j=0;j<posList.size();j++) {

						PosPartType thispart = (PosPartType) posList.get(j);

						//System.out.print(" PosPart "+j+" Copy "+thispart.getCopyNumber());

						ReferenceType parent = (ReferenceType) thispart.getRParent();
						ReferenceType child = (ReferenceType) thispart.getRChild();
						ReferenceType rotref = (ReferenceType) thispart.getRRotation();
						TranslationType translation = (TranslationType) thispart.getTranslation();

						posTranslationPresent[j] = false;
						posRotationPresent[j] = false;

						posCopy[j] = thispart.getCopyNumber();

						if(parent != null) {
							posParent[j] = new String(parent.getName());
							posParent[j] = posParent[j].substring(posParent[j].indexOf(":")+1);
						} else {
							posParent[j] = new String("NULL");
						}
						if(child != null) {
							posChild[j] = new String(child.getName());
							posChild[j] = posChild[j].substring(posChild[j].indexOf(":")+1);
						} else {
							posChild[j] = new String("NULL");
						}
						if(rotref != null) {
							posRotationPresent[j] = true;
							String rotname = rotref.getName();
							rotname = rotname.substring(rotname.indexOf(":")+1);
							int kindex = -1;
							for(int k=0;k<nRotMatrices;k++) {
								if(rotname.equals(rotMnames[k])) {
									kindex = k;
									break;
								}
							}
							if(kindex == -1) {
								System.err.println("Error finding rotation "+rotname);
							}
							posRotation[j] = kindex;
						} 
						if(translation != null) {
							posTranslationX[j] = lt2double(translation.getX());
							posTranslationY[j] = lt2double(translation.getY());
							posTranslationZ[j] = lt2double(translation.getZ());
							posTranslationPresent[j] = true;
						} 

					}
					continue;

				} catch (ClassCastException e) {
					System.out.println("cast failed: try next section");
				}


				try {
					// try cast to a solid section
					SolidSectionType solidSection = (SolidSectionType) section;
					System.out.println("Solid Section");

					java.util.List solidList = solidSection.getSolid();

					System.out.println(" Solid Section contains "+solidList.size()+" solids");

					nVolumes = solidList.size();

					volumeNames = new String[nVolumes];
					volumeShapes = new String[nVolumes];
					volumeParams = new float[nVolumes][100];

					for(int j=0;j<solidList.size();j++) {

						SolidType solidType = (SolidType) solidList.get(j);
						//System.out.print(" Solid "+j+" Name "+solidType.getName());

						volumeNames[j] = new String(solidType.getName());
						volumeNames[j] = volumeNames[j].substring(volumeNames[j].indexOf(":")+1);

						volumeShapes[j] = new String("BRIK");
						for(int k=0;k<100;k++) {
							volumeParams[j][k] = 0.0f;
						}

						try {

							// Try for PCON

							PolyconeType polycone = (PolyconeType) solidType;
							volumeShapes[j] = new String("PCON");

							volumeParams[j][0] = (float) dt2double(polycone.getStartPhi());
							volumeParams[j][1] = (float) dt2double(polycone.getDeltaPhi());

							java.util.List RZPointList = polycone.getRZPoint();
							java.util.List ZSectionList = polycone.getZSection();

							volumeParams[j][2] = (float) ZSectionList.size();

							for(int k=0;k<RZPointList.size();k++) {
								//RZPointType rzpoint = (RZPointType) RZPointList.get(k);
							}

							if(RZPointList.size() > 0) {
								System.err.println("Error PCON volume "+j);
							}

							int ips = 3;
							for(int k=0;k<ZSectionList.size();k++) {
								ZSectionType zsection = (ZSectionType) ZSectionList.get(k);
								volumeParams[j][ips++] = (float) lt2double(zsection.getZ());
								volumeParams[j][ips++] = (float) lt2double(zsection.getRMin());
								volumeParams[j][ips++] = (float) lt2double(zsection.getRMax());
							}

							System.out.print("PCON "+volumeNames[j]);
							for(int k=0;k<ips;k++) {
								System.out.print(" p["+k+"]="+(float)volumeParams[j][k]);
							}
							System.out.println(" ");
							
							continue;

						} catch(ClassCastException e) {
						}

						try {

							// Try for PGON

							PolyhedraType polyhedra = (PolyhedraType) solidType;
							volumeShapes[j] = new String("PGON");

							volumeParams[j][0] = (float) dt2double(polyhedra.getStartPhi());
							volumeParams[j][1] = (float) dt2double(polyhedra.getDeltaPhi());
							volumeParams[j][2] = (float) (polyhedra.getNumSide()).intValue();

							java.util.List RZPointList = polyhedra.getRZPoint();
							java.util.List ZSectionList = polyhedra.getZSection();

							volumeParams[j][3] = (float) ZSectionList.size();

							for(int k=0;k<RZPointList.size();k++) {
								//RZPointType rzpoint = (RZPointType) RZPointList.get(k);
							}

							if(RZPointList.size() > 0) {
								System.err.println("Error PGON volume "+j);
							}

							int ips = 4;
							for(int k=0;k<ZSectionList.size();k++) {
								ZSectionType zsection = (ZSectionType) ZSectionList.get(k);
								volumeParams[j][ips++] = (float) lt2double(zsection.getZ());
								volumeParams[j][ips++] = (float) lt2double(zsection.getRMin());
								volumeParams[j][ips++] = (float) lt2double(zsection.getRMax());
							}
							
							System.out.print("PGON "+volumeNames[j]);
							for(int k=0;k<ips;k++) {
								System.out.print(" p["+k+"]="+(float)volumeParams[j][k]);
							}
							System.out.println(" ");

							continue;

						} catch(ClassCastException e) {
						}


						try {

							// Try for CONS
							ConeType cone = (ConeType) solidType;
							volumeShapes[j] = new String("CONS");

							volumeParams[j][0] = (float) lt2double(cone.getDz());
							volumeParams[j][1] = (float) lt2double(cone.getRMin1());
							volumeParams[j][2] = (float) lt2double(cone.getRMax1());
							volumeParams[j][3] = (float) lt2double(cone.getRMin2());
							volumeParams[j][4] = (float) lt2double(cone.getRMax2());
							volumeParams[j][5] = (float) dt2double(cone.getStartPhi());
							volumeParams[j][6] = volumeParams[j][5] +
												 (float) dt2double(cone.getDeltaPhi());

							System.out.print("CONS "+volumeNames[j]);
							for(int k=0;k<7;k++) {
								System.out.print(" p["+k+"]="+(float)volumeParams[j][k]);
							}
							System.out.println(" ");
							
							continue;

						} catch(ClassCastException e) {
						}


						try {

							// Try for TUBS
							TubsType tubs = (TubsType) solidType;
							volumeShapes[j] = new String("TUBS");

							volumeParams[j][0] = (float) lt2double(tubs.getRMin());
							volumeParams[j][1] = (float) lt2double(tubs.getRMax());
							volumeParams[j][2] = (float) lt2double(tubs.getDz());
							volumeParams[j][3] = (float) dt2double(tubs.getStartPhi());
							volumeParams[j][4] = volumeParams[j][3] +
												 (float) dt2double(tubs.getDeltaPhi());

							System.out.print("TUBS "+volumeNames[j]);
							for(int k=0;k<5;k++) {
								System.out.print(" p["+k+"]="+(float)volumeParams[j][k]);
							}
							System.out.println(" ");

							
							continue;

						} catch(ClassCastException e) {
						}
						
						try {

							// Try for TRAP
							TrapezoidType trap = (TrapezoidType) solidType;
							volumeShapes[j] = new String("TRAP");

							volumeParams[j][0] = (float) lt2double(trap.getDz());
							volumeParams[j][1] = (float) dt2double(trap.getTheta());
							volumeParams[j][2] = (float) dt2double(trap.getPhi());
							volumeParams[j][3] = (float) lt2double(trap.getH1());
							volumeParams[j][4] = (float) lt2double(trap.getBl1());
							volumeParams[j][5] = (float) lt2double(trap.getTl1());
							volumeParams[j][6] = (float) dt2double(trap.getAlp1());
							volumeParams[j][7] = (float) lt2double(trap.getH2());
							volumeParams[j][8] = (float) lt2double(trap.getBl2());
							volumeParams[j][9] = (float) lt2double(trap.getTl2());
							volumeParams[j][10] = (float) dt2double(trap.getAlp2());

							System.out.print("TRAP "+volumeNames[j]);
							for(int k=0;k<11;k++) {
								System.out.print(" p["+k+"]="+(float)volumeParams[j][k]);
							}
							System.out.println(" ");

							continue;

						} catch(ClassCastException e) {
						}

						
						try {

							// Try for TRD1
							Trd1Type trd1 = (Trd1Type) solidType;
							volumeShapes[j] = new String("TRD1");

							volumeParams[j][0] = (float) lt2double(trd1.getDx1());
							volumeParams[j][1] = (float) lt2double(trd1.getDx2());
							volumeParams[j][2] = (float) lt2double(trd1.getDy1());
							// hmmm what is dy2 ?
							volumeParams[j][3] = (float) lt2double(trd1.getDz());

							if(!trd1.getDy1().equals(trd1.getDy2())) {
								System.err.println("Error parsing TRD1 volume "+j);
							}
							

							System.out.print("TRD1 "+volumeNames[j]);
							for(int k=0;k<4;k++) {
								System.out.print(" p["+k+"]="+(float)volumeParams[j][k]);
							}
							System.out.println(" ");

							continue;

						} catch(ClassCastException e) {
						}
						
						try {

							// Try for BOX
							BoxType box = (BoxType) solidType;
							volumeShapes[j] = new String("BRIK");

							volumeParams[j][0] = (float) lt2double(box.getDx());
							volumeParams[j][1] = (float) lt2double(box.getDy());
							volumeParams[j][2] = (float) lt2double(box.getDz());
							
							System.out.print("BOX "+volumeNames[j]);
							for(int k=0;k<3;k++) {
								System.out.print(" p["+k+"]="+(float)volumeParams[j][k]);
							}
							System.out.println(" ");

							continue;

						} catch(ClassCastException e) {
						}


						try {

							// Try for BooleanSolid
							// This will be treated specially

							BooleanSolidType bool = (BooleanSolidType) solidType;

							java.util.List boolList = (java.util.List) bool.getRSolid();
							if(boolList.size() != 2) {
								System.err.println("Bad boolean solid");
								continue;
							}

							ReferenceType volA = (ReferenceType) boolList.get(0);
							ReferenceType volB = (ReferenceType) boolList.get(1);

							String nameA = volA.getName();
							nameA = nameA.substring(nameA.indexOf(":")+1);
							 
							// Find volume nameA and simply copy it, ignoring the boolean operation

							boolean found = false;
							for(int k=0;k<j;k++) {
								if(volumeNames[k].equals(nameA)) {
									found = true;
									System.out.println("Boolean "+volumeNames[j]+" will be copy of "+nameA);
									volumeShapes[j] = volumeShapes[k];
									for(int l=0;l<100;l++) volumeParams[j][l] = volumeParams[k][l];
									break;
								}
							}
							if(!found) {
								System.err.println("Cannot find solid "+nameA+" for Boolean");
								continue;
							}

							continue;

						} catch(ClassCastException e) {
						}

						
						System.err.println("Untreated shape "+j);

					}
					continue;
				} catch (ClassCastException e) {
					System.out.println("cast failed: try next section");					
				}

				System.out.println("Unknown Section type :-( ");

			}

            
        } catch( JAXBException je ) {
            je.printStackTrace();
        }
    }


	public class DDDConstant {
		public String name;
		public double value;

		DDDConstant(String _name, double _value) {
			name = new String(_name);
			value = _value;
		}
	}
}


