package org.jvnet.jaxb2_commons.xjc.model.concrete; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import org.jvnet.jaxb2_commons.xjc.model.concrete.origin.XJCCMClassInfoOrigin; import org.jvnet.jaxb2_commons.xjc.model.concrete.origin.XJCCMElementInfoOrigin; import org.jvnet.jaxb2_commons.xjc.model.concrete.origin.XJCCMEnumConstantInfoOrigin; import org.jvnet.jaxb2_commons.xjc.model.concrete.origin.XJCCMEnumLeafInfoOrigin; import org.jvnet.jaxb2_commons.xjc.model.concrete.origin.XJCCMModelInfoOrigin; import org.jvnet.jaxb2_commons.xjc.model.concrete.origin.XJCCMPackageInfoOrigin; import org.jvnet.jaxb2_commons.xjc.model.concrete.origin.XJCCMPropertyInfoOrigin; import org.jvnet.jaxb2_commons.xml.bind.model.MClassInfo; import org.jvnet.jaxb2_commons.xml.bind.model.MClassRef; import org.jvnet.jaxb2_commons.xml.bind.model.MClassTypeInfo; import org.jvnet.jaxb2_commons.xml.bind.model.MContainer; import org.jvnet.jaxb2_commons.xml.bind.model.MPackageInfo; import org.jvnet.jaxb2_commons.xml.bind.model.MTypeInfo; import org.jvnet.jaxb2_commons.xml.bind.model.concrete.CMClassRef; import org.jvnet.jaxb2_commons.xml.bind.model.concrete.CMInfoFactory; import org.jvnet.jaxb2_commons.xml.bind.model.concrete.CMPackageInfo; import org.jvnet.jaxb2_commons.xml.bind.model.concrete.origin.CMPackageInfoOrigin; import org.jvnet.jaxb2_commons.xml.bind.model.origin.MClassInfoOrigin; import org.jvnet.jaxb2_commons.xml.bind.model.origin.MElementInfoOrigin; import org.jvnet.jaxb2_commons.xml.bind.model.origin.MEnumConstantInfoOrigin; import org.jvnet.jaxb2_commons.xml.bind.model.origin.MEnumLeafInfoOrigin; import org.jvnet.jaxb2_commons.xml.bind.model.origin.MModelInfoOrigin; import org.jvnet.jaxb2_commons.xml.bind.model.origin.MPackageInfoOrigin; import org.jvnet.jaxb2_commons.xml.bind.model.origin.MPropertyInfoOrigin; import com.sun.codemodel.JClass; import com.sun.codemodel.JPackage; import com.sun.tools.xjc.model.CAttributePropertyInfo; import com.sun.tools.xjc.model.CBuiltinLeafInfo; import com.sun.tools.xjc.model.CClassInfo; import com.sun.tools.xjc.model.CClassInfoParent; import com.sun.tools.xjc.model.CClassInfoParent.Visitor; import com.sun.tools.xjc.model.CClassRef; import com.sun.tools.xjc.model.CElementInfo; import com.sun.tools.xjc.model.CElementPropertyInfo; import com.sun.tools.xjc.model.CEnumConstant; import com.sun.tools.xjc.model.CEnumLeafInfo; import com.sun.tools.xjc.model.CPropertyInfo; import com.sun.tools.xjc.model.CReferencePropertyInfo; import com.sun.tools.xjc.model.CTypeInfo; import com.sun.tools.xjc.model.CValuePropertyInfo; import com.sun.tools.xjc.model.CWildcardTypeInfo; import com.sun.tools.xjc.model.Model; 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; public class XJCCMInfoFactory extends CMInfoFactory<NType, NClass, Model, CTypeInfo, CBuiltinLeafInfo, CElementInfo, CEnumLeafInfo, CEnumConstant, CClassInfo, CPropertyInfo, CAttributePropertyInfo, CValuePropertyInfo, CElementPropertyInfo, CReferencePropertyInfo, CWildcardTypeInfo> { private final Map<CClassRef, MClassRef<NType, NClass>> classRefs = new IdentityHashMap<CClassRef, MClassRef<NType, NClass>>(); public XJCCMInfoFactory(Model model) { super(model); } protected NClass getClazz(CClassRef info) { return info; } protected NClass getClazz(final Class<?> _clas) { return new NClass() { @Override public boolean isBoxedType() { return false; } @Override public String fullName() { return _clas.getName(); } @Override public JClass toType(Outline o, Aspect aspect) { return o.getCodeModel().ref(_clas); } @Override public boolean isAbstract() { return false; } }; } protected NClass getClazz(final String className) { return new NClass() { @Override public boolean isBoxedType() { return false; } @Override public String fullName() { return className; } @Override public JClass toType(Outline o, Aspect aspect) { return o.getCodeModel().ref(className); } @Override public boolean isAbstract() { return false; } }; } protected MClassRef<NType, NClass> createClassRef(Class<?> _class) { return new CMClassRef<NType, NClass>(getClazz(_class), getPackage(_class), getContainer(_class), getLocalName(_class)); } protected MClassRef<NType, NClass> getTypeInfo(CClassRef info) { MClassRef<NType, NClass> classInfo = classRefs.get(info); if (classInfo == null) { classInfo = createClassRef(info); classRefs.put(info, classInfo); } return classInfo; } protected MClassRef<NType, NClass> createClassRef(CClassRef info) { return new CMClassRef<NType, NClass>(getClazz(info), getPackage(info), getContainer(info), getLocalName(info)); } @Override protected MTypeInfo<NType, NClass> getTypeInfo(CTypeInfo typeInfo) { if (typeInfo instanceof CClassRef) { return getTypeInfo((CClassRef) typeInfo); } else { return super.getTypeInfo(typeInfo); } } @Override protected MPackageInfo getPackage(CClassInfo info) { return getPackage(info.parent()); } protected MPackageInfo getPackage(CClassRef info) { final String fullName = info.fullName(); return getPackage(fullName); } private MPackageInfo getPackage(final String fullName) { try { final Class<?> _class = Class.forName(fullName); return getPackage(_class); } catch (ClassNotFoundException cnfex) { final String packageName; final int lastIndexOfDot = fullName.lastIndexOf('.'); if (lastIndexOfDot != -1) { packageName = fullName.substring(0, lastIndexOfDot); } else { packageName = ""; } return new CMPackageInfo(new CMPackageInfoOrigin(), packageName); } } private MPackageInfo getPackage(final Class _class) { final Package _package = _class.getPackage(); return new CMPackageInfo(new CMPackageInfoOrigin(), _package.getName()); } @Override protected MPackageInfo getPackage(CEnumLeafInfo info) { return getPackage(info.parent); } @Override protected MPackageInfo getPackage(CElementInfo info) { return getPackage(info.parent); } @Override protected MContainer getContainer(CClassInfo info) { final CClassInfoParent parent = info.parent(); return parent == null ? null : getContainer(parent); } @Override protected MContainer getContainer(CElementInfo info) { final CClassInfoParent parent = info.parent; return parent == null ? null : getContainer(parent); } @Override protected MContainer getContainer(CEnumLeafInfo info) { final CClassInfoParent parent = info.parent; return parent == null ? null : getContainer(parent); } protected MContainer getContainer(CClassRef info) { final String fullName = info.fullName(); try { final Class<?> _class = Class.forName(fullName); return getContainer(_class); } catch (ClassNotFoundException cnfex) { return getPackage(info); } } private MContainer getContainer(final Class<?> _class) { final Class<?> enclosingClass = _class.getEnclosingClass(); if (enclosingClass == null) { return getPackage(_class); } else { return createClassRef(enclosingClass); } } private final Map<String, MPackageInfo> packages = new HashMap<String, MPackageInfo>(); private MContainer getContainer(CClassInfoParent parent) { return parent.accept(new Visitor<MContainer>() { public MContainer onBean(CClassInfo bean) { return getTypeInfo(bean); } public MContainer onPackage(JPackage pkg) { return getPackage(pkg); } public MContainer onElement(CElementInfo element) { return getElementInfo(element); } }); } private MPackageInfo getPackage(CClassInfoParent parent) { return parent.accept(new Visitor<MPackageInfo>() { public MPackageInfo onBean(CClassInfo bean) { return getPackage(bean.parent()); } public MPackageInfo onPackage(JPackage pkg) { return getPackage(pkg); } public MPackageInfo onElement(CElementInfo element) { return getPackage(element.parent); } }); } @Override protected MClassInfo<NType, NClass> getScope(CClassInfo info) { return info.getScope() == null ? null : getTypeInfo(info.getScope()); } @Override protected String getLocalName(CClassInfo info) { return info.shortName; } protected String getLocalName(CClassRef info) { final String fullName = info.fullName(); try { final Class<?> _class = Class.forName(fullName); return getLocalName(_class); } catch (ClassNotFoundException cnfex) { return getLocalName(fullName); } } private String getLocalName(final String fullName) { final int lastIndexOfDollar = fullName.lastIndexOf('$'); if (lastIndexOfDollar != -1) { return fullName.substring(lastIndexOfDollar + 1); } final int lastIndexOfDot = fullName.lastIndexOf('.'); if (lastIndexOfDot != -1) { return fullName.substring(lastIndexOfDot + 1); } return fullName; } private String getLocalName(final Class<?> _class) { return _class.getSimpleName(); } @Override protected String getLocalName(CEnumLeafInfo info) { return info.shortName; } @Override protected String getLocalName(CElementInfo info) { return info.shortName(); } @Override protected MModelInfoOrigin createModelInfoOrigin(Model info) { return new XJCCMModelInfoOrigin(info); } protected MPackageInfoOrigin createPackageInfoOrigin(JPackage info) { return new XJCCMPackageInfoOrigin(info); } protected MClassInfoOrigin createClassInfoOrigin(CClassInfo info) { return new XJCCMClassInfoOrigin(info); } @Override protected MPropertyInfoOrigin createPropertyInfoOrigin(CPropertyInfo info) { return new XJCCMPropertyInfoOrigin(info); } @Override protected MElementInfoOrigin createElementInfoOrigin(CElementInfo info) { return new XJCCMElementInfoOrigin(info); } @Override protected MEnumLeafInfoOrigin createEnumLeafInfoOrigin(CEnumLeafInfo info) { return new XJCCMEnumLeafInfoOrigin(info); } @Override protected MEnumConstantInfoOrigin createEnumConstantInfoOrigin( CEnumConstant info) { return new XJCCMEnumConstantInfoOrigin(info); } @Override protected NType createListType(final NType elementType) { return new NClass() { public boolean isBoxedType() { return false; } public String fullName() { return List.class.getName(); } public JClass toType(Outline o, Aspect aspect) { return o.getCodeModel().ref(List.class) .narrow(elementType.toType(o, aspect).boxify()); } public boolean isAbstract() { return false; } }; } private MPackageInfo getPackage(JPackage pkg) { String packageName = pkg.name(); MPackageInfo _package = packages.get(packageName); if (_package == null) { _package = new CMPackageInfo(createPackageInfoOrigin(pkg), packageName); packages.put(packageName, _package); } return _package; } @Override protected MClassTypeInfo<NType, NClass> createBaseTypeInfo(CClassInfo info) { if (info.getBaseClass() != null) { return getTypeInfo(info.getBaseClass()); } else if (info.getRefBaseClass() != null) { return getTypeInfo(info.getRefBaseClass()); } else { return null; } } }