| /* |
| * Copyright (c) 2013, 2021 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 v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Denise Smith - 2.6 - initial implementation |
| // Juan Pablo Gardella = 2.7.4 - Fix for the bug #543063 |
| package org.eclipse.persistence.internal.oxm.record.json; |
| |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| import jakarta.json.Json; |
| import jakarta.json.JsonBuilderFactory; |
| import jakarta.json.JsonException; |
| import jakarta.json.JsonReader; |
| import jakarta.json.JsonStructure; |
| import jakarta.json.JsonArray; |
| import jakarta.json.JsonNumber; |
| import jakarta.json.JsonObject; |
| import jakarta.json.JsonObjectBuilder; |
| import jakarta.json.JsonString; |
| import jakarta.json.JsonValue; |
| import jakarta.json.JsonValue.ValueType; |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.persistence.exceptions.XMLMarshalException; |
| import org.eclipse.persistence.internal.oxm.CollectionGroupingElementNodeValue; |
| import org.eclipse.persistence.internal.oxm.ConversionManager; |
| import org.eclipse.persistence.internal.oxm.Constants; |
| import org.eclipse.persistence.internal.oxm.ContainerValue; |
| import org.eclipse.persistence.internal.oxm.MediaType; |
| import org.eclipse.persistence.internal.oxm.NamespaceResolver; |
| import org.eclipse.persistence.internal.oxm.NodeValue; |
| import org.eclipse.persistence.internal.oxm.Root; |
| import org.eclipse.persistence.internal.oxm.Unmarshaller; |
| import org.eclipse.persistence.internal.oxm.XPathFragment; |
| import org.eclipse.persistence.internal.oxm.mappings.Field; |
| import org.eclipse.persistence.internal.oxm.record.AbstractUnmarshalRecord; |
| import org.eclipse.persistence.internal.oxm.record.SAXUnmarshallerHandler; |
| import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord; |
| import org.eclipse.persistence.internal.oxm.XPathNode; |
| import org.eclipse.persistence.internal.oxm.record.XMLReaderAdapter; |
| import org.eclipse.persistence.internal.oxm.record.deferred.DeferredContentHandler; |
| import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy; |
| import org.eclipse.persistence.oxm.record.XMLRootRecord; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.AttributesImpl; |
| |
| public class JsonStructureReader extends XMLReaderAdapter { |
| |
| private static final String TRUE = "true"; |
| private static final String FALSE = "false"; |
| private String attributePrefix = null; |
| private NamespaceResolver namespaces = null; |
| private boolean includeRoot; |
| private String textWrapper; |
| private Class unmarshalClass; |
| private boolean isInCollection; |
| private JsonStructure jsonStructure; |
| private JsonAttributes attributes = new JsonAttributes(); |
| |
| /** |
| * If we should treat unqualified type property in JSON as MOXy type discriminator. |
| */ |
| private boolean jsonTypeCompatibility; |
| |
| public JsonStructureReader(Unmarshaller u) { |
| this(u, null); |
| } |
| |
| public JsonStructureReader(Unmarshaller u, Class clazz) { |
| this.attributePrefix = u.getAttributePrefix(); |
| if (Constants.EMPTY_STRING.equals(attributePrefix)) { |
| attributePrefix = null; |
| } |
| namespaces = u.getNamespaceResolver(); |
| |
| setNamespaceAware(u.getNamespaceResolver() != null); |
| setNamespaceSeparator(u.getNamespaceSeparator()); |
| this.includeRoot = u.isIncludeRoot(); |
| this.setErrorHandler(u.getErrorHandler()); |
| this.textWrapper = u.getValueWrapper(); |
| this.unmarshalClass = clazz; |
| this.jsonTypeCompatibility = u.getJsonTypeConfiguration().useJsonTypeCompatibility(); |
| } |
| |
| public void setJsonStructure(JsonStructure jsonStructure) { |
| this.jsonStructure = jsonStructure; |
| } |
| |
| @Override |
| public void parse(InputSource input) throws IOException, SAXException, JsonException { |
| if (input == null) { |
| if (jsonStructure != null) { |
| parseRoot(jsonStructure); |
| } |
| return; |
| } |
| |
| try { |
| InputStream inputStream = null; |
| JsonReader jsonReader; |
| if (null != input.getByteStream()) { |
| inputStream = input.getByteStream(); |
| jsonReader = Json.createReader(inputStream); |
| } else if (null != input.getCharacterStream()) { |
| jsonReader = Json.createReader(input.getCharacterStream()); |
| } else { |
| try { |
| URL url = new URL(input.getSystemId()); |
| inputStream = url.openStream(); |
| } catch (MalformedURLException malformedURLException) { |
| try { |
| inputStream = new FileInputStream(input.getSystemId()); |
| } catch (FileNotFoundException fileNotFoundException) { |
| throw malformedURLException; |
| } |
| } |
| jsonReader = Json.createReader(inputStream); |
| } |
| if (jsonReader != null) { |
| JsonStructure structure = jsonReader.read(); |
| parseRoot(structure); |
| } |
| |
| if (null != inputStream) { |
| inputStream.close(); |
| } |
| } catch (JsonException je) { |
| throw XMLMarshalException.unmarshalException(je); |
| } |
| } |
| |
| @Override |
| public void parse(String systemId) { |
| try { |
| parse(new InputSource(systemId)); |
| } catch (IOException | SAXException e) { |
| throw XMLMarshalException.unmarshalException(e); |
| } |
| } |
| |
| public void parseRoot(JsonValue jsonValue) throws SAXException { |
| if (namespaces != null) { |
| Map<String, String> namespacePairs = namespaces.getPrefixesToNamespaces(); |
| for (Entry<String, String> namespacePair : namespacePairs.entrySet()) { |
| contentHandler.startPrefixMapping(namespacePair.getKey(), namespacePair.getValue()); |
| } |
| } |
| |
| if (jsonValue.getValueType() == ValueType.OBJECT) { |
| contentHandler.startDocument(); |
| JsonObject jsonObject = (JsonObject) jsonValue; |
| |
| Set<Entry<String, JsonValue>> children = jsonObject.entrySet(); |
| if (children.size() == 0 && unmarshalClass == null) { |
| return; |
| } |
| |
| Iterator<Entry<String, JsonValue>> iter = children.iterator(); |
| |
| if (includeRoot) { |
| if (children.size() > 0) { |
| Entry<String, JsonValue> nextEntry = iter.next(); |
| parsePair(nextEntry.getKey(), nextEntry.getValue()); |
| } |
| |
| } else { |
| |
| contentHandler.startElement(Constants.EMPTY_STRING, Constants.EMPTY_STRING, null, attributes.setValue(jsonValue, attributePrefix, namespaces, getNamespaceSeparator(), isNamespaceAware())); |
| |
| while (iter.hasNext()) { |
| Entry<String, JsonValue> nextEntry = iter.next(); |
| parsePair(nextEntry.getKey(), nextEntry.getValue()); |
| } |
| contentHandler.endElement(Constants.EMPTY_STRING, Constants.EMPTY_STRING, null); |
| } |
| contentHandler.endDocument(); |
| } else if (jsonValue.getValueType() == ValueType.ARRAY) { |
| |
| SAXUnmarshallerHandler rootContentHandler = null; |
| if (getContentHandler() instanceof SAXUnmarshallerHandler) { |
| rootContentHandler = (SAXUnmarshallerHandler) getContentHandler(); |
| } |
| JsonArray jsonArray = (JsonArray) jsonValue; |
| |
| List<Object> list = new ArrayList<>(jsonArray.size()); |
| for (JsonValue aJsonArray : jsonArray) { |
| parseRoot(aJsonArray); |
| if (getContentHandler() instanceof SAXUnmarshallerHandler) { |
| SAXUnmarshallerHandler saxUnmarshallerHandler = (SAXUnmarshallerHandler) contentHandler; |
| list.add(saxUnmarshallerHandler.getObject()); |
| saxUnmarshallerHandler.setObject(null); |
| } else if (getContentHandler() instanceof UnmarshalRecord) { |
| UnmarshalRecord unmarshalRecord = (UnmarshalRecord) contentHandler; |
| Object unmarshalledObject = unmarshalRecord.getCurrentObject(); |
| if (includeRoot && unmarshalClass != null) { |
| if (!(unmarshalledObject instanceof Root)) { |
| Root xmlRoot = unmarshalRecord.createRoot(); |
| xmlRoot.setNamespaceURI(unmarshalRecord.getRootElementNamespaceUri()); |
| xmlRoot.setLocalName(unmarshalRecord.getLocalName()); |
| xmlRoot.setObject(unmarshalledObject); |
| unmarshalledObject = xmlRoot; |
| } |
| } |
| list.add(unmarshalledObject); |
| unmarshalRecord.setCurrentObject(null); |
| unmarshalRecord.setRootElementName(null); |
| unmarshalRecord.setLocalName(null); |
| } |
| } |
| if (getContentHandler() instanceof SAXUnmarshallerHandler) { |
| ((SAXUnmarshallerHandler) getContentHandler()).setObject(list); |
| } else if (getContentHandler() instanceof UnmarshalRecord) { |
| ((UnmarshalRecord) getContentHandler()).setCurrentObject(list); |
| ((UnmarshalRecord) getContentHandler()).setRootElementName(Constants.EMPTY_STRING); |
| ((UnmarshalRecord) getContentHandler()).setLocalName(Constants.EMPTY_STRING); |
| if (rootContentHandler != null) { |
| rootContentHandler.setObject(list); |
| } |
| } |
| |
| } else { |
| getContentHandler().startDocument(); |
| parseValue(jsonValue); |
| } |
| } |
| |
| private void parseValue(JsonValue jsonValue) throws SAXException { |
| switch (jsonValue.getValueType()) { |
| case STRING: { |
| String string = ((JsonString) jsonValue).getString(); |
| contentHandler.characters(string); |
| break; |
| } |
| case FALSE: { |
| contentHandler.characters(FALSE); |
| break; |
| } |
| case TRUE: { |
| contentHandler.characters(TRUE); |
| break; |
| } |
| case NUMBER: { |
| JsonNumber number = ((JsonNumber) jsonValue); |
| contentHandler.characters(number.toString()); |
| break; |
| } |
| case OBJECT: { |
| Entry<String, JsonValue> xmlValueEntry = null; |
| for (Entry<String, JsonValue> nextEntry : ((JsonObject) jsonValue).entrySet()) { |
| if (textWrapper != null && textWrapper.equals(nextEntry.getKey())) { |
| xmlValueEntry = nextEntry; |
| } else { |
| parsePair(nextEntry.getKey(), nextEntry.getValue()); |
| } |
| } |
| //Proceed JSON value mapped to @XmlValue property as a last |
| if (xmlValueEntry != null) { |
| parsePair(xmlValueEntry.getKey(), xmlValueEntry.getValue()); |
| } |
| break; |
| } |
| case ARRAY: { |
| for (JsonValue value : (JsonArray) jsonValue) { |
| parseValue(value); |
| } |
| break; |
| } |
| case NULL: { |
| contentHandler.setNil(true); |
| break; |
| } |
| default: |
| throw new IllegalStateException("Unhandled valueType: " + jsonValue.getValueType()); |
| } |
| } |
| |
| private void parsePair(String name, JsonValue jsonValue) throws SAXException { |
| if (jsonValue == null) { |
| return; |
| } |
| ValueType valueType = jsonValue.getValueType(); |
| |
| if (valueType == ValueType.ARRAY) { |
| JsonArray jsonArray = (JsonArray) jsonValue; |
| String parentLocalName = name; |
| |
| if (attributePrefix != null && parentLocalName.startsWith(attributePrefix)) { |
| // do nothing; |
| return; |
| } |
| String uri = Constants.EMPTY_STRING; |
| if (isNamespaceAware() && namespaces != null) { |
| if (parentLocalName.length() > 2) { |
| int nsIndex = parentLocalName.indexOf(getNamespaceSeparator(), 1); |
| if (nsIndex > -1) { |
| String prefix = parentLocalName.substring(0, nsIndex); |
| uri = namespaces.resolveNamespacePrefix(prefix); |
| } |
| if (uri == null || uri == Constants.EMPTY_STRING) { |
| uri = namespaces.getDefaultNamespaceURI(); |
| } else { |
| parentLocalName = parentLocalName.substring(nsIndex + 1); |
| } |
| } else { |
| uri = namespaces.getDefaultNamespaceURI(); |
| } |
| } |
| |
| boolean isTextValue; |
| int arraySize = jsonArray.size(); |
| if (arraySize == 0) { |
| if (contentHandler instanceof UnmarshalRecord || isUnmarshalRecordWithinAdapter()) { |
| final UnmarshalRecord ur = this.contentHandler instanceof UnmarshalRecord ? (UnmarshalRecord) this.contentHandler : getUnmarshalRecordFromAdapter(); |
| XPathNode node = ur.getNonAttributeXPathNode(uri, parentLocalName, parentLocalName, null); |
| if (node != null) { |
| NodeValue nv = node.getNodeValue(); |
| if (nv == null && node.getTextNode() != null) { |
| nv = node.getTextNode().getUnmarshalNodeValue(); |
| } |
| if (nv != null && nv.isContainerValue()) { |
| ur.getContainerInstance(((ContainerValue) nv)); |
| } |
| } |
| } |
| } |
| startCollection(); |
| |
| XPathFragment groupingXPathFragment = null; |
| XPathFragment itemXPathFragment = null; |
| if (contentHandler instanceof UnmarshalRecord || isUnmarshalRecordWithinAdapter()) { |
| final UnmarshalRecord contentHandler_ = contentHandler instanceof UnmarshalRecord ? (UnmarshalRecord) contentHandler : getUnmarshalRecordFromAdapter(); |
| isTextValue = isTextValue(parentLocalName, contentHandler_); |
| UnmarshalRecord unmarshalRecord = contentHandler_; |
| if (unmarshalRecord.getUnmarshaller().isWrapperAsCollectionName()) { |
| XPathNode unmarshalRecordXPathNode = unmarshalRecord.getXPathNode(); |
| if (null != unmarshalRecordXPathNode) { |
| XPathFragment currentFragment = new XPathFragment(); |
| currentFragment.setLocalName(parentLocalName); |
| currentFragment.setNamespaceURI(uri); |
| currentFragment.setNamespaceAware(isNamespaceAware()); |
| XPathNode groupingXPathNode = unmarshalRecordXPathNode.getNonAttributeChildrenMap().get(currentFragment); |
| if (groupingXPathNode != null) { |
| if (groupingXPathNode.getUnmarshalNodeValue() instanceof CollectionGroupingElementNodeValue) { |
| groupingXPathFragment = groupingXPathNode.getXPathFragment(); |
| contentHandler_.startElement(uri, parentLocalName, parentLocalName, new AttributesImpl()); |
| XPathNode itemXPathNode = groupingXPathNode.getNonAttributeChildren().get(0); |
| itemXPathFragment = itemXPathNode.getXPathFragment(); |
| } else if (groupingXPathNode.getUnmarshalNodeValue() == null) { |
| XPathNode itemXPathNode = groupingXPathNode.getNonAttributeChildren().get(0); |
| if (itemXPathNode != null) { |
| if ((itemXPathNode.getUnmarshalNodeValue()).isContainerValue()) { |
| groupingXPathFragment = groupingXPathNode.getXPathFragment(); |
| contentHandler_.startElement(uri, parentLocalName, parentLocalName, new AttributesImpl()); |
| itemXPathFragment = itemXPathNode.getXPathFragment(); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| for (JsonValue nextArrayValue : jsonArray) { |
| if (nextArrayValue.getValueType() == ValueType.NULL) { |
| contentHandler.setNil(true); |
| } |
| |
| if (!isTextValue) { |
| if (null != itemXPathFragment) { |
| contentHandler.startElement(itemXPathFragment.getNamespaceURI(), itemXPathFragment.getLocalName(), itemXPathFragment.getLocalName(), attributes.setValue(nextArrayValue, attributePrefix, namespaces, getNamespaceSeparator(), isNamespaceAware())); |
| } else { |
| contentHandler.startElement(uri, parentLocalName, parentLocalName, attributes.setValue(nextArrayValue, attributePrefix, namespaces, getNamespaceSeparator(), isNamespaceAware())); |
| } |
| |
| } |
| //Internally store each nested array it as JsonObject with name: "item" |
| if (valueType == nextArrayValue.getValueType()) { |
| JsonBuilderFactory factory = Json.createBuilderFactory(null); |
| JsonObjectBuilder jsonObjectBuilder = factory.createObjectBuilder(); |
| jsonObjectBuilder.add("item", nextArrayValue); |
| nextArrayValue = jsonObjectBuilder.build(); |
| } |
| parseValue(nextArrayValue); |
| if (!isTextValue) { |
| if (null != itemXPathFragment) { |
| contentHandler.endElement(itemXPathFragment.getNamespaceURI(), itemXPathFragment.getLocalName(), itemXPathFragment.getLocalName()); |
| } else { |
| contentHandler.endElement(uri, parentLocalName, parentLocalName); |
| } |
| } |
| } |
| } |
| if (null != groupingXPathFragment) { |
| contentHandler.endElement(uri, groupingXPathFragment.getLocalName(), groupingXPathFragment.getLocalName()); |
| } |
| endCollection(); |
| } else { |
| if (attributePrefix != null && name.startsWith(attributePrefix)) { |
| return; |
| } |
| String localName = name; |
| String uri = Constants.EMPTY_STRING; |
| if (isNamespaceAware() && namespaces != null) { |
| if (localName.length() > 2) { |
| int nsIndex = localName.indexOf(getNamespaceSeparator(), 1); |
| String prefix = Constants.EMPTY_STRING; |
| if (nsIndex > -1) { |
| prefix = localName.substring(0, nsIndex); |
| } |
| uri = namespaces.resolveNamespacePrefix(prefix); |
| if (uri == null || uri == Constants.EMPTY_STRING) { |
| uri = namespaces.getDefaultNamespaceURI(); |
| } else { |
| localName = localName.substring(nsIndex + 1); |
| } |
| |
| if (localName.equals(Constants.SCHEMA_TYPE_ATTRIBUTE) && uri != null && uri.equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)) { |
| return; |
| } |
| } else { |
| uri = namespaces.getDefaultNamespaceURI(); |
| } |
| } |
| if (contentHandler instanceof XMLRootRecord || contentHandler instanceof DeferredContentHandler) { |
| if (jsonTypeCompatibility) { |
| // if its not namespaceAware don't report the "type" child as it |
| // is will be read by the xsi:type lookup |
| if (!isNamespaceAware() && localName.equals(Constants.SCHEMA_TYPE_ATTRIBUTE)) { |
| return; |
| } |
| } |
| if (textWrapper != null && textWrapper.equals(localName)) { |
| parseValue(jsonValue); |
| return; |
| } |
| } else if (contentHandler instanceof UnmarshalRecord && ((UnmarshalRecord) contentHandler).getXPathNode() != null) { |
| if (jsonTypeCompatibility) { |
| if (!isNamespaceAware() && localName.equals(Constants.SCHEMA_TYPE_ATTRIBUTE) && !((UnmarshalRecord) contentHandler).getXPathNode().hasTypeChild()) { |
| return; |
| } |
| } |
| boolean isTextValue = isTextValue(localName, (UnmarshalRecord) contentHandler); |
| if (isTextValue) { |
| parseValue(jsonValue); |
| return; |
| } |
| NodeValue nv = ((UnmarshalRecord) contentHandler).getAttributeChildNodeValue(uri, localName); |
| if (attributePrefix == null && nv != null) { |
| return; |
| } |
| } else if (isUnmarshalRecordWithinAdapter()) { |
| @SuppressWarnings("rawtypes") final UnmarshalRecord contentHandler_ = getUnmarshalRecordFromAdapter(); |
| if (jsonTypeCompatibility) { |
| if (!isNamespaceAware() && localName.equals(Constants.SCHEMA_TYPE_ATTRIBUTE) && !contentHandler_.getXPathNode().hasTypeChild()) { |
| return; |
| } |
| } |
| boolean isTextValue = isTextValue(localName, contentHandler_); |
| if (isTextValue) { |
| parseValue(jsonValue); |
| return; |
| } |
| NodeValue nv = contentHandler_.getAttributeChildNodeValue(uri, localName); |
| if (attributePrefix == null && nv != null) { |
| return; |
| } |
| } |
| |
| if (jsonValue.getValueType() == ValueType.NULL) { |
| contentHandler.setNil(true); |
| } |
| |
| contentHandler.startElement(uri, localName, localName, attributes.setValue(jsonValue, attributePrefix, namespaces, getNamespaceSeparator(), isNamespaceAware())); |
| parseValue(jsonValue); |
| contentHandler.endElement(uri, localName, localName); |
| |
| } |
| |
| } |
| |
| private UnmarshalRecord getUnmarshalRecordFromAdapter() { |
| return (UnmarshalRecord) ((ValidatingContentHandler) ((ExtendedContentHandlerAdapter) contentHandler) |
| .getContentHandler()).getContentHandler(); |
| } |
| |
| private boolean isUnmarshalRecordWithinAdapter() { |
| return contentHandler instanceof ExtendedContentHandlerAdapter |
| && ((ExtendedContentHandlerAdapter) contentHandler) |
| .getContentHandler() instanceof ValidatingContentHandler |
| && ((ValidatingContentHandler) ((ExtendedContentHandlerAdapter) contentHandler).getContentHandler()) |
| .getContentHandler() instanceof UnmarshalRecord; |
| } |
| |
| @Override |
| public boolean isNullRepresentedByXsiNil(AbstractNullPolicy nullPolicy) { |
| return true; |
| } |
| |
| private void startCollection() { |
| isInCollection = true; |
| } |
| |
| private void endCollection() { |
| isInCollection = false; |
| } |
| |
| @Override |
| public boolean isInCollection() { |
| return isInCollection; |
| } |
| |
| private boolean isTextValue(String localName, UnmarshalRecord contentHandler_) { |
| XPathNode currentNode = contentHandler_.getXPathNode(); |
| if (currentNode == null) { |
| return textWrapper != null && textWrapper.equals(localName); |
| } |
| |
| return ((currentNode.getNonAttributeChildrenMap() == null |
| || currentNode.getNonAttributeChildrenMap().size() == 0 |
| || (currentNode.getNonAttributeChildrenMap().size() == 1 |
| && currentNode.getTextNode() != null) |
| ) && textWrapper != null && textWrapper.equals(localName) |
| ); |
| } |
| |
| |
| @Override |
| public Object convertValueBasedOnSchemaType(Field xmlField, Object value, ConversionManager conversionManager, AbstractUnmarshalRecord record) { |
| if (xmlField.getSchemaType() != null) { |
| if (Constants.QNAME_QNAME.equals(xmlField.getSchemaType())) { |
| String stringValue = (String) value; |
| int indexOpen = stringValue.indexOf('{'); |
| int indexClose = stringValue.indexOf('}'); |
| String uri; |
| String localName; |
| if (indexOpen > -1 && indexClose > -1) { |
| uri = stringValue.substring(indexOpen + 1, indexClose); |
| localName = stringValue.substring(indexClose + 1); |
| } else { |
| QName obj = (QName) xmlField.convertValueBasedOnSchemaType(stringValue, conversionManager, record); |
| localName = obj.getLocalPart(); |
| uri = obj.getNamespaceURI(); |
| } |
| if (uri != null) { |
| return new QName(uri, localName); |
| } else { |
| return new QName(localName); |
| } |
| } else { |
| Class fieldType = xmlField.getType(); |
| if (fieldType == null) { |
| fieldType = xmlField.getJavaClass(xmlField.getSchemaType(), conversionManager); |
| } |
| return conversionManager.convertObject(value, fieldType, xmlField.getSchemaType()); |
| } |
| } |
| return value; |
| } |
| |
| /** |
| * INTERNAL: The MediaType associated with this reader |
| */ |
| @Override |
| public MediaType getMediaType() { |
| return Constants.APPLICATION_JSON; |
| } |
| |
| private static class JsonAttributes extends IndexedAttributeList { |
| |
| private JsonValue value; |
| private String attributePrefix; |
| private char namespaceSeparator; |
| private NamespaceResolver namespaces; |
| private boolean namespaceAware; |
| |
| public JsonAttributes setValue(JsonValue value, String attributePrefix, NamespaceResolver nr, char namespaceSeparator, boolean namespaceAware) { |
| reset(); |
| this.value = value; |
| this.attributePrefix = attributePrefix; |
| this.namespaces = nr; |
| this.namespaceSeparator = namespaceSeparator; |
| this.namespaceAware = namespaceAware; |
| return this; |
| } |
| |
| private void addSimpleAttribute(List<Attribute> attributes, String uri, String attributeLocalName, JsonValue childValue) { |
| switch (childValue.getValueType()) { |
| case STRING: { |
| String stringValue = ((JsonString) childValue).getString(); |
| attributes.add(new Attribute(uri, attributeLocalName, attributeLocalName, stringValue)); |
| break; |
| } |
| case NUMBER: { |
| attributes.add(new Attribute(uri, attributeLocalName, attributeLocalName, childValue.toString())); |
| break; |
| } |
| case FALSE: { |
| attributes.add(new Attribute(uri, attributeLocalName, attributeLocalName, FALSE)); |
| break; |
| } |
| case TRUE: { |
| attributes.add(new Attribute(uri, attributeLocalName, attributeLocalName, TRUE)); |
| break; |
| } |
| case ARRAY: |
| case OBJECT: |
| case NULL: |
| break; // noop |
| default: |
| throw new IllegalStateException("Unhandled valueType: " + childValue.getValueType()); |
| } |
| } |
| |
| @Override |
| public int getIndex(String uri, String localName) { |
| if (null == localName) { |
| return -1; |
| } |
| int index = 0; |
| for (Attribute attribute : attributes()) { |
| if (namespaceAware) { |
| if (localName.equals(attribute.getLocalName()) && uri.equals(attribute.getUri())) { |
| return index; |
| } |
| } else { |
| if (attribute.getName().equals(localName)) { |
| return index; |
| } |
| } |
| index++; |
| } |
| return -1; |
| } |
| |
| @Override |
| protected Attribute[] attributes() { |
| if (null == attributes) { |
| |
| switch (value.getValueType()) { |
| case NULL: { |
| return NO_ATTRIBUTES; |
| } |
| case OBJECT: { |
| JsonObject jsonObject = (JsonObject) value; |
| ArrayList<Attribute> attributesList = new ArrayList<>(jsonObject.values().size()); |
| |
| for (Entry<String, JsonValue> nextEntry : jsonObject.entrySet()) { |
| String attributeLocalName = nextEntry.getKey(); |
| |
| if (attributePrefix != null) { |
| if (attributeLocalName.startsWith(attributePrefix)) { |
| attributeLocalName = attributeLocalName.substring(attributePrefix.length()); |
| } else { |
| continue; |
| } |
| } |
| |
| String uri = Constants.EMPTY_STRING; |
| |
| if (namespaceAware && namespaces != null) { |
| if (attributeLocalName.length() > 2) { |
| String prefix = Constants.EMPTY_STRING; |
| int nsIndex = attributeLocalName.indexOf(namespaceSeparator, 1); |
| if (nsIndex > -1) { |
| prefix = attributeLocalName.substring(0, nsIndex); |
| } |
| uri = namespaces.resolveNamespacePrefix(prefix); |
| if (uri == null) { |
| uri = namespaces.getDefaultNamespaceURI(); |
| } else { |
| attributeLocalName = attributeLocalName.substring(nsIndex + 1); |
| } |
| } else { |
| uri = namespaces.getDefaultNamespaceURI(); |
| } |
| } |
| |
| JsonValue nextValue = nextEntry.getValue(); |
| if (nextValue.getValueType() == ValueType.ARRAY) { |
| JsonArray jsonArray = (JsonArray) nextValue; |
| if (jsonArray.size() == 0) { |
| attributesList.add(new Attribute(uri, attributeLocalName, attributeLocalName, "")); |
| } |
| for (JsonValue nextChildValue : jsonArray) { |
| addSimpleAttribute(attributesList, uri, attributeLocalName, nextChildValue); |
| } |
| } else { |
| addSimpleAttribute(attributesList, uri, attributeLocalName, nextValue); |
| } |
| } |
| |
| attributes = attributesList.toArray(new Attribute[attributesList.size()]); |
| break; |
| } |
| default: { |
| attributes = NO_ATTRIBUTES; |
| } |
| } |
| } |
| return attributes; |
| } |
| |
| } |
| |
| } |