/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.oxm.record; import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession; import org.eclipse.persistence.internal.oxm.Constants; import org.eclipse.persistence.internal.oxm.Root; import org.eclipse.persistence.internal.oxm.StrBuffer; import org.eclipse.persistence.internal.oxm.XMLUnmarshaller; import org.eclipse.persistence.internal.oxm.mappings.Mapping; import org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl; import org.xml.sax.Attributes; import org.xml.sax.SAXException; /** * Record for handling simple root elements that have a single text child node, * and are being unmarshalled to a primitive wrapper object. The characters * method will be used to gather the text to be converted. */ public class XMLRootRecord extends UnmarshalRecordImpl { private Class targetClass; private StrBuffer characters; private boolean shouldReadChars; private int elementCount; private XMLUnmarshaller unmarshaller; /** * Default constructor. */ public XMLRootRecord(Class cls, XMLUnmarshaller unmarshaller) { this.targetClass = cls; this.unmarshaller = unmarshaller; setSession((CoreAbstractSession) unmarshaller.getContext().getSession()); } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (characters == null) { characters = new StrBuffer(); } if (shouldReadChars) { characters.append(ch, start, length); } } @Override public void characters(CharSequence characters) throws SAXException { if(null != characters) { String string = characters.toString(); characters(string.toCharArray(), 0, string.length()); } } @Override public void endDocument() throws SAXException { } @Override public void endElement(String namespaceURI, String localName, String qName) throws SAXException { // once the root element is closed (or any sub-elements for that matter) we don't // want to process any more characters shouldReadChars = false; } /** * Return a populated XMLRoot object. */ @Override public Object getCurrentObject() { Root xmlRoot = unmarshaller.createRoot(); xmlRoot.setLocalName(getLocalName()); xmlRoot.setNamespaceURI(getRootElementNamespaceUri()); if(currentObject == null) { // this assumes that since we're unmarshalling to a primitive wrapper, the root // element has a single text node. if, however, the root element doesn't have // a text node as a first child, we'll try converting null String val = null; if (characters != null) { val = characters.toString(); } xmlRoot.setObject(session.getDatasourcePlatform().getConversionManager().convertObject(val, targetClass)); } else { xmlRoot.setObject(currentObject); } return xmlRoot; } @Override public void startDocument() throws SAXException { characters = null; elementCount = 0; shouldReadChars = true; } @Override public void initializeRecord(Mapping selfRecordMapping) throws SAXException { } @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { // set the root element's prefix qualified name and namespace prefix if (getRootElementName() == null) { setRootElementName(qName); setLocalName(localName); setRootElementNamespaceUri(namespaceURI); } if(Constants.EMPTY_STRING.equals(localName)) { return; } elementCount++; if (elementCount > 1) { // we only want to process characters from the first text child; // if a subelement occurs, we will stop shouldReadChars = false; } } }