View Javadoc

1   //-------------------------------------------------------------------------
2   // FILE: XmlToNativeDomImpl.java
3   // PACKAGE: org.astrogrid.ace.utils
4   //
5   // DATE       AUTHOR    NOTES
6   // ----       ------    -----
7   // 14/10/02   KEA       Initial prototype
8   // 04/12/02   KEA       Revised to deal with new Ace Schema (v.1_0).
9   //                      NB this is an interim release.
10  // 13/12/02   KEA       Added support for new "Wavelength" XML tag
11  //-------------------------------------------------------------------------
12  
13  
14  package org.astrogrid.ace.utils;
15  
16  import org.w3c.dom.Document;
17  import org.w3c.dom.Element;
18  import org.w3c.dom.NodeList;
19  import org.w3c.dom.Node;
20  
21  import org.apache.xerces.parsers.DOMParser;
22  import org.xml.sax.InputSource;
23  
24  import java.util.Map;
25  import java.util.Iterator;
26  import java.util.TreeMap;
27  import java.util.Vector;
28  
29  import java.io.Reader;
30  import java.io.Writer;
31  
32  
33  /***
34   * <p>DOM-parser based implementation of file format converter for 
35   * conversions from Ace XML format to SExtractor native parameter 
36   * files.
37   *
38   * <p>This version uses the Xerces DOM parser;  an alternative 
39   * would be to try IBM's xml4j (a progenitor of Xerces but
40   * undergoing separate development).
41   *
42   * <p> In this interim version, the following output catalog vector
43   * parameters <strong>are</strong> supported:
44   * <ul>
45   * <li> MAG_APER(n) </li>
46   * <li> MAGERR_APER(n) </li>
47   * <li> FLUX_APER(n) </li>
48   * <li> FLUXERR_APER(n) </li>
49   * </ul>
50   *
51   * but the following output catalog vector parameters are
52   * <strong>not</strong> supported:
53   *
54   * <ul>
55   * <li> VECTOR_SOMFIT(n) </li>
56   * <li> VECTOR_ASSOC(n) </li>
57   * <li> FLUX_GROWTH(n) </li>
58   * <li> VIGNET(m,n) </li>
59   * <li> VIGNET_SHIFT(m,n) </li>
60   * </ul>
61   *
62   *
63   * <p>See Translator.java for a usage example, and Tester.java 
64   * for a run-time test harness.
65   * 
66   * <p>TO DO:  <ul>
67   * <li>Handle <strong>all</strong>SExtractor vector catalog parameters, 
68   *  not just a subset.</li>
69   * <li>Nicer exception-throwing and handling?</li>
70   * </ul>
71   *
72   *
73   * @see org.astrogrid.ace.utils.XmlToNativeIfc
74   * @see org.astrogrid.ace.utils.Translator 
75   * @see org.astrogrid.ace.utils.Tester 
76   * 
77   * @author Kona Andrews,
78   * <a href="mailto:kea@ast.cam.ac.uk">kea@ast.cam.ac.uk</a>
79   * @version 1.0
80  */
81  public class XmlToNativeDomImpl implements XmlToNativeIfc
82  {
83  	// Utility variable for calculating vector values for certain
84  	// output parameters.
85  	//
86  	private int numPhotApertures = -1;
87  
88  	/***
89  	 * Dummy constructor - does nothing.
90  	 */
91  	 public XmlToNativeDomImpl()
92  	 {
93  	 }
94  
95  	/***
96  	 * Parses ACE XML input into a DOM tree.
97  	 * 
98  	 * @param xmlIn  A (pre-initialised) reader for the input XML
99  	 *
100 	 * @return  A Document containing the DOM tree for the input XML.
101 	 */
102 	 protected Document getDOMTree(Reader inputXML) throws Exception
103 	 {
104 		DOMParser parser = new DOMParser();
105 		try 
106 		{
107 			parser.setFeature("http://xml.org/sax/features/namespaces", false);
108 			parser.setFeature(
109 				"http://apache.org/xml/features/dom/include-ignorable-whitespace",
110 				false);
111 		}
112 		catch (Exception e) 
113 		{
114 			throw new Exception(
115 			"\nThis parser cannot process a requested feature: \n"
116 			+ e.getMessage());
117 		}
118 		parser.parse(new InputSource(inputXML));
119 		return parser.getDocument();
120 	 }
121 	
122 	/***
123 	 * Converts Ace XML input to SExtractor output (configuration
124 	 * file *.sex and catalog parameter file *.param).
125 	 * 
126 	 * Parses the Ace XML input into a DOM Tree, then traverses this
127 	 * tree to produce the configuration and catalog parameter files.
128 	 * 
129 	 * @param xmlIn  A (pre-initialised) reader for the input XML
130 	 *
131 	 * @param configOutWriter  A (pre-initialised) writer for the output 
132 	 *     SExtractor *.sex * file.
133 	 *
134 	 * @param catalogOutWriter  A (pre-initialised) writer for the output 
135 	 *     SExtractor *.param file.
136 	 */
137 	public void makeNative(Reader xmlIn, Writer configOutWriter, 
138 										Writer catalogOutWriter) throws Exception
139 	{
140 		Document document = getDOMTree(xmlIn);
141 		Map configMap = new TreeMap();
142 		numPhotApertures = -1;
143 
144 		configOutWriter.write(
145 			"# Generated by org.astrogrid.ace.utils - DOM implementation\n");
146 		catalogOutWriter.write(
147 			"# Generated by org.astrogrid.ace.utils - DOM implementation\n"
148 			+ "#!WARNING! - "
149 			+ "This interim release does not support any vector parameters\n"	
150 			+ "#   except MAG_APER, MAG_APERERR, FLUX_APER AND FLUX_APERERR."
151 			);
152 
153 		// Get all children of the root element (AceInputDoc) for processing
154 		//
155 		NodeList nodeList = (document.getDocumentElement()).getChildNodes();
156 		for (int i = 0; i < nodeList.getLength(); i++) 
157 		{
158 			if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE) 
159 			{
160 				Element paramNode = (Element)(nodeList.item(i));
161 				
162             String tagName = paramNode.getTagName();
163 
164             // Check if we have a catalog parameter
165 				//
166             if ( tagName.equals("OUTPUT_COLUMNS") )
167 				{
168 					doCatalogParameter(paramNode, document.getDocumentElement(),
169 							catalogOutWriter);
170 				}
171 				// Check if we have an ignorable command-line parameter 
172 				//
173             else if ( !(tagName.equals("ImageToCatalog")) && 
174 	                   !(tagName.equals("ImageToMeasure")) &&
175 							 !(tagName.equals("Wavelength")) )
176 				{
177 					// Not command-line param, so have a config parameter
178 					// See if this is a multi-argument parameter
179 					//
180 					NodeList args = 
181 						paramNode.getElementsByTagName("arg");
182 
183 					if (args.getLength() == 0) 
184 					{
185 						throw new Exception("Error - missing <arg> for parameter "
186 								+ paramNode.getTagName());
187 					}
188 					
189 					String tagString = 
190 						args.item(0).getFirstChild().getNodeValue();
191 
192 					for (int j = 1; j < args.getLength(); j++) 
193 					{
194 						tagString = 
195 							tagString + ", " + 
196 							args.item(j).getFirstChild().getNodeValue();
197 					}
198 					configMap.put(paramNode.getTagName(),tagString);
199 				}
200 			}
201 		}
202 		// Now convert config parameters to native format 
203 		//   (catalog parameters all dealt with already).
204 
205 		// First of all, get length of longest keyword (for pretty-printing)
206 		//
207 		int maxLen = 0;
208 		Iterator iterator;
209 		for (iterator = configMap.entrySet().iterator(); iterator.hasNext(); ) 
210 		{
211 			Map.Entry me = (Map.Entry)iterator.next();
212 			int len = ((String)me.getKey()).length();
213 			if (maxLen < len) 
214 			{
215 				maxLen = len;
216 			}
217       }
218 
219 		// Now write all keywords/values to output in native format
220 		//
221 		for (iterator = configMap.entrySet().iterator(); iterator.hasNext(); ) 
222 		{
223 			Map.Entry me = (Map.Entry)iterator.next();
224 			String tagname = (String)me.getKey();
225 			String value = (String)me.getValue();
226 
227 			int numSpaces = maxLen - tagname.length();
228 
229 			// Write tag name and pretty-printing spaces
230 			configOutWriter.write(tagname + "   ");
231 			//System.out.print(tagname + "   ");
232 			
233 			for (int j = 0; j < numSpaces; j++) 
234 			{
235 				configOutWriter.write(" ");
236 				//System.out.print(" ");
237 			}
238 
239 			// Booleans are a special case (native format uses Y/N)
240 			String paramVal = value.trim();
241 			if (paramVal.equalsIgnoreCase("true")) 
242 			{
243 				configOutWriter.write("Y" + "\n");
244 				//System.out.print("Y" + "\n");
245 			}
246 			else if (paramVal.equalsIgnoreCase("false")) 
247 			{
248 				configOutWriter.write("N" + "\n");
249 				//System.out.print("N" + "\n");
250 			}
251 			else 
252 			{
253 				// All else than boolean parameters
254 				configOutWriter.write(value + "\n");
255 				//System.out.print(value + "\n");
256 			}
257 		}
258 	}
259 
260 
261 	protected void doCatalogParameter(Element paramNode, Element rootNode,
262 											 Writer catalogOutWriter) throws Exception
263 
264 	/***
265 	 * Traverses a DOM ELement node containing an Ace XML catalog 
266 	 * parameter and writes the equivalent native catalog parameter 
267 	 * to the * SExtractor catalog parameter file (*.param).
268 	 *
269 	 * @param element  The DOM element containing the Ace catalog parameter.
270 	 *
271 	 * @param element  The DOM element that is the root of the input
272 	 * document.
273 	 *
274 	 * @param catalogOutWriter  A (pre-initialised) writer for the output 
275 	 *     SExtractor *.param file.
276 	 *
277 	 * @throws Exception if inconsistencies between configuration and
278 	 * catalog parameters are encountered.
279 	 */
280 	{	
281 		String tagName = paramNode.getTagName();
282 		NodeList args = paramNode.getElementsByTagName("arg");
283 		for (int i = 0; i < args.getLength(); i++) 
284 		{
285 			String tagname = args.item(i).getFirstChild().getNodeValue();
286 
287 			// Check for currently unsupported keyword names (vector keywords)
288 			// 
289 			if ( (tagname.equals("FLUX_APER")) ||
290 				  (tagname.equals("FLUXERR_APER")) ||
291 				  (tagname.equals("MAG_APER")) ||
292 				  (tagname.equals("MAGERR_APER")) )
293 			{
294 				// Currently-supported vector parameters
295 				// Vector value of these is no. of elements in PHOT_APERTURES
296 				//
297 				if (numPhotApertures == -1) // Not set yet
298 				{
299 					NodeList photAps =
300 						rootNode.getElementsByTagName("PHOT_APERTURES");
301 					if (photAps.getLength() != 1)
302 					{
303 						throw new Exception("Error - unexpected number (" 
304 							+ Integer.toString(photAps.getLength()) 
305 							+ ") of PHOT_APERTURE tags (expected exactly 1, "
306 							+ "since output tag " + tagname + " is present.");
307 					}
308 					else 
309 					{
310 						NodeList photArgs = 
311 							((Element)photAps.item(0)).getElementsByTagName("arg");
312 						numPhotApertures = photArgs.getLength();
313 					}
314 				}
315 				catalogOutWriter.write(tagname + "(" + 
316 						Integer.toString(numPhotApertures) + ")\n");
317 
318 			}
319 
320 			else if ( (tagname.equals("VECTOR_SOMFIT")) ||
321 				  (tagname.equals("VECTOR_ASSOC")) ||
322 				  (tagname.equals("FLUX_GROWTH")) ||
323 				  (tagname.equals("VIGNET")) ||
324 				  (tagname.equals("VIGNET_SHIFT")) ) 
325 
326 			{
327 				// Not currently supported vector parameters
328 				//
329 				catalogOutWriter.write("#!WARNING! Vector parameter \"" + tagname 
330 					+ "\" is not supported in this release!\n");
331 			}
332 			else 
333 			{
334 				catalogOutWriter.write(tagname + "\n");
335 			}
336 		}
337 	}
338 }
339 //-------------------------------------------------------------------------