All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.tools.xjc.model.CClassInfo Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package com.sun.tools.xjc.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlID;
import jakarta.xml.bind.annotation.XmlIDREF;
import jakarta.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;

import com.sun.codemodel.JClass;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JPackage;
import com.sun.istack.Nullable;
import com.sun.tools.xjc.Language;
import com.sun.tools.xjc.model.nav.NClass;
import com.sun.tools.xjc.model.nav.NType;
import com.sun.tools.xjc.outline.Aspect;
import com.sun.tools.xjc.outline.Outline;
import com.sun.tools.xjc.reader.Ring;
import com.sun.tools.xjc.reader.xmlschema.BGMBuilder;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIFactoryMethod;
import org.glassfish.jaxb.core.v2.model.core.ClassInfo;
import org.glassfish.jaxb.core.v2.model.core.Element;
import com.sun.xml.xsom.ForeignAttributes;
import com.sun.xml.xsom.XSComponent;

import org.xml.sax.Locator;

/**
 * Mutable {@link ClassInfo} representation.
 *
 * 

* Schema parsers build these objects. * * @author Kohsuke Kawaguchi */ public final class CClassInfo extends AbstractCElement implements ClassInfo, CClassInfoParent, CClass, NClass { @XmlIDREF private CClass baseClass; /** * List of all subclasses, together with {@link #nextSibling}. * * If this class has no sub-class, this field is null. Otherwise, * this field points to a sub-class of this class. From there you can enumerate * all the sub-classes by using {@link #nextSibling}. */ private CClassInfo firstSubclass; /** * @see #firstSubclass */ private CClassInfo nextSibling = null; /** * @see #getTypeName() */ private final QName typeName; /** * Custom {@link #getSqueezedName() squeezed name}, if any. */ private /*almost final*/ @Nullable String squeezedName; /** * If this class also gets {@link XmlRootElement}, the class name. */ private final @Nullable QName elementName; private boolean isOrdered = true; private final List properties = new ArrayList<>(); /** * TODO: revisit this design. * we should at least do a basic encapsulation to avoid careless * mistakes. Maybe we should even differ the javadoc generation * by queueing runners. */ public String javadoc; @XmlIDREF private final CClassInfoParent parent; /** * short name. */ public final String shortName; /** * Optional user-specified implementation override class. */ private @Nullable String implClass; /** * The {@link Model} object to which this bean belongs. */ public final Model model; /** * @see #hasAttributeWildcard() */ private boolean hasAttributeWildcard; public CClassInfo(Model model,JPackage pkg, String shortName, Locator location, QName typeName, QName elementName, XSComponent source, CCustomizations customizations) { this(model,model.getPackage(pkg),shortName,location,typeName,elementName,source,customizations); } public CClassInfo(Model model,CClassInfoParent p, String shortName, Locator location, QName typeName, QName elementName, XSComponent source, CCustomizations customizations) { super(model,source,location,customizations); this.model = model; this.parent = p; this.shortName = model.allocator.assignClassName(parent,shortName); this.typeName = typeName; this.elementName = elementName; Language schemaLanguage = model.options.getSchemaLanguage(); if ((schemaLanguage != null) && (schemaLanguage.equals(Language.XMLSCHEMA) || schemaLanguage.equals(Language.WSDL))) { BIFactoryMethod factoryMethod = Ring.get(BGMBuilder.class).getBindInfo(source).get(BIFactoryMethod.class); if(factoryMethod!=null) { factoryMethod.markAsAcknowledged(); this.squeezedName = factoryMethod.name; } } model.add(this); } public CClassInfo(Model model,JCodeModel cm, String fullName, Locator location, QName typeName, QName elementName, XSComponent source, CCustomizations customizations) { super(model,source,location,customizations); this.model = model; int idx = fullName.lastIndexOf('.'); if(idx<0) { this.parent = model.getPackage(cm.rootPackage()); this.shortName = model.allocator.assignClassName(parent,fullName); } else { this.parent = model.getPackage(cm._package(fullName.substring(0,idx))); this.shortName = model.allocator.assignClassName(parent,fullName.substring(idx+1)); } this.typeName = typeName; this.elementName = elementName; model.add(this); } @Override public boolean hasAttributeWildcard() { return hasAttributeWildcard; } public void hasAttributeWildcard(boolean hasAttributeWildcard) { this.hasAttributeWildcard = hasAttributeWildcard; } @Override public boolean hasSubClasses() { return firstSubclass!=null; } /** * Returns true if a new attribute wildcard property needs to be * declared on this class. */ @Override public boolean declaresAttributeWildcard() { return hasAttributeWildcard && !inheritsAttributeWildcard(); } /** * Returns true if this class inherits a wildcard attribute property * from its ancestor classes. */ @Override public boolean inheritsAttributeWildcard() { if (getRefBaseClass() != null) { CClassRef cref = (CClassRef)baseClass; for(ForeignAttributes foreignAttributes: cref.getSchemaComponent().getForeignAttributes()) { if(foreignAttributes.getLength() > 0) { return true; } } } else { for( CClassInfo c=getBaseClass(); c!=null; c=c.getBaseClass() ) { if(c.hasAttributeWildcard) return true; } } return false; } @Override public NClass getClazz() { return this; } @Override public CClassInfo getScope() { return null; } @XmlID @Override public String getName() { return fullName(); } /** * Returns the "squeezed name" of this bean token. *

* The squeezed name of a bean is the concatenation of * the names of its outer classes and itself. *

* Thus if the bean is "org.acme.foo.Bean", then the squeezed name is "Bean", * if the bean is "org.acme.foo.Outer1.Outer2.Bean", then "Outer1Outer2Bean". *

* This is used by the code generator */ @XmlElement public String getSqueezedName() { if (squeezedName != null) return squeezedName; return calcSqueezedName.onBean(this); } private static final CClassInfoParent.Visitor calcSqueezedName = new Visitor<>() { @Override public String onBean(CClassInfo bean) { return bean.parent.accept(this) + bean.shortName; } @Override public String onElement(CElementInfo element) { return element.parent.accept(this) + element.shortName(); } @Override public String onPackage(JPackage pkg) { return ""; } }; /** * Returns a mutable list. */ @Override public List getProperties() { return properties; } @Override public boolean hasValueProperty() { throw new UnsupportedOperationException(); } /** * Gets a propery by name. */ @Override public CPropertyInfo getProperty(String name) { // TODO: does this method need to be fast? for( CPropertyInfo p : properties ) if(p.getName(false).equals(name)) return p; return null; } @Override public boolean hasProperties() { return !getProperties().isEmpty(); } @Override public boolean isElement() { return elementName!=null; } /** * Guaranteed to return this. */ @Deprecated @Override public CNonElement getInfo() { return this; } @Override public Element asElement() { if(isElement()) return this; else return null; } @Override public boolean isOrdered() { return isOrdered; } /** * @deprecated * if you are calling this method directly, you must be doing something wrong. */ @Deprecated @Override public boolean isFinal() { return false; } public void setOrdered(boolean value) { isOrdered = value; } @Override public QName getElementName() { return elementName; } @Override public QName getTypeName() { return typeName; } @Override public boolean isSimpleType() { throw new UnsupportedOperationException(); } /** * Returns the FQCN of this bean. */ @Override public String fullName() { String r = parent.fullName(); if(r.length()==0) return shortName; else return r+'.'+shortName; } public CClassInfoParent parent() { return parent; } public void setUserSpecifiedImplClass(String implClass) { assert this.implClass==null; assert implClass!=null; this.implClass = implClass; } public String getUserSpecifiedImplClass() { return implClass; } /** * Adds a new property. */ public void addProperty(CPropertyInfo prop) { if(prop.ref().isEmpty()) // this property isn't contributing anything // this happens when you try to map an empty sequence to a property return; prop.setParent(this); properties.add(prop); } /** * This method accepts both (which means the base class * is also generated), or {@link CClassRef} (which means the base class is * already generated and simply referenced.) * * The latter is treated somewhat special --- from the rest of the model * this external base class is invisible. This modeling might need more * thoughts to get right. */ public void setBaseClass(CClass base) { assert baseClass==null; assert base!=null; baseClass = base; assert nextSibling==null; if (base instanceof CClassInfo) { CClassInfo realBase = (CClassInfo) base; this.nextSibling = realBase.firstSubclass; realBase.firstSubclass = this; } } /** * This inherited version returns null if this class extends from {@link CClassRef}. * * @see #getRefBaseClass() */ @Override public CClassInfo getBaseClass() { if (baseClass instanceof CClassInfo) { return (CClassInfo) baseClass; } else { return null; } } public CClassRef getRefBaseClass() { if (baseClass instanceof CClassRef) { return (CClassRef) baseClass; } else { return null; } } /** * Enumerates all the sub-classes of this class. */ public Iterator listSubclasses() { return new Iterator<>() { CClassInfo cur = firstSubclass; @Override public boolean hasNext() { return cur != null; } @Override public CClassInfo next() { CClassInfo r = cur; cur = cur.nextSibling; return r; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } @Override public CClassInfo getSubstitutionHead() { CClassInfo c=getBaseClass(); while(c!=null && !c.isElement()) c=c.getBaseClass(); return c; } /** * Interfaces to be implemented. * Lazily constructed. */ private Set _implements = null; public void _implements(JClass c) { if(_implements==null) _implements = new HashSet<>(); _implements.add(c); } /** Constructor declarations. array of {@link Constructor}s. */ private final List constructors = new ArrayList<>(1); /** Creates a new constructor declaration and adds it. */ public void addConstructor( String... fieldNames ) { constructors.add(new Constructor(fieldNames)); } /** list all constructor declarations. */ public Collection getConstructors() { return constructors; } @Override public T accept(Visitor visitor) { return visitor.onBean(this); } @Override public JPackage getOwnerPackage() { return parent.getOwnerPackage(); } @Override public NClass getType() { return this; } @Override public JClass toType(Outline o, Aspect aspect) { switch(aspect) { case IMPLEMENTATION: return o.getClazz(this).implRef; case EXPOSED: return o.getClazz(this).ref; default: throw new IllegalStateException(); } } @Override public boolean isBoxedType() { return false; } @Override public String toString() { return fullName(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy