Java tutorial
/* ************************************************************************ ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* ************** CENTRE CANADIEN DE DONNES ASTRONOMIQUES ************** * * (c) 2011. (c) 2011. * Government of Canada Gouvernement du Canada * National Research Council Conseil national de recherches * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 * All rights reserved Tous droits rservs * * NRC disclaims any warranties, Le CNRC dnie toute garantie * expressed, implied, or nonce, implicite ou lgale, * statutory, of any kind with de quelque nature que ce * respect to the software, soit, concernant le logiciel, * including without limitation y compris sans restriction * any warranty of merchantability toute garantie de valeur * or fitness for a particular marchande ou de pertinence * purpose. NRC shall not be pour un usage particulier. * liable in any event for any Le CNRC ne pourra en aucun cas * damages, whether direct or tre tenu responsable de tout * indirect, special or general, dommage, direct ou indirect, * consequential or incidental, particulier ou gnral, * arising from the use of the accessoire ou fortuit, rsultant * software. Neither the name de l'utilisation du logiciel. Ni * of the National Research le nom du Conseil National de * Council of Canada nor the Recherches du Canada ni les noms * names of its contributors may de ses participants ne peuvent * be used to endorse or promote tre utiliss pour approuver ou * products derived from this promouvoir les produits drivs * software without specific prior de ce logiciel sans autorisation * written permission. pralable et particulire * par crit. * * This file is part of the Ce fichier fait partie du projet * OpenCADC project. OpenCADC. * * OpenCADC is free software: OpenCADC est un logiciel libre ; * you can redistribute it and/or vous pouvez le redistribuer ou le * modify it under the terms of modifier suivant les termes de * the GNU Affero General Public la GNU Affero General Public * License as published by the License? telle que publie * Free Software Foundation, par la Free Software Foundation * either version 3 of the : soit la version 3 de cette * License, or (at your option) licence, soit ( votre gr) * any later version. toute version ultrieure. * * OpenCADC is distributed in the OpenCADC est distribu * hope that it will be useful, dans lespoir quil vous * but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE * without even the implied GARANTIE : sans mme la garantie * warranty of MERCHANTABILITY implicite de COMMERCIALISABILIT * or FITNESS FOR A PARTICULAR ni dADQUATION UN OBJECTIF * PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence * General Public License for Gnrale Publique GNU Affero * more details. pour plus de dtails. * * You should have received Vous devriez avoir reu une * a copy of the GNU Affero copie de la Licence Gnrale * General Public License along Publique GNU Affero avec * with OpenCADC. If not, see OpenCADC ; si ce nest * <http://www.gnu.org/licenses/>. pas le cas, consultez : * <http://www.gnu.org/licenses/>. * * $Revision: 4 $ * ************************************************************************ */ package ca.nrc.cadc.caom2.xml; import ca.nrc.cadc.caom2.Algorithm; import ca.nrc.cadc.caom2.Artifact; import ca.nrc.cadc.caom2.CalibrationLevel; import ca.nrc.cadc.caom2.CaomEntity; import ca.nrc.cadc.caom2.Chunk; import ca.nrc.cadc.caom2.CompositeObservation; import ca.nrc.cadc.caom2.DataProductType; import ca.nrc.cadc.caom2.DataQuality; import ca.nrc.cadc.caom2.Energy; import ca.nrc.cadc.caom2.EnergyBand; import ca.nrc.cadc.caom2.EnergyTransition; import ca.nrc.cadc.caom2.Environment; import ca.nrc.cadc.caom2.Instrument; import ca.nrc.cadc.caom2.Metrics; import ca.nrc.cadc.caom2.Observation; import ca.nrc.cadc.caom2.ObservationIntentType; import ca.nrc.cadc.caom2.ObservationURI; import ca.nrc.cadc.caom2.Part; import ca.nrc.cadc.caom2.Plane; import ca.nrc.cadc.caom2.PlaneURI; import ca.nrc.cadc.caom2.Polarization; import ca.nrc.cadc.caom2.PolarizationState; import ca.nrc.cadc.caom2.Position; import ca.nrc.cadc.caom2.ProductType; import ca.nrc.cadc.caom2.Proposal; import ca.nrc.cadc.caom2.Provenance; import ca.nrc.cadc.caom2.Quality; import ca.nrc.cadc.caom2.ReleaseType; import ca.nrc.cadc.caom2.Requirements; import ca.nrc.cadc.caom2.SimpleObservation; import ca.nrc.cadc.caom2.Status; import ca.nrc.cadc.caom2.Target; import ca.nrc.cadc.caom2.TargetPosition; import ca.nrc.cadc.caom2.TargetType; import ca.nrc.cadc.caom2.Telescope; import ca.nrc.cadc.caom2.Time; import ca.nrc.cadc.caom2.types.Circle; import ca.nrc.cadc.caom2.types.Interval; import ca.nrc.cadc.caom2.types.MultiPolygon; import ca.nrc.cadc.caom2.types.Point; import ca.nrc.cadc.caom2.types.Polygon; import ca.nrc.cadc.caom2.types.SegmentType; import ca.nrc.cadc.caom2.types.SubInterval; import ca.nrc.cadc.caom2.types.Vertex; import ca.nrc.cadc.caom2.util.CaomUtil; import ca.nrc.cadc.caom2.wcs.Axis; import ca.nrc.cadc.caom2.wcs.Coord2D; import ca.nrc.cadc.caom2.wcs.CoordAxis1D; import ca.nrc.cadc.caom2.wcs.CoordAxis2D; import ca.nrc.cadc.caom2.wcs.CoordBounds1D; import ca.nrc.cadc.caom2.wcs.CoordBounds2D; import ca.nrc.cadc.caom2.wcs.CoordCircle2D; import ca.nrc.cadc.caom2.wcs.CoordError; import ca.nrc.cadc.caom2.wcs.CoordFunction1D; import ca.nrc.cadc.caom2.wcs.CoordFunction2D; import ca.nrc.cadc.caom2.wcs.CoordPolygon2D; import ca.nrc.cadc.caom2.wcs.CoordRange1D; import ca.nrc.cadc.caom2.wcs.CoordRange2D; import ca.nrc.cadc.caom2.wcs.Dimension2D; import ca.nrc.cadc.caom2.wcs.ObservableAxis; import ca.nrc.cadc.caom2.wcs.PolarizationWCS; import ca.nrc.cadc.caom2.wcs.RefCoord; import ca.nrc.cadc.caom2.wcs.Slice; import ca.nrc.cadc.caom2.wcs.SpatialWCS; import ca.nrc.cadc.caom2.wcs.SpectralWCS; import ca.nrc.cadc.caom2.wcs.TemporalWCS; import ca.nrc.cadc.caom2.wcs.ValueCoord2D; import ca.nrc.cadc.date.DateUtil; import ca.nrc.cadc.xml.XmlUtil; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.Serializable; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.text.DateFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.apache.log4j.Logger; import org.jdom2.Attribute; import org.jdom2.DataConversionException; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.Namespace; /** * * @author jburke */ public class ObservationReader implements Serializable { private static final long serialVersionUID = 201604081100L; private static final String CAOM20_SCHEMA_RESOURCE = "CAOM-2.0.xsd"; private static final String CAOM21_SCHEMA_RESOURCE = "CAOM-2.1.xsd"; private static final String CAOM22_SCHEMA_RESOURCE = "CAOM-2.2.xsd"; private static final String CAOM23_SCHEMA_RESOURCE = "CAOM-2.3.xsd"; private static final int CURRENT_CAOM2_SCHEMA_LEVEL = 23; private static final String XLINK_SCHEMA_RESOURCE = "XLINK.xsd"; private static final Logger log = Logger.getLogger(ObservationReader.class); protected boolean enableSchemaValidation; protected Map<String, String> schemaMap; protected Namespace xsiNamespace; private transient boolean initDone = false; /** * Constructor. XML Schema validation is enabled by default. */ public ObservationReader() { this(true); } /** * Constructor. XML schema validation may be disabled, in which case the * client is likely to fail in horrible ways (e.g. NullPointerException) if * it receives invalid documents. However, performance may be improved. * * @param enableSchemaValidation */ public ObservationReader(boolean enableSchemaValidation) { this.enableSchemaValidation = enableSchemaValidation; } private void init() { if (!initDone) { if (enableSchemaValidation) { String caom2SchemaUrl = XmlUtil.getResourceUrlString(CAOM20_SCHEMA_RESOURCE, ObservationReader.class); log.debug("caom-2.0 schema URL: " + caom2SchemaUrl); String caom21SchemaUrl = XmlUtil.getResourceUrlString(CAOM21_SCHEMA_RESOURCE, ObservationReader.class); log.debug("caom-2.1 schema URL: " + caom21SchemaUrl); String caom22SchemaUrl = XmlUtil.getResourceUrlString(CAOM22_SCHEMA_RESOURCE, ObservationReader.class); log.debug("caom-2.2 schema URL: " + caom22SchemaUrl); String caom23SchemaUrl = XmlUtil.getResourceUrlString(CAOM23_SCHEMA_RESOURCE, ObservationReader.class); log.debug("caom-2.3 schema URL: " + caom23SchemaUrl); String xlinkSchemaUrl = XmlUtil.getResourceUrlString(XLINK_SCHEMA_RESOURCE, ObservationReader.class); log.debug("xlinkSchemaUrl: " + xlinkSchemaUrl); if (caom2SchemaUrl == null) { throw new RuntimeException("failed to load " + CAOM20_SCHEMA_RESOURCE + " from classpath"); } if (caom21SchemaUrl == null) { throw new RuntimeException("failed to load " + CAOM21_SCHEMA_RESOURCE + " from classpath"); } if (caom22SchemaUrl == null) { throw new RuntimeException("failed to load " + CAOM22_SCHEMA_RESOURCE + " from classpath"); } if (caom23SchemaUrl == null) { throw new RuntimeException("failed to load " + CAOM23_SCHEMA_RESOURCE + " from classpath"); } if (xlinkSchemaUrl == null) { throw new RuntimeException("failed to load " + XLINK_SCHEMA_RESOURCE + " from classpath"); } schemaMap = new HashMap<String, String>(); schemaMap.put(XmlConstants.CAOM2_0_NAMESPACE, caom2SchemaUrl); schemaMap.put(XmlConstants.CAOM2_1_NAMESPACE, caom21SchemaUrl); schemaMap.put(XmlConstants.CAOM2_2_NAMESPACE, caom22SchemaUrl); schemaMap.put(XmlConstants.CAOM2_3_NAMESPACE, caom23SchemaUrl); schemaMap.put(XmlConstants.XLINK_NAMESPACE, xlinkSchemaUrl); log.debug("schema validation enabled"); } else { log.debug("schema validation disabled"); } xsiNamespace = Namespace.getNamespace("xsi", XmlConstants.XMLSCHEMA); this.initDone = true; } } private class ReadContext implements Serializable { private static final long serialVersionUID = 201604081100L; DateFormat dateFormat = DateUtil.getDateFormat(DateUtil.IVOA_DATE_FORMAT, DateUtil.UTC); int docVersion = CURRENT_CAOM2_SCHEMA_LEVEL; // allow for missing milliseconds in timestamps Date parseTimestamp(String value) throws ParseException { try { return dateFormat.parse(value); } catch (ParseException pex1) { try { // append missing milliseconds? return dateFormat.parse(value + ".000"); } catch (ParseException pex2) { throw pex1; // original } } finally { // nothing to do } } } /** * Construct an Observation from an XML String source. * * @param xml * String of the XML. * @return An Observation. * @throws ObservationParsingException * if there is an error parsing the XML. */ public Observation read(String xml) throws ObservationParsingException { if (xml == null) { throw new IllegalArgumentException("XML must not be null"); } try { return read(new StringReader(xml)); } catch (IOException ioe) { String error = "Error reading XML: " + ioe.getMessage(); throw new ObservationParsingException(error, ioe); } } /** * Construct an Observation from a InputStream. * * @param in * An InputStream. * @return An Observation. * @throws ObservationParsingException * if there is an error parsing the XML. */ public Observation read(InputStream in) throws ObservationParsingException, IOException { if (in == null) { throw new IllegalArgumentException("stream must not be null"); } try { return read(new InputStreamReader(in, "UTF-8")); } catch (UnsupportedEncodingException e) { throw new RuntimeException("UTF-8 encoding not supported"); } } /** * Construct an Observation from a Reader. * * @param reader * A Reader. * @return An Observation. * @throws ObservationParsingException * if there is an error parsing the XML. */ public Observation read(Reader reader) throws ObservationParsingException, IOException { if (reader == null) { throw new IllegalArgumentException("reader must not be null"); } init(); Document document; try { document = XmlUtil.buildDocument(reader, schemaMap); } catch (JDOMException jde) { String error = "XML failed schema validation: " + jde.getMessage(); throw new ObservationParsingException(error, jde); } // Root element and namespace of the Document Element root = document.getRootElement(); Namespace namespace = root.getNamespace(); log.debug("obs namespace uri: " + namespace.getURI()); log.debug("obs namespace prefix: " + namespace.getPrefix()); ReadContext rc = new ReadContext(); if (XmlConstants.CAOM2_0_NAMESPACE.equals(namespace.getURI())) { rc.docVersion = 20; } else if (XmlConstants.CAOM2_1_NAMESPACE.equals(namespace.getURI())) { rc.docVersion = 21; } else if (XmlConstants.CAOM2_2_NAMESPACE.equals(namespace.getURI())) { rc.docVersion = 22; } // Simple or Composite Attribute type = root.getAttribute("type", xsiNamespace); String tval = type.getValue(); String collection = getChildText("collection", root, namespace, false); String observationID = getChildText("observationID", root, namespace, false); // Algorithm. Algorithm algorithm = getAlgorithm(root, namespace, rc); // Create the Observation. Observation obs; String simple = namespace.getPrefix() + ":" + SimpleObservation.class.getSimpleName(); String comp = namespace.getPrefix() + ":" + CompositeObservation.class.getSimpleName(); if (simple.equals(tval)) { obs = new SimpleObservation(collection, observationID); obs.setAlgorithm(algorithm); } else if (comp.equals(tval)) { obs = new CompositeObservation(collection, observationID, algorithm); } else { throw new ObservationParsingException("unexpected observation type: " + tval); } // Observation children. String intent = getChildText("intent", root, namespace, false); if (intent != null) { obs.intent = ObservationIntentType.toValue(intent); } obs.type = getChildText("type", root, namespace, false); obs.metaRelease = getChildTextAsDate("metaRelease", root, namespace, false, rc.dateFormat); obs.sequenceNumber = getChildTextAsInteger("sequenceNumber", root, namespace, false); obs.proposal = getProposal(root, namespace, rc); obs.target = getTarget(root, namespace, rc); obs.targetPosition = getTargetPosition(root, namespace, rc); obs.requirements = getRequirements(root, namespace, rc); obs.telescope = getTelescope(root, namespace, rc); obs.instrument = getInstrument(root, namespace, rc); obs.environment = getEnvironment(root, namespace, rc); addPlanes(obs.getPlanes(), root, namespace, rc); if (obs instanceof CompositeObservation) { addMembers(((CompositeObservation) obs).getMembers(), root, namespace, rc); } assignEntityAttributes(root, obs, rc); return obs; } private void assignEntityAttributes(Element e, CaomEntity ce, ReadContext rc) throws ObservationParsingException { Attribute aid = e.getAttribute("id", e.getNamespace()); Attribute alastModified = e.getAttribute("lastModified", e.getNamespace()); Attribute amaxLastModified = e.getAttribute("maxLastModified", e.getNamespace()); Attribute mcs = e.getAttribute("metaChecksum", e.getNamespace()); Attribute acc = e.getAttribute("accMetaChecksum", e.getNamespace()); try { UUID uuid; if (rc.docVersion == 20) { Long id = new Long(aid.getLongValue()); uuid = new UUID(0L, id); } else { uuid = UUID.fromString(aid.getValue()); } CaomUtil.assignID(ce, uuid); if (alastModified != null) { Date lastModified = rc.parseTimestamp(alastModified.getValue()); CaomUtil.assignLastModified(ce, lastModified, "lastModified"); } if (rc.docVersion >= 23) { if (amaxLastModified != null) { Date lastModified = rc.parseTimestamp(amaxLastModified.getValue()); CaomUtil.assignLastModified(ce, lastModified, "maxLastModified"); } if (mcs != null) { URI metaCS = new URI(mcs.getValue()); CaomUtil.assignMetaChecksum(ce, metaCS, "metaChecksum"); } if (acc != null) { URI accCS = new URI(acc.getValue()); CaomUtil.assignMetaChecksum(ce, accCS, "accMetaChecksum"); } } } catch (DataConversionException ex) { throw new ObservationParsingException("invalid id: " + aid.getValue()); } catch (ParseException ex) { throw new ObservationParsingException("invalid lastModified: " + alastModified.getValue()); } catch (URISyntaxException ex) { throw new ObservationParsingException("invalid checksum uri: " + aid.getValue()); } } /** * Build an Algorithm from a JDOM representation of an algorithm element. * * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @return an Algorithm, or null if the document doesn't contain an * algorithm element. * @throws ObservationParsingException */ protected Environment getEnvironment(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("environment", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } Environment env = new Environment(); env.seeing = getChildTextAsDouble("seeing", element, namespace, false); env.humidity = getChildTextAsDouble("humidity", element, namespace, false); env.elevation = getChildTextAsDouble("elevation", element, namespace, false); env.tau = getChildTextAsDouble("tau", element, namespace, false); env.wavelengthTau = getChildTextAsDouble("wavelengthTau", element, namespace, false); env.ambientTemp = getChildTextAsDouble("ambientTemp", element, namespace, false); env.photometric = getChildTextAsBoolean("photometric", element, namespace, false); return env; } /** * Build an Algorithm from a JDOM representation of an algorithm element. * * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @return an Algorithm, or null if the document doesn't contain an * algorithm element. * @throws ObservationParsingException */ protected Algorithm getAlgorithm(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("algorithm", parent, namespace, true); if (element == null || element.getContentSize() == 0) { return null; } String name = getChildText("name", element, namespace, true); return new Algorithm(name); } /** * Build an Proposal from a JDOM representation of an proposal element. * * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @return an Proposal, or null if the document doesn't contain an proposal * element. * @throws ObservationParsingException */ protected Proposal getProposal(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("proposal", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } String id = getChildText("id", element, namespace, true); // no check for null: Proposal will check and throw if illegal Proposal proposal = new Proposal(id); proposal.pi = getChildText("pi", element, namespace, false); proposal.project = getChildText("project", element, namespace, false); proposal.title = getChildText("title", element, namespace, false); if (rc.docVersion < 23) { addChildTextToStringList("keywords", proposal.getKeywords(), element, namespace, false); } else { addKeywordsToList(proposal.getKeywords(), element, namespace); } return proposal; } /** * Build an Target from a JDOM representation of an target element. * * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @return an Target, or null if the document doesn't contain an target * element. * @throws ObservationParsingException */ protected Target getTarget(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("target", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } String name = getChildText("name", element, namespace, true); Target target = new Target(name); String type = getChildText("type", element, namespace, false); if (type != null) { target.type = TargetType.toValue(type); } target.standard = getChildTextAsBoolean("standard", element, namespace, false); target.redshift = getChildTextAsDouble("redshift", element, namespace, false); target.moving = getChildTextAsBoolean("moving", element, namespace, false); if (rc.docVersion < 23) { addChildTextToStringList("keywords", target.getKeywords(), element, namespace, false); } else { addKeywordsToList(target.getKeywords(), element, namespace); } return target; } /** * Build a TargetPosition from a JDOM representation of an targetPosition * element. * * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @return a TargetPosition, or null if the document doesn't contain an * targetPosition element. * @throws ObservationParsingException */ protected TargetPosition getTargetPosition(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("targetPosition", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } String coordsys = getChildText("coordsys", element, namespace, true); Double equinox = getChildTextAsDouble("equinox", element, namespace, false); Element coords = getChildElement("coordinates", element, namespace, true); double cval1 = getChildTextAsDouble("cval1", coords, namespace, true); double cval2 = getChildTextAsDouble("cval2", coords, namespace, true); TargetPosition tpos = new TargetPosition(coordsys, new Point(cval1, cval2)); tpos.equinox = equinox; return tpos; } /** * * @param parent * @param namespace * @param rc * @return * @throws ObservationParsingException */ protected Requirements getRequirements(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("requirements", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } String flag = getChildText("flag", element, namespace, true); Requirements req = new Requirements(Status.toValue(flag)); return req; } /** * Build an Telescope from a JDOM representation of an telescope element. * * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @return an TarTelescopeget, or null if the document doesn't contain an * telescope element. * @throws ObservationParsingException */ protected Telescope getTelescope(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("telescope", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } String name = getChildText("name", element, namespace, true); Telescope telescope = new Telescope(name); telescope.geoLocationX = getChildTextAsDouble("geoLocationX", element, namespace, false); telescope.geoLocationY = getChildTextAsDouble("geoLocationY", element, namespace, false); telescope.geoLocationZ = getChildTextAsDouble("geoLocationZ", element, namespace, false); if (rc.docVersion < 23) { addChildTextToStringList("keywords", telescope.getKeywords(), element, namespace, false); } else { addKeywordsToList(telescope.getKeywords(), element, namespace); } return telescope; } /** * Build an Instrument from a JDOM representation of an instrument element. * * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @return an Instrument, or null if the document doesn't contain an * instrument element. * @throws ObservationParsingException */ protected Instrument getInstrument(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("instrument", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } String name = getChildText("name", element, namespace, true); Instrument instrument = new Instrument(name); if (rc.docVersion < 23) { addChildTextToStringList("keywords", instrument.getKeywords(), element, namespace, false); } else { addKeywordsToList(instrument.getKeywords(), element, namespace); } return instrument; } /** * Creates ObservationURI from the observationURI elements found in the * members element, and adds them to the given Set of ObservationURI's. * * @param members * Set of Member's from the Observation. * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @throws ObservationParsingException */ protected void addMembers(Set<ObservationURI> members, Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("members", parent, namespace, false); if (element != null) { List children = getChildrenElements("observationURI", element, namespace, false); Iterator it = children.iterator(); while (it.hasNext()) { Element child = (Element) it.next(); try { members.add(new ObservationURI(new URI(child.getText()))); } catch (URISyntaxException e) { String error = "Unable to parse observationURI " + child.getText() + " in to an ObservationURI in element " + element.getName() + " because " + e.getMessage(); throw new ObservationParsingException(error); } } } } /** * Creates Plane's from the plane elements found in the planes element, and * adds them to the given Set of Plane's. * * @param planes * the Set of Plane's from the Observation. * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @throws ObservationParsingException */ protected void addPlanes(Set<Plane> planes, Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("planes", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return; } List planeElements = getChildrenElements("plane", element, namespace, false); Iterator it = planeElements.iterator(); while (it.hasNext()) { Element planeElement = (Element) it.next(); String productID = getChildText("productID", planeElement, namespace, true); Plane plane = new Plane(productID); plane.metaRelease = getChildTextAsDate("metaRelease", planeElement, namespace, false, rc.dateFormat); plane.dataRelease = getChildTextAsDate("dataRelease", planeElement, namespace, false, rc.dateFormat); String creatorIDStr = getChildText("creatorID", planeElement, namespace, false); if (creatorIDStr != null) { try { plane.creatorID = new URI(creatorIDStr); } catch (URISyntaxException e) { String error = "Unable to parse creatorID " + creatorIDStr + " to URI in element " + element.getName() + " because " + e.getMessage(); throw new ObservationParsingException(error, e); } } String dataProductType = getChildText("dataProductType", planeElement, namespace, false); if (dataProductType != null) { plane.dataProductType = DataProductType.toValue(dataProductType); } String calibrationLevel = getChildText("calibrationLevel", planeElement, namespace, false); if (calibrationLevel != null) { plane.calibrationLevel = CalibrationLevel.toValue(Integer.parseInt(calibrationLevel)); } plane.provenance = getProvenance(planeElement, namespace, rc); plane.metrics = getMetrics(planeElement, namespace, rc); plane.quality = getQuality(planeElement, namespace, rc); plane.position = getPosition(planeElement, namespace, rc); plane.energy = getEnergy(planeElement, namespace, rc); plane.time = getTime(planeElement, namespace, rc); plane.polarization = getPolarization(planeElement, namespace, rc); addArtifacts(plane.getArtifacts(), planeElement, namespace, rc); assignEntityAttributes(planeElement, plane, rc); boolean added = planes.add(plane); if (!added) { throw new IllegalArgumentException("Plane.productID = " + productID + " is not unique"); } } } protected Position getPosition(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("position", parent, namespace, false); if (element == null) { return null; } Position pos = new Position(); Element cur = getChildElement("bounds", element, namespace, false); if (cur != null) { if (rc.docVersion < 23) { throw new UnsupportedOperationException( "cannot convert version " + rc.docVersion + " polygon to current version"); } Attribute type = cur.getAttribute("type", xsiNamespace); String tval = type.getValue(); String circleType = namespace.getPrefix() + ":" + Circle.class.getSimpleName(); String polyType = namespace.getPrefix() + ":" + Polygon.class.getSimpleName(); if (polyType.equals(tval)) { List<Point> points = new ArrayList<Point>(); Element pes = cur.getChild("points", namespace); for (Element pe : pes.getChildren()) { // only vertex double cval1 = getChildTextAsDouble("cval1", pe, namespace, true); double cval2 = getChildTextAsDouble("cval2", pe, namespace, true); points.add(new Point(cval1, cval2)); } Element se = cur.getChild("samples", namespace); MultiPolygon poly = new MultiPolygon(); Element ves = se.getChild("vertices", namespace); for (Element ve : ves.getChildren()) { // only vertex double cval1 = getChildTextAsDouble("cval1", ve, namespace, true); double cval2 = getChildTextAsDouble("cval2", ve, namespace, true); int sv = getChildTextAsInteger("type", ve, namespace, true); poly.getVertices().add(new Vertex(cval1, cval2, SegmentType.toValue(sv))); } pos.bounds = new Polygon(points, poly); } else if (circleType.equals(tval)) { Element ce = cur.getChild("center", namespace); double cval1 = getChildTextAsDouble("cval1", ce, namespace, true); double cval2 = getChildTextAsDouble("cval2", ce, namespace, true); Point c = new Point(cval1, cval2); double r = getChildTextAsDouble("radius", cur, namespace, true); pos.bounds = new Circle(c, r); } else { throw new UnsupportedOperationException("unsupported shape: " + tval); } } cur = getChildElement("dimension", element, namespace, false); if (cur != null) { // Attribute type = cur.getAttribute("type", xsiNamespace); // String tval = type.getValue(); // String extype = namespace.getPrefix() + ":" + // Dimension2D.class.getSimpleName(); // if ( extype.equals(tval) ) // { long naxis1 = getChildTextAsLong("naxis1", cur, namespace, true); long naxis2 = getChildTextAsLong("naxis2", cur, namespace, true); pos.dimension = new Dimension2D(naxis1, naxis2); // } // else // throw new ObservationParsingException("unsupported dimension // type: " + tval); } pos.resolution = getChildTextAsDouble("resolution", element, namespace, false); pos.sampleSize = getChildTextAsDouble("sampleSize", element, namespace, false); pos.timeDependent = getChildTextAsBoolean("timeDependent", element, namespace, false); return pos; } protected Energy getEnergy(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("energy", parent, namespace, false); if (element == null) { return null; } Energy nrg = new Energy(); Element cur = getChildElement("bounds", element, namespace, false); if (cur != null) { double lb = getChildTextAsDouble("lower", cur, namespace, true); double ub = getChildTextAsDouble("upper", cur, namespace, true); nrg.bounds = new Interval(lb, ub); addSamples(nrg.bounds, cur.getChild("samples", namespace), namespace, rc); } cur = getChildElement("dimension", element, namespace, false); if (cur != null) { nrg.dimension = getChildTextAsLong("dimension", element, namespace, true); } nrg.resolvingPower = getChildTextAsDouble("resolvingPower", element, namespace, false); nrg.sampleSize = getChildTextAsDouble("sampleSize", element, namespace, false); nrg.bandpassName = getChildText("bandpassName", element, namespace, false); String emb = getChildText("emBand", element, namespace, false); if (emb != null) { nrg.emBand = EnergyBand.toValue(emb); } nrg.restwav = getChildTextAsDouble("restwav", element, namespace, false); cur = getChildElement("transition", element, namespace, false); if (cur != null) { String species = getChildText("species", cur, namespace, true); String trans = getChildText("transition", cur, namespace, true); nrg.transition = new EnergyTransition(species, trans); } return nrg; } protected Time getTime(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("time", parent, namespace, false); if (element == null) { return null; } Time tim = new Time(); Element cur = getChildElement("bounds", element, namespace, false); if (cur != null) { double lb = getChildTextAsDouble("lower", cur, namespace, true); double ub = getChildTextAsDouble("upper", cur, namespace, true); tim.bounds = new Interval(lb, ub); addSamples(tim.bounds, cur.getChild("samples", namespace), namespace, rc); } cur = getChildElement("dimension", element, namespace, false); if (cur != null) { // Attribute type = cur.getAttribute("type", xsiNamespace); // String tval = type.getValue(); // String extype = namespace.getPrefix() + ":" + // Long.class.getSimpleName(); // if ( extype.equals(tval) ) // { tim.dimension = getChildTextAsLong("dimension", element, namespace, true); // } // else // throw new ObservationParsingException("unsupported dimension // type: " + tval); } tim.resolution = getChildTextAsDouble("resolution", element, namespace, false); tim.sampleSize = getChildTextAsDouble("sampleSize", element, namespace, false); tim.exposure = getChildTextAsDouble("exposure", element, namespace, false); return tim; } private void addSamples(Interval inter, Element sampleElement, Namespace namespace, ReadContext rc) throws ObservationParsingException { if (sampleElement != null) { List<Element> sse = sampleElement.getChildren("sample", namespace); for (Element se : sse) { double lb = getChildTextAsDouble("lower", se, namespace, true); double ub = getChildTextAsDouble("upper", se, namespace, true); inter.getSamples().add(new SubInterval(lb, ub)); } } if (rc.docVersion < 23 && inter.getSamples().isEmpty()) { // backwards compat inter.getSamples().add(new SubInterval(inter.getLower(), inter.getUpper())); } } protected Polarization getPolarization(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("polarization", parent, namespace, false); if (element == null) { return null; } Polarization pol = new Polarization(); Element cur = getChildElement("states", element, namespace, false); if (cur != null) { List<Element> ces = cur.getChildren(); pol.states = new ArrayList<PolarizationState>(ces.size()); for (Element e : ces) { String ss = e.getTextTrim(); PolarizationState ps = PolarizationState.valueOf(ss); pol.states.add(ps); } } cur = getChildElement("dimension", element, namespace, false); if (cur != null) { // Attribute type = cur.getAttribute("type", xsiNamespace); // String tval = type.getValue(); // String extype = namespace.getPrefix() + ":" + // Integer.class.getSimpleName(); // if ( extype.equals(tval) ) // { pol.dimension = getChildTextAsLong("dimension", element, namespace, true); // } // else // throw new ObservationParsingException("unsupported dimension // type: " + tval); } return pol; } /** * Build a Provenance from a JDOM representation of an Provenance. * * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @return an Provenance, or null if the document doesn't contain a * provenance element. * @throws ObservationParsingException */ protected Provenance getProvenance(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("provenance", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } String name = getChildText("name", element, namespace, true); Provenance provenance = new Provenance(name); provenance.version = getChildText("version", element, namespace, false); provenance.project = getChildText("project", element, namespace, false); provenance.producer = getChildText("producer", element, namespace, false); provenance.runID = getChildText("runID", element, namespace, false); String reference = getChildText("reference", element, namespace, false); if (reference != null) { try { provenance.reference = new URI(reference); } catch (URISyntaxException e) { String error = "Unable to parse reference " + reference + " to URI in element " + element.getName() + " because " + e.getMessage(); throw new ObservationParsingException(error); } } provenance.lastExecuted = getChildTextAsDate("lastExecuted", element, namespace, false, rc.dateFormat); if (rc.docVersion < 23) { addChildTextToStringList("keywords", provenance.getKeywords(), element, namespace, false); } else { addKeywordsToList(provenance.getKeywords(), element, namespace); } addInputs(provenance.getInputs(), element, namespace, rc); return provenance; } protected Metrics getMetrics(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("metrics", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } Metrics metrics = new Metrics(); metrics.sourceNumberDensity = getChildTextAsDouble("sourceNumberDensity", element, namespace, false); metrics.background = getChildTextAsDouble("background", element, namespace, false); metrics.backgroundStddev = getChildTextAsDouble("backgroundStddev", element, namespace, false); metrics.fluxDensityLimit = getChildTextAsDouble("fluxDensityLimit", element, namespace, false); metrics.magLimit = getChildTextAsDouble("magLimit", element, namespace, false); return metrics; } /** * * @param parent * @param namespace * @param rc * @return * @throws ObservationParsingException */ protected DataQuality getQuality(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("quality", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } String flag = getChildText("flag", element, namespace, true); DataQuality ret = new DataQuality(Quality.toValue(flag)); return ret; } protected EnergyTransition getTransition(Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("transition", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } String species = getChildText("species", element, namespace, true); String transition = getChildText("transition", element, namespace, true); return new EnergyTransition(species, transition); } /** * Creates PlaneURI's from the planeURI elements found in the inputs * element, and adds them to the given Set of PlaneURI's. * * @param inputs * the Set of PlaneURI from the Provenance. * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @throws ObservationParsingException */ protected void addInputs(Set<PlaneURI> inputs, Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("inputs", parent, namespace, false); if (element != null) { List children = getChildrenElements("planeURI", element, namespace, false); Iterator it = children.iterator(); while (it.hasNext()) { Element child = (Element) it.next(); try { inputs.add(new PlaneURI(new URI(child.getText()))); } catch (URISyntaxException e) { String error = "Unable to parse observationURI " + child.getText() + " in to an ObservationURI in element " + element.getName() + " because " + e.getMessage(); throw new ObservationParsingException(error); } } } } /** * Creates Artifact's from the artifact elements found in the artifacts * element, and adds them to the given Set of Artifact's. * * @param artifacts * the Set of Artifact's from the Plane. * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @throws ObservationParsingException */ protected void addArtifacts(Set<Artifact> artifacts, Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("artifacts", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return; } List artifactElements = getChildrenElements("artifact", element, namespace, false); Iterator it = artifactElements.iterator(); while (it.hasNext()) { Element artifactElement = (Element) it.next(); String uri = getChildText("uri", artifactElement, namespace, true); String pts = getChildText("productType", artifactElement, namespace, false); ProductType productType = null; if (pts != null) { productType = ProductType.toValue(pts); } else { productType = ProductType.SCIENCE; log.warn("assigning default Artifact.productType = " + productType + " for " + uri); } String rts = getChildText("releaseType", artifactElement, namespace, false); ReleaseType releaseType = null; if (rts != null) { releaseType = ReleaseType.toValue(rts); } else { releaseType = ReleaseType.DATA; log.warn("assigning default Artifact.releaseType = " + releaseType + " for " + uri); } Artifact artifact; try { artifact = new Artifact(new URI(uri), productType, releaseType); } catch (URISyntaxException e) { String error = "Unable to parse uri " + uri + " in to a URI in element " + artifactElement.getName() + " because " + e.getMessage(); throw new ObservationParsingException(error); } artifact.contentType = getChildText("contentType", artifactElement, namespace, false); artifact.contentLength = getChildTextAsLong("contentLength", artifactElement, namespace, false); String contentChecksumStr = getChildText("contentChecksum", artifactElement, namespace, false); if (contentChecksumStr != null) { try { artifact.contentChecksum = new URI(contentChecksumStr); } catch (URISyntaxException e) { String error = "Unable to parse contentChecksum " + uri + " into a URI in element " + artifactElement.getName() + " because " + e.getMessage(); throw new ObservationParsingException(error, e); } } addParts(artifact.getParts(), artifactElement, namespace, rc); assignEntityAttributes(artifactElement, artifact, rc); boolean added = artifacts.add(artifact); if (!added) { throw new IllegalArgumentException("Artifact.uri = " + uri + " is not unique"); } } } /** * Creates Part's from the part elements found in the parts element, and * adds them to the given Set of Part's. * * @param parts * the Set of Part's from the Artifact. * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @throws ObservationParsingException */ protected void addParts(Set<Part> parts, Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("parts", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return; } List partElements = getChildrenElements("part", element, namespace, false); Iterator it = partElements.iterator(); while (it.hasNext()) { Element partElement = (Element) it.next(); String partName = getChildText("name", partElement, namespace, true); Part part = new Part(partName); String productType = getChildText("productType", partElement, namespace, false); if (productType != null) { part.productType = ProductType.toValue(productType); } addChunks(part.getChunks(), partElement, namespace, rc); assignEntityAttributes(partElement, part, rc); boolean added = parts.add(part); if (!added) { throw new IllegalArgumentException("Part.name = " + partName + " is not unique"); } } } /** * Creates Chunk's from the chunk elements found in the chunks element, and * adds them to the given Set of Chunk's. * * @param chunks * the Set of Chunk's from the Part. * @param parent * the parent Element. * @param namespace * of the document. * @param rc * @throws ObservationParsingException */ protected void addChunks(Set<Chunk> chunks, Element parent, Namespace namespace, ReadContext rc) throws ObservationParsingException { Element element = getChildElement("chunks", parent, namespace, false); if (element == null || element.getContentSize() == 0) { return; } List chunkElements = getChildrenElements("chunk", element, namespace, false); Iterator it = chunkElements.iterator(); while (it.hasNext()) { Element chunkElement = (Element) it.next(); Chunk chunk = new Chunk(); String productType = getChildText("productType", chunkElement, namespace, false); if (productType != null) { chunk.productType = ProductType.toValue(productType); } chunk.naxis = getChildTextAsInteger("naxis", chunkElement, namespace, false); chunk.observableAxis = getChildTextAsInteger("observableAxis", chunkElement, namespace, false); chunk.positionAxis1 = getChildTextAsInteger("positionAxis1", chunkElement, namespace, false); chunk.positionAxis2 = getChildTextAsInteger("positionAxis2", chunkElement, namespace, false); chunk.energyAxis = getChildTextAsInteger("energyAxis", chunkElement, namespace, false); chunk.timeAxis = getChildTextAsInteger("timeAxis", chunkElement, namespace, false); chunk.polarizationAxis = getChildTextAsInteger("polarizationAxis", chunkElement, namespace, false); chunk.observable = getObservableAxis("observable", chunkElement, namespace, false, rc); chunk.position = getSpatialWCS("position", chunkElement, namespace, false, rc); chunk.energy = getSpectralWCS("energy", chunkElement, namespace, false, rc); chunk.time = getTemporalWCS("time", chunkElement, namespace, false, rc); chunk.polarization = getPolarizationWCS("polarization", chunkElement, namespace, false, rc); assignEntityAttributes(chunkElement, chunk, rc); chunks.add(chunk); } } /* * //alt version for one-chunk-per-part that was reverted from caom-2.2 * protected Chunk getChunk(Element parent, Namespace namespace, ReadContext * rc) throws ObservationParsingException { Element chunkParent = parent; if * (rc.docVersion < 22) { // pre 2.2 a part could have multiple chunks * inside a "chunks" element Element e = getChildElement("chunks", parent, * namespace, false); if (e == null) return null; chunkParent = e; } Element * chunkElement = getChildElement("chunk", chunkParent, namespace, false); * if (chunkElement == null) return null; * * Chunk chunk = new Chunk(); * * chunk.naxis = getChildTextAsInteger("naxis", chunkElement, namespace, * false); chunk.observableAxis = getChildTextAsInteger("observableAxis", * chunkElement, namespace, false); chunk.positionAxis1 = * getChildTextAsInteger("positionAxis1", chunkElement, namespace, false); * chunk.positionAxis2 = getChildTextAsInteger("positionAxis2", * chunkElement, namespace, false); chunk.energyAxis = * getChildTextAsInteger("energyAxis", chunkElement, namespace, false); * chunk.timeAxis = getChildTextAsInteger("timeAxis", chunkElement, * namespace, false); chunk.polarizationAxis = * getChildTextAsInteger("polarizationAxis", chunkElement, namespace, * false); * * chunk.observable = getObservableAxis("observable", chunkElement, * namespace, false, rc); chunk.position = getSpatialWCS("position", * chunkElement, namespace, false, rc); chunk.energy = * getSpectralWCS("energy", chunkElement, namespace, false, rc); chunk.time * = getTemporalWCS("time", chunkElement, namespace, false, rc); * chunk.polarization = getPolarizationWCS("polarization", chunkElement, * namespace, false, rc); * * assignEntityAttributes(chunkElement, chunk, rc); * * return chunk; } */ /** * Build an ObservableAxis from a JDOM representation of an observable * element. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @param rc * @return an ObservableAxis, or null if the document doesn't contain an * observable element. * @throws ObservationParsingException */ protected ObservableAxis getObservableAxis(String name, Element parent, Namespace namespace, boolean required, ReadContext rc) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } Slice dependent = getSlice("dependent", element, namespace, true); ObservableAxis observable = new ObservableAxis(dependent); observable.independent = getSlice("independent", element, namespace, false); return observable; } /** * Build an SpatialWCS from a JDOM representation of an position element. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @param rc * @return an SpatialWCS, or null if the document doesn't contain an * position element. * @throws ObservationParsingException */ protected SpatialWCS getSpatialWCS(String name, Element parent, Namespace namespace, boolean required, ReadContext rc) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } CoordAxis2D axis = getCoordAxis2D("axis", element, namespace, true); SpatialWCS position = new SpatialWCS(axis); position.coordsys = getChildText("coordsys", element, namespace, false); position.equinox = getChildTextAsDouble("equinox", element, namespace, false); position.resolution = getChildTextAsDouble("resolution", element, namespace, false); return position; } /** * Build an SpectralWCS from a JDOM representation of an energy element. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @param rc * @return an SpectralWCS, or null if the document doesn't contain an energy * element. * @throws ObservationParsingException */ protected SpectralWCS getSpectralWCS(String name, Element parent, Namespace namespace, boolean required, ReadContext rc) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } CoordAxis1D axis = getCoordAxis1D("axis", element, namespace, true); String specsys = getChildText("specsys", element, namespace, true); SpectralWCS energy = new SpectralWCS(axis, specsys); energy.ssysobs = getChildText("ssysobs", element, namespace, false); energy.ssyssrc = getChildText("ssyssrc", element, namespace, false); energy.restfrq = getChildTextAsDouble("restfrq", element, namespace, false); energy.restwav = getChildTextAsDouble("restwav", element, namespace, false); energy.velosys = getChildTextAsDouble("velosys", element, namespace, false); energy.zsource = getChildTextAsDouble("zsource", element, namespace, false); energy.velang = getChildTextAsDouble("velang", element, namespace, false); energy.bandpassName = getChildText("bandpassName", element, namespace, false); energy.resolvingPower = getChildTextAsDouble("resolvingPower", element, namespace, false); energy.transition = getTransition(element, namespace, rc); return energy; } /** * Build an TemporalWCS from a JDOM representation of an time element. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @param rc * @return an TemporalWCS, or null if the document doesn't contain an time * element. * @throws ObservationParsingException */ protected TemporalWCS getTemporalWCS(String name, Element parent, Namespace namespace, boolean required, ReadContext rc) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } CoordAxis1D axis = getCoordAxis1D("axis", element, namespace, true); TemporalWCS time = new TemporalWCS(axis); time.timesys = getChildText("timesys", element, namespace, false); time.trefpos = getChildText("trefpos", element, namespace, false); time.mjdref = getChildTextAsDouble("mjdref", element, namespace, false); time.exposure = getChildTextAsDouble("exposure", element, namespace, false); time.resolution = getChildTextAsDouble("resolution", element, namespace, false); return time; } /** * Build an PolarizationWCS from a JDOM representation of an polarization * element. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * @param rc * @return an PolarizationWCS, or null if the document doesn't contain an * polarization element. * @throws ObservationParsingException */ protected PolarizationWCS getPolarizationWCS(String name, Element parent, Namespace namespace, boolean required, ReadContext rc) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } CoordAxis1D axis = getCoordAxis1D("axis", element, namespace, true); return new PolarizationWCS(axis); } /** * Build an Axis from a JDOM representation of an axis element. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an Axis, or null if the document doesn't contain an axis element. * @throws ObservationParsingException */ protected Axis getAxis(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } String ctype = getChildText("ctype", element, namespace, true); String cunit = getChildText("cunit", element, namespace, false); return new Axis(ctype, cunit); } /** * Build an Coord2D from a JDOM representation of an element named name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return a Coord2D, or null if the document doesn't contain element named * name. * @throws ObservationParsingException */ protected Coord2D getCoord2D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } RefCoord coord1 = getRefCoord("coord1", element, namespace, true); RefCoord coord2 = getRefCoord("coord2", element, namespace, true); return new Coord2D(coord1, coord2); } /** * Build an ValueCoord2D from a JDOM representation of an element named * name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return a ValueCoord2D, or null if the document doesn't contain element * named name. * @throws ObservationParsingException */ protected ValueCoord2D getValueCoord2D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } double coord1 = getChildTextAsDouble("coord1", element, namespace, true); double coord2 = getChildTextAsDouble("coord2", element, namespace, true); return new ValueCoord2D(coord1, coord2); } /** * Build an CoordAxis1D from a JDOM representation of element name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordAxis1D, or null if the document doesn't contain element * called name. * @throws ObservationParsingException */ protected CoordAxis1D getCoordAxis1D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } Axis axis = getAxis("axis", element, namespace, true); CoordAxis1D coordAxis1D = new CoordAxis1D(axis); coordAxis1D.error = getCoordError("error", element, namespace, false); coordAxis1D.range = getCoordRange1D("range", element, namespace, false); coordAxis1D.bounds = getCoordBounds1D("bounds", element, namespace, false); coordAxis1D.function = getCoordFunction1D("function", element, namespace, false); return coordAxis1D; } /** * Build an CoordAxis2D from a JDOM representation of element name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordAxis2D, or null if the document doesn't contain element * called name. * @throws ObservationParsingException */ protected CoordAxis2D getCoordAxis2D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } Axis axis1 = getAxis("axis1", element, namespace, true); Axis axis2 = getAxis("axis2", element, namespace, true); CoordAxis2D axis = new CoordAxis2D(axis1, axis2); axis.error1 = getCoordError("error1", element, namespace, false); axis.error2 = getCoordError("error2", element, namespace, false); axis.range = getCoordRange2D("range", element, namespace, false); axis.bounds = getCoordBounds2D("bounds", element, namespace, false); axis.function = getCoordFunction2D("function", element, namespace, false); return axis; } /** * Build an CoordBounds1D from a JDOM representation of an element named * name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordBounds1D, or null if the document doesn't contain element * named name. * @throws ObservationParsingException */ protected CoordBounds1D getCoordBounds1D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } CoordBounds1D coordBounds1D = new CoordBounds1D(); Element samples = getChildElement("samples", element, namespace, false); if (samples != null) { addChildrenToCoordRange1DList("range", coordBounds1D.getSamples(), samples, namespace, false); } return coordBounds1D; } /** * Build an CoordBounds2D from a JDOM representation of an element named * name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordBounds2D, or null if the document doesn't contain element * named name. * @throws ObservationParsingException */ protected CoordBounds2D getCoordBounds2D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } // Look for a CoordCircle2D which has a center and a radius. CoordCircle2D circle = getCoordCircle2D("circle", element, namespace, false); if (circle != null) { return circle; } // Look for a CoordPolygon2D which has a list of Coord2D vertices. CoordPolygon2D polygon = getCoordPolygon2D("polygon", element, namespace, false); if (polygon != null) { return polygon; } // Unknown children. String error = "Unsupported element found in " + name + ": " + element.getText(); throw new ObservationParsingException(error); } /** * Build an CoordCircle2D from a JDOM representation of an element named * name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordCircle2D, or null if the document doesn't contain element * named name. * @throws ObservationParsingException */ protected CoordCircle2D getCoordCircle2D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null) { return null; } // Look for a CoordCircle2D which has a center and a radius. ValueCoord2D center = getValueCoord2D("center", element, namespace, true); Double radius = getChildTextAsDouble("radius", element, namespace, true); return new CoordCircle2D(center, radius); } /** * Build an CoordError from a JDOM representation of element name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordError, or null if the document doesn't contain element * called name. * @throws ObservationParsingException */ protected CoordError getCoordError(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } Double syser = getChildTextAsDouble("syser", element, namespace, true); Double rnder = getChildTextAsDouble("rnder", element, namespace, true); return new CoordError(syser, rnder); } /** * Build an CoordFunction1D from a JDOM representation of an element named * name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordFunction1D, or null if the document doesn't contain * element named name. * @throws ObservationParsingException */ protected CoordFunction1D getCoordFunction1D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } Long naxis = getChildTextAsLong("naxis", element, namespace, true); Double delta = getChildTextAsDouble("delta", element, namespace, true); RefCoord refCoord = getRefCoord("refCoord", element, namespace, true); return new CoordFunction1D(naxis, delta, refCoord); } /** * Build an CoordFunction2D from a JDOM representation of an element named * name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordFunction2D, or null if the document doesn't contain * element named name. * @throws ObservationParsingException */ protected CoordFunction2D getCoordFunction2D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } Dimension2D dimension = getDimension2D("dimension", element, namespace, true); Coord2D refCoord = getCoord2D("refCoord", element, namespace, true); double cd11 = getChildTextAsDouble("cd11", element, namespace, true); double cd12 = getChildTextAsDouble("cd12", element, namespace, true); double cd21 = getChildTextAsDouble("cd21", element, namespace, true); double cd22 = getChildTextAsDouble("cd22", element, namespace, true); return new CoordFunction2D(dimension, refCoord, cd11, cd12, cd21, cd22); } /** * Build an CoordPolygon2D from a JDOM representation of an element named * name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordPolygon2D, or null if the document doesn't contain * element named name. * @throws ObservationParsingException */ protected CoordPolygon2D getCoordPolygon2D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null) { return null; } Element vertices = getChildElement("vertices", element, namespace, true); List children = getChildrenElements("vertex", vertices, namespace, true); // Vertices must have a minimum of 3 vertexes. if (children.size() < 3) { String error = "CoordPolygon2D must have a minimum of 3 vertexes, found " + children.size(); throw new ObservationParsingException(error); } CoordPolygon2D polygon = new CoordPolygon2D(); Iterator it = children.iterator(); while (it.hasNext()) { Element vertexElement = (Element) it.next(); double coord1 = getChildTextAsDouble("coord1", vertexElement, namespace, true); double coord2 = getChildTextAsDouble("coord2", vertexElement, namespace, true); polygon.getVertices().add(new ValueCoord2D(coord1, coord2)); } return polygon; } /** * Build an CoordRange1D from a JDOM representation of an element named * name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordRange1D, or null if the document doesn't contain element * named name. * @throws ObservationParsingException */ protected CoordRange1D getCoordRange1D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } RefCoord start = getRefCoord("start", element, namespace, true); RefCoord end = getRefCoord("end", element, namespace, true); return new CoordRange1D(start, end); } /** * Build an CoordRange2D from a JDOM representation of an element named * name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an CoordRange2D, or null if the document doesn't contain element * named name. * @throws ObservationParsingException */ protected CoordRange2D getCoordRange2D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } Coord2D start = getCoord2D("start", element, namespace, true); Coord2D end = getCoord2D("end", element, namespace, true); return new CoordRange2D(start, end); } /** * Build an Dimension2D from a JDOM representation of an element named name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an Dimension2D, or null if the document doesn't contain element * named name. * @throws ObservationParsingException */ protected Dimension2D getDimension2D(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } Long naxis1 = getChildTextAsLong("naxis1", element, namespace, true); Long naxis2 = getChildTextAsLong("naxis2", element, namespace, true); return new Dimension2D(naxis1, naxis2); } /** * Build an RefCoord from a JDOM representation of an element named name. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an RefCoord, or null if the document doesn't contain element * named name. * @throws ObservationParsingException */ protected RefCoord getRefCoord(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, false); if (element == null || element.getContentSize() == 0) { return null; } Double pix = getChildTextAsDouble("pix", element, namespace, true); Double val = getChildTextAsDouble("val", element, namespace, true); return new RefCoord(pix, val); } /** * Build an Slice from a JDOM representation of an slice element. * * @param name * the name of the Element. * @param parent * the parent Element. * @param namespace * of the document. * @param required * is the element expected to be found. * @return an Slice, or null if the document doesn't contain an slice * element. * @throws ObservationParsingException */ protected Slice getSlice(String name, Element parent, Namespace namespace, boolean required) throws ObservationParsingException { Element element = getChildElement(name, parent, namespace, required); if (element == null || element.getContentSize() == 0) { return null; } Axis axis = getAxis("axis", element, namespace, true); Long bin = getChildTextAsLong("bin", element, namespace, true); return new Slice(axis, bin); } // protected String getAttributeValue(String name, Element element, boolean // required) // throws ObservationParsingException // { // String value = element.getAttributeValue(name); // if (required && value == null) // { // String error = "Required attribute " + name + " not found in element " + // element.getName(); // throw new ObservationParsingException(error); // } // return value; // } protected Element getChildElement(String name, Element element, Namespace ns, boolean required) throws ObservationParsingException { Element child = element.getChild(name, ns); if (required && child == null) { String error = name + " element not found in " + element.getName(); throw new ObservationParsingException(error); } return child; } protected String getChildText(String name, Element element, Namespace ns, boolean required) throws ObservationParsingException { Element child = getChildElement(name, element, ns, required); if (child != null) { return cleanWhitespace(child.getText()); } return null; } protected Boolean getChildTextAsBoolean(String name, Element element, Namespace ns, boolean required) throws ObservationParsingException { Element child = getChildElement(name, element, ns, required); if (child != null) { return Boolean.valueOf(child.getText()); } return null; } protected Integer getChildTextAsInteger(String name, Element element, Namespace ns, boolean required) throws ObservationParsingException { Element child = getChildElement(name, element, ns, required); if (child != null) { return Integer.valueOf(child.getText()); } return null; } protected Double getChildTextAsDouble(String name, Element element, Namespace ns, boolean required) throws ObservationParsingException { Element child = getChildElement(name, element, ns, required); if (child != null) { return Double.valueOf(child.getText()); } return null; } protected Long getChildTextAsLong(String name, Element element, Namespace ns, boolean required) throws ObservationParsingException { Element child = getChildElement(name, element, ns, required); if (child != null) { return Long.valueOf(child.getText()); } return null; } protected void addChildTextToStringList(String name, Collection<String> list, Element element, Namespace ns, boolean required) throws ObservationParsingException { String child = getChildText(name, element, ns, required); if (child == null) { return; } String[] tokens = child.split("[\\s]+"); for (int i = 0; i < tokens.length; i++) { String token = tokens[i]; token = cleanWhitespace(token); if (!token.isEmpty()) { list.add(token); } } } protected void addKeywordsToList(Collection<String> list, Element element, Namespace ns) throws ObservationParsingException { Element kwe = element.getChild("keywords", ns); log.debug("addKeywordsToList: " + kwe); if (kwe == null) { return; } List kws = kwe.getChildren("keyword", ns); log.debug("addKeywordsToList: " + kws.size()); Iterator it = kws.iterator(); while (it.hasNext()) { Element k = (Element) it.next(); String s = k.getTextTrim(); log.debug("addKeywordsToList: " + s); list.add(s); } } protected void addChildrenToCoordRange1DList(String name, List<CoordRange1D> list, Element element, Namespace ns, boolean required) throws ObservationParsingException { List children = getChildrenElements(name, element, ns, required); Iterator it = children.iterator(); while (it.hasNext()) { Element child = (Element) it.next(); RefCoord start = getRefCoord("start", child, ns, true); RefCoord end = getRefCoord("end", child, ns, true); list.add(new CoordRange1D(start, end)); } } protected Date getChildTextAsDate(String name, Element element, Namespace ns, boolean required, DateFormat dateFormat) throws ObservationParsingException { String child = getChildText(name, element, ns, required); if (child != null) { try { return DateUtil.flexToDate(child, dateFormat); } catch (ParseException ex) { String error = "Unable to parse " + name + " in " + element.getName() + " to a date because " + ex.getMessage(); throw new ObservationParsingException(error, ex); } } return null; } protected List getChildrenElements(String name, Element element, Namespace ns, boolean required) throws ObservationParsingException { List children = element.getChildren(name, ns); if (required && children.isEmpty()) { String error = name + " element not found in " + element.getName(); throw new ObservationParsingException(error); } return children; } protected String cleanWhitespace(String s) { if (s == null) { return null; } s = s.trim(); if (s.isEmpty()) { return null; } return s; } }