/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 *******************************************************************************/ package org.ebayopensource.turmeric.runtime.common.impl.internal.schema; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import org.ebayopensource.turmeric.runtime.binding.schema.DataElementSchema; import org.ebayopensource.turmeric.runtime.binding.utils.CollectionUtils; /** * @author ichernyshev */ public final class DataElementSchemaImpl implements DataElementSchema { private final QName m_elementName; private final int m_maxOccurs; private Map<QName, DataElementSchema> m_children; private Map<String, DataElementSchema[]> m_childrenByLocalName = new HashMap<String, DataElementSchema[]>(); public DataElementSchemaImpl(QName elementName, int maxOccurs) { m_elementName = elementName; m_maxOccurs = maxOccurs; } public DataElementSchemaImpl(QName elementName, int maxOccurs, List<DataElementSchema> children) { this(elementName, maxOccurs); setChildren(children); } public void setChildren(List<DataElementSchema> children) { if (children == null || children.isEmpty()) { m_children = null; return; } int size = children.size(); // Creates m_children and hashmap of local name to DataElementSchema // ArrayList. HashMap<String, ArrayList<DataElementSchema>> childrenByLocalName = new HashMap<String, ArrayList<DataElementSchema>>( size); m_children = new HashMap<QName, DataElementSchema>(size); for (DataElementSchema child : children) { QName elementName = child.getElementName(); m_children.put(elementName, child); String localName = elementName.getLocalPart(); ArrayList<DataElementSchema> elementSchemas = childrenByLocalName .get(localName); if (null == elementSchemas) { elementSchemas = new ArrayList<DataElementSchema>(1); childrenByLocalName.put(localName, elementSchemas); } elementSchemas.add(child); } // Creates haspmap of local name to DataElementSchema element array. m_childrenByLocalName = new HashMap<String, DataElementSchema[]>( childrenByLocalName.size()); for (String localName : childrenByLocalName.keySet()) { ArrayList<DataElementSchema> elementSchemaList = childrenByLocalName .get(localName); int listSize = elementSchemaList.size(); DataElementSchema[] elementSchemsArray = new DataElementSchema[listSize]; for (int i = 0; i < listSize; i++) { elementSchemsArray[i] = elementSchemaList.get(i); } m_childrenByLocalName.put(localName, elementSchemsArray); } m_children = Collections.unmodifiableMap(m_children); m_childrenByLocalName = Collections .unmodifiableMap(m_childrenByLocalName); } DataElementSchemaImpl copyElement(QName elementName, int maxOccurs) { // make a new children map List<DataElementSchema> children = null; if (m_children != null) { children = new ArrayList<DataElementSchema>(); for (DataElementSchema child : m_children.values()) { children.add(child); } } // create root element with a different name, but the same children DataElementSchemaImpl result = new DataElementSchemaImpl(elementName, maxOccurs); result.setChildren(children); return result; } public QName getElementName() { return m_elementName; } public int getMaxOccurs() { return m_maxOccurs; } public boolean hasChildren() { return m_children != null; } public Collection<QName> getChildrenNames() { if (m_children == null) { return CollectionUtils.EMPTY_QNAME_SET; } return m_children.keySet(); } public DataElementSchema getChild(QName name) { if (m_children == null) { return null; } DataElementSchema childSchema = m_children.get(name); if (null != childSchema) { return childSchema; } return getChild(name.getNamespaceURI(), name.getLocalPart()); } public DataElementSchema getChild(String namespaceURI, String localName) { DataElementSchema[] elementSchemsArray = m_childrenByLocalName .get(localName); if (null == elementSchemsArray) { return null; } if (namespaceURI == null || namespaceURI.length() == 0) { if (elementSchemsArray.length == 1) { return elementSchemsArray[0]; } // If the name comes with a empty nsURI, we will assume that it has // the same ns as its parent. So, we search the schema info by // local part. namespaceURI = m_elementName.getNamespaceURI(); } DataElementSchema elementSchemaFound = null; for (DataElementSchema elementSchema : elementSchemsArray) { if (elementSchema.getElementName().getNamespaceURI().equals( namespaceURI)) { elementSchemaFound = elementSchema; break; } } // if still not found or namespaces didn't match use the local part. // Fix added for backward compatability with Codegen bug related to JSON // and useSchemaInfo=true // to avoid creation of arrays by default in a JSON type response. if (elementSchemaFound == null) { if (elementSchemsArray.length == 1) { return elementSchemsArray[0]; } } return elementSchemaFound; } }