/*
 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.internal.xjc.generator.bean;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.namespace.QName;

import com.sun.codemodel.internal.JDefinedClass;
import com.sun.codemodel.internal.JPackage;
import com.sun.tools.internal.xjc.generator.annotation.spec.XmlSchemaWriter;
import com.sun.tools.internal.xjc.model.CAttributePropertyInfo;
import com.sun.tools.internal.xjc.model.CClassInfo;
import com.sun.tools.internal.xjc.model.CElement;
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
import com.sun.tools.internal.xjc.model.CPropertyInfo;
import com.sun.tools.internal.xjc.model.CPropertyVisitor;
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
import com.sun.tools.internal.xjc.model.CTypeRef;
import com.sun.tools.internal.xjc.model.CValuePropertyInfo;
import com.sun.tools.internal.xjc.model.Model;
import com.sun.tools.internal.xjc.outline.PackageOutline;
import com.sun.tools.internal.xjc.outline.Aspect;

PackageOutline enhanced with schema2java specific information.
Author: Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com), Martin Grebac (martin.grebac@oracle.com)
/** * {@link PackageOutline} enhanced with schema2java specific * information. * * @author * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com), Martin Grebac (martin.grebac@oracle.com) */
public final class PackageOutlineImpl implements PackageOutline { private final Model _model; private final JPackage _package; private final ObjectFactoryGenerator objectFactoryGenerator; /*package*/ final Set<ClassOutlineImpl> classes = new HashSet<ClassOutlineImpl>(); private final Set<ClassOutlineImpl> classesView = Collections.unmodifiableSet(classes); private String mostUsedNamespaceURI; private XmlNsForm elementFormDefault; private XmlNsForm attributeFormDefault;
The namespace URI most commonly used in classes in this package. This should be used as the namespace URI for XmlSchema.namespace().

Null if no default

See Also:
/** * The namespace URI most commonly used in classes in this package. * This should be used as the namespace URI for {@link XmlSchema#namespace()}. * * <p> * Null if no default * * @see #calcDefaultValues() */
public String getMostUsedNamespaceURI() { return mostUsedNamespaceURI; }
The attribute form default for this package.

The value is computed by examining what would yield the smallest generated code.

/** * The attribute form default for this package. * <p> * The value is computed by examining what would yield the smallest generated code. */
public XmlNsForm getAttributeFormDefault() { assert attributeFormDefault!=null; return attributeFormDefault; }
The element form default for this package.

The value is computed by examining what would yield the smallest generated code.

/** * The element form default for this package. * <p> * The value is computed by examining what would yield the smallest generated code. */
public XmlNsForm getElementFormDefault() { assert elementFormDefault!=null; return elementFormDefault; } public JPackage _package() { return _package; } public ObjectFactoryGenerator objectFactoryGenerator() { return objectFactoryGenerator; } public Set<ClassOutlineImpl> getClasses() { return classesView; } public JDefinedClass objectFactory() { return objectFactoryGenerator.getObjectFactory(); } protected PackageOutlineImpl( BeanGenerator outline, Model model, JPackage _pkg ) { this._model = model; this._package = _pkg; switch(model.strategy) { case BEAN_ONLY: objectFactoryGenerator = new PublicObjectFactoryGenerator(outline,model,_pkg); break; case INTF_AND_IMPL: objectFactoryGenerator = new DualObjectFactoryGenerator(outline,model,_pkg); break; default: throw new IllegalStateException(); } }
Compute the most common namespace URI in this package (to put into XmlSchema.namespace() and what value we should put into XmlSchema.elementFormDefault(). This method is called after classes field is filled up.
/** * Compute the most common namespace URI in this package * (to put into {@link XmlSchema#namespace()} and what value * we should put into {@link XmlSchema#elementFormDefault()}. * * This method is called after {@link #classes} field is filled up. */
public void calcDefaultValues() { // short-circuit if xjc was told not to generate package level annotations in // package-info.java if(!_model.isPackageLevelAnnotations()) { mostUsedNamespaceURI = ""; elementFormDefault = XmlNsForm.UNQUALIFIED; return; } // used to visit properties CPropertyVisitor<Void> propVisitor = new CPropertyVisitor<Void>() { public Void onElement(CElementPropertyInfo p) { for (CTypeRef tr : p.getTypes()) { countURI(propUriCountMap, tr.getTagName()); } return null; } public Void onReference(CReferencePropertyInfo p) { for (CElement e : p.getElements()) { countURI(propUriCountMap, e.getElementName()); } return null; } public Void onAttribute(CAttributePropertyInfo p) { return null; } public Void onValue(CValuePropertyInfo p) { return null; } }; for (ClassOutlineImpl co : classes) { CClassInfo ci = co.target; countURI(uriCountMap, ci.getTypeName()); countURI(uriCountMap, ci.getElementName()); for( CPropertyInfo p : ci.getProperties() ) p.accept(propVisitor); } mostUsedNamespaceURI = getMostUsedURI(uriCountMap); elementFormDefault = getFormDefault(); attributeFormDefault = XmlNsForm.UNQUALIFIED; try { XmlNsForm modelValue = _model.getAttributeFormDefault(mostUsedNamespaceURI); attributeFormDefault = modelValue; } catch (Exception e) { // ignore and accept default } // generate package-info.java // we won't get this far if the user specified -npa if(!mostUsedNamespaceURI.equals("") || elementFormDefault==XmlNsForm.QUALIFIED || (attributeFormDefault == XmlNsForm.QUALIFIED)) { XmlSchemaWriter w = _model.strategy.getPackage(_package, Aspect.IMPLEMENTATION).annotate2(XmlSchemaWriter.class); if(!mostUsedNamespaceURI.equals("")) w.namespace(mostUsedNamespaceURI); if(elementFormDefault==XmlNsForm.QUALIFIED) w.elementFormDefault(elementFormDefault); if(attributeFormDefault==XmlNsForm.QUALIFIED) w.attributeFormDefault(attributeFormDefault); } } // Map to keep track of how often each type or element uri is used in this package // mostly used to calculate mostUsedNamespaceURI private HashMap<String, Integer> uriCountMap = new HashMap<String, Integer>(); // Map to keep track of how often each property uri is used in this package // used to calculate elementFormDefault private HashMap<String, Integer> propUriCountMap = new HashMap<String, Integer>();
pull the uri out of the specified QName and keep track of it in the specified hash map
Params:
  • qname –
/** * pull the uri out of the specified QName and keep track of it in the * specified hash map * * @param qname */
private void countURI(HashMap<String, Integer> map, QName qname) { if (qname == null) return; String uri = qname.getNamespaceURI(); if (map.containsKey(uri)) { map.put(uri, map.get(uri) + 1); } else { map.put(uri, 1); } }
Iterate through the hash map looking for the namespace used most frequently. Ties are arbitrarily broken by the order in which the map keys are iterated over.

Because JAX-WS often reassigns the "" namespace URI, and when that happens it unintentionally also renames (normally unqualified) local elements, prefer non-"" URI when there's a tie.

/** * Iterate through the hash map looking for the namespace used * most frequently. Ties are arbitrarily broken by the order * in which the map keys are iterated over. * * <p> * Because JAX-WS often reassigns the "" namespace URI, * and when that happens it unintentionally also renames (normally * unqualified) local elements, prefer non-"" URI when there's a tie. */
private String getMostUsedURI(HashMap<String, Integer> map) { String mostPopular = null; int count = 0; for (Map.Entry<String,Integer> e : map.entrySet()) { String uri = e.getKey(); int uriCount = e.getValue(); if (mostPopular == null) { mostPopular = uri; count = uriCount; } else { if (uriCount > count || (uriCount==count && mostPopular.equals(""))) { mostPopular = uri; count = uriCount; } } } if (mostPopular == null) return ""; return mostPopular; }
Calculate the element form defaulting. Compare the most frequently used property URI to the most frequently used element/type URI. If they match, then return QUALIFIED
/** * Calculate the element form defaulting. * * Compare the most frequently used property URI to the most frequently used * element/type URI. If they match, then return QUALIFIED */
private XmlNsForm getFormDefault() { if (getMostUsedURI(propUriCountMap).equals("")) return XmlNsForm.UNQUALIFIED; else return XmlNsForm.QUALIFIED; } }