View Javadoc

1   package org.lcsim.geometry.compact.converter.lcdd.util;
2   
3   import java.util.ArrayList;
4   import java.util.Iterator;
5   import java.util.List;
6   
7   import org.jdom.Document;
8   import org.jdom.Element;
9   import org.jdom.JDOMException;
10  import org.lcsim.material.XMLMaterialManager;
11  
12  /**
13   * This helper class is used to export data from an XMLMaterialManager to LCDD.
14   * 
15   * @author jeremym
16   * @version $Id: LCDDMaterialHelper.java,v 1.2 2011/04/19 00:48:34 jeremy Exp $
17   */
18  public class LCDDMaterialHelper
19  {
20      XMLMaterialManager xmgr = null;
21      
22      /**
23       * Ctor for helper which will use the given {@link org.lcsim.material.XMLMaterialManager}.
24       * @param xmgr The XMLMaterialManager with material XML data.
25       */
26      public LCDDMaterialHelper(XMLMaterialManager xmgr)
27      {
28          this.xmgr = xmgr;
29      }
30      
31      /**
32       * Copy a MaterialElement node. 
33       * @param e The XML element to copy.
34       * @return The cloned XML element.
35       * @throws JDOMException
36       */
37      private static org.jdom.Element makeMaterialElement(org.jdom.Element e)
38      {
39          org.jdom.Element ee = new org.jdom.Element("element");
40          ee.addContent(e.cloneContent());
41          ee.setAttribute("name", e.getAttributeValue("name"));
42          ee.setAttribute("formula", e.getAttributeValue("formula"));
43          ee.setAttribute("Z", e.getAttributeValue("Z"));
44          return ee;
45      }
46      
47      private static Material makeMaterial(org.jdom.Element m)
48      {
49          Material mat = new Material(m.getAttributeValue("name"));
50          mat.addContent(m.cloneContent());
51          return mat;
52      }
53             
54      private void makeReferenceList(String matName, List refs)
55      {
56          if (refs == null)
57          {
58              throw new IllegalArgumentException("List cannot be null.");
59          }
60  
61          org.jdom.Element m = xmgr.getMaterialXML(matName);
62  
63          if (m != null)
64          {
65              if ("material".equals(m.getName()))
66              {
67                  List l = m.getChildren("composite");
68  
69                  if (l.isEmpty())
70                  {
71                      l = m.getChildren("fraction");
72                  }
73  
74                  if (l.isEmpty())
75                  {
76                      throw new RuntimeException("Material does not contain fraction or composite tags.");
77                  }
78  
79                  for (org.jdom.Element ce : (List<org.jdom.Element>)l)
80                  {
81                      String ref = ce.getAttributeValue("ref");
82  
83                      /* Add if element. */
84                      org.jdom.Element fnd = xmgr.getMaterialElementXML(ref);
85                      if (fnd != null)
86                      {
87                          if (!refs.contains(fnd))
88                          {
89                              refs.add(fnd);
90                          }
91                      }
92                      /* Add if material. */
93                      else
94                      {
95                          fnd = xmgr.getMaterialXML(ref);
96  
97                          /* Recursively add references of this material. */
98                          if (fnd != null)
99                          {
100                             makeReferenceList(fnd.getAttributeValue("name"), refs);
101                         }
102                     }
103                 }
104 
105                 /* Lastly, add the material that was passed in after its references are recursively resolved. */
106                 if (!refs.contains(m))
107                 {
108                     refs.add(m);
109                 }
110             }
111             else
112             {
113                 throw new IllegalArgumentException("makeReferenceList() - Material not found: " + matName);
114             }
115         }
116     }
117     
118     // DEBUG
119     private void printXMLMat()
120     {
121         System.out.println();
122         System.out.println("XMLMatMgr mats ...");
123         for (Object o : xmgr.getMaterialXMLMap().values())
124         {                       
125             org.jdom.Element e = (org.jdom.Element)o;
126             System.out.println(e.getAttributeValue("name"));
127         }
128         System.out.println();
129     }
130     
131     /** 
132      * Copy all materials into an LCDD object for output.
133      * @param lcdd The LCDD object. 
134      */
135     private void copyMaterialsToLCDD(LCDD lcdd) throws JDOMException
136     {
137         // DEBUG
138         //printXMLMat();
139         //
140         
141         for (Object o : xmgr.getMaterialXMLMap().values())
142         {                       
143             org.jdom.Element e = (org.jdom.Element)o;                      
144             Material m = makeMaterial(e);
145             lcdd.addMaterial(m);
146         }
147     }
148     
149     /**
150      * Add references to materials from a compact document to this manager.
151      * @param lccdd The compact detector.
152      * @throws JDOMException
153      */
154     private void addReferencesFromCompact(org.jdom.Element lccdd)
155     {
156         // FIXME This fixes up problem with preloaded XMgr but is just kludge.
157         this.xmgr.clearMaterialMap();
158         
159         if (lccdd == null)
160         {
161             throw new RuntimeException("The argument points to null.");
162         }
163         
164         if (lccdd.getChild("materials") == null)
165         {
166             throw new RuntimeException("No materials section found in Element.");
167         }
168         
169         org.jdom.Element materials = lccdd.getChild("materials");
170 
171         // FIXME Ugh!
172         xmgr.setMaterialsRoot(materials);
173                 
174         for (Iterator i = materials.getChildren().iterator(); i.hasNext();)
175         {
176             org.jdom.Element element = (org.jdom.Element)i.next();
177             if ("material".equals(element.getName()))
178             {
179                 addReferences(element);
180             }
181         }
182     }
183     
184     /**
185      * Recursively add the referenced materials or elements from a single material node. 
186      * This method will also look in the parent XMLMaterialManager.  
187      */
188     // FIXME Affecting the state of XMatMgr with this method is a bad idea.
189     private void addReferences(org.jdom.Element e, Document d)
190     {
191         if ("material".equals(e.getName()))
192         {
193             // Check for composite or fraction tags.
194             List l = e.getChildren("composite");
195             if (l.isEmpty())
196             {
197                 l = e.getChildren("fraction");
198             }
199             
200             if (l.isEmpty())
201             {
202                 // Bad XML.  Required tags missing.
203                 throw new RuntimeException("Material does not contain required fraction or composite tags.");
204             }
205 
206             for (org.jdom.Element ce : (List<org.jdom.Element>)l)
207             {
208                 String ref = ce.getAttributeValue("ref");
209 
210                 // Add if element.
211                 org.jdom.Element fnd = xmgr.findMaterialElementXML(ref, d);
212                 if (fnd != null)
213                 {
214                     xmgr.addMaterialElementRef(fnd);
215                 }
216                 // Add if material.
217                 else
218                 {
219                     fnd = xmgr.findMaterialXML(ref, d);
220 
221                     if (fnd != null)
222                     {
223                         // Recursively add references of this material.
224                         addReferences(fnd, d);
225                     }
226                     else
227                     {
228                         throw new RuntimeException("Material or element reference not found: " + ref);
229                     }
230                 }
231             }
232             
233             // Add original material after refs resolved.
234             xmgr.addMaterialRef(e);
235         }       
236     }
237 
238     /** 
239      * Copy material data into LCDD.
240      * @param lcdd The LCDD object. 
241      **/
242     public void copyToLCDD(LCDD lcdd) throws JDOMException
243     {
244         copyMaterialElementsToLCDD(lcdd);
245         copyMaterialsToLCDD(lcdd);
246     }
247     
248     /**
249      * Copy material elements into LCDD.
250      * @param lcdd The LCDD object.
251      */
252     private void copyMaterialElementsToLCDD(LCDD lcdd)
253     {
254         for (Object o : xmgr.getElementXMLMap().values())
255         {
256             org.jdom.Element e = (org.jdom.Element)o;
257             lcdd.addElement((org.jdom.Element)e.clone());
258         }
259     }
260     
261     /**
262      * Add material reference from a materials section.
263      * @param e The element pointing to the materials section.
264      */
265     private void addReferences(org.jdom.Element e)
266     {
267         addReferences(e, xmgr.getCurrentDocument());
268     }   
269     
270     /**
271      * Load referenced material into this manager.
272      * @param name The name of the material.
273      * @param lcdd The LCDD object to update.
274      */
275     // FIXME This is called from LCDDDetector but not sure it should be.
276     public void resolveLCDDMaterialReference(String name, LCDD lcdd)
277     {
278         List l = new ArrayList();
279 
280         makeReferenceList(name, l);
281 
282         for (Object o : l)
283         {
284             org.jdom.Element e = (org.jdom.Element)o;
285 
286             // Material.
287             if ("material".equals(e.getName()))
288             {
289                 Material m = makeMaterial(e);
290                 lcdd.addMaterial(m);
291             }
292             // Element.
293             else
294             {
295                 org.jdom.Element ee = makeMaterialElement(e);
296                 lcdd.addElement(ee);
297             }
298         }
299     }
300     
301     public void copyToLCDD(Element compact, LCDD lcdd)
302     {       
303         try 
304         {
305             // Adds references from compact file to the XMLMaterialManager.
306             addReferencesFromCompact(compact);
307     
308             // Copy materials used in the compact file to the LCDD file.
309             copyToLCDD(lcdd);
310         }
311         catch (Exception x)
312         {
313             throw new RuntimeException(x);
314         }
315     }
316 }