From: <one...@us...> - 2002-11-16 13:12:26
|
Update of /cvsroot/hibernate/Hibernate/cirrus/hibernate/tools/codegen In directory usw-pr-cvs1:/tmp/cvs-serv31226/cirrus/hibernate/tools/codegen Modified Files: ClassMapping.java Log Message: Tom Cellucci's patch allowing correct composite-id generation Index: ClassMapping.java =================================================================== RCS file: /cvsroot/hibernate/Hibernate/cirrus/hibernate/tools/codegen/ClassMapping.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** ClassMapping.java 10 Nov 2002 15:19:48 -0000 1.13 --- ClassMapping.java 16 Nov 2002 13:12:22 -0000 1.14 *************** *** 13,17 **** import cirrus.hibernate.type.Type; - import org.apache.commons.lang.StringUtils; import org.jdom.Attribute; import org.jdom.Element; --- 13,16 ---- *************** *** 19,175 **** public class ClassMapping { ! private ClassName name = null; ! private String superClass = null; ! private String proxyClass = null; ! private List fields = new ArrayList(); ! private TreeSet imports = new TreeSet(); ! private List subclasses = new ArrayList(); ! private static final Map components = new HashMap(); ! ! ! public ClassMapping(ClassName superClass, Element classElement) throws Exception { ! this(classElement); ! ! this.superClass = superClass.getName(); ! addImport(superClass); ! } ! ! public ClassMapping(Element classElement) throws Exception { ! this(classElement, false); ! } ! ! public ClassMapping(Element classElement, boolean component) throws Exception { ! String fullyQualifiedName = classElement.getAttributeValue(component?"class":"name"); ! ! System.out.println("processing mapping for class: " + fullyQualifiedName); ! ! // class & package names ! name = new ClassName(); ! name.setFullyQualifiedName(fullyQualifiedName); ! ! // get the properties defined for this class ! List propertyList = new ArrayList(); ! ! propertyList.addAll( classElement.getChildren("property") ); ! ! Attribute att = classElement.getAttribute("proxy"); ! if (att!=null) proxyClass = att.getValue(); ! ! Element id = classElement.getChild("id"); ! ! if (id != null) propertyList.add(0, id); ! ! // derive the class imports and fields from the properties ! for (Iterator properties = propertyList.iterator(); properties.hasNext();) { ! Element property = (Element) properties.next(); ! ! String name = property.getAttributeValue("name"); ! if ( name == null || name.trim().equals("") ) { ! continue; //since an id doesn't necessarily need a name ! } ! ! // ensure that the type is specified ! String type = property.getAttributeValue("type"); ! if (StringUtils.isEmpty(type)) { ! System.out.println("property \"" + name + "\" in class " + getName() + " is missing a type attribute"); ! continue; ! } ! ! // handle in a different way id and properties... ! // ids may be generated and may need to be of object type in order to support ! // the unsaved-value "null" value. ! // Properties may be nullable (whilst ids can not) ! if(property == id) { ! Element generator = property.getChild("generator"); ! String unsavedValue = property.getAttributeValue("unsaved-value"); ! boolean needObject = (unsavedValue != null && unsavedValue.equals("null")); ! boolean generated = !generator.getAttributeValue("class").equals("assigned"); ! Field idField = new Field(name, getFieldType(type, needObject), true, generated); ! fields.add(idField); ! } else { ! String notnull = property.getAttributeValue("not-null"); ! // if not-null property is missing lets see if it has been ! // defined at column level ! if(notnull == null) { ! Element column = property.getChild("column"); ! if(column != null) ! notnull = column.getAttributeValue("not-null"); ! } ! boolean nullable = (notnull == null || notnull.equals("false")); ! fields.add(new Field(name, getFieldType(type), nullable)); ! } ! } ! ! List onetooneList = classElement.getChildren("one-to-one"); ! for (Iterator onetoones = onetooneList.iterator(); onetoones.hasNext();) { ! Element onetoone = (Element) onetoones.next(); ! ! String name = onetoone.getAttributeValue("name"); ! ! // ensure that the class is specified ! String clazz = onetoone.getAttributeValue("class"); ! if(StringUtils.isEmpty(clazz)) { ! System.out.println("one-to-one \"" + name + "\" in class " + getName() + " is missing a class attribute"); ! continue; ! } ! ! fields.add(new Field(name, getFieldType(clazz), true)); ! ! } ! ! ! // many to ones - TODO: consolidate with code above ! for (Iterator manytoOnes = classElement.getChildren("many-to-one").iterator(); manytoOnes.hasNext();) { ! Element manyToOne = (Element) manytoOnes.next(); ! ! String name = manyToOne.getAttributeValue("name"); ! ! // ensure that the type is specified ! String type = manyToOne.getAttributeValue("class"); ! if ( type == null || type.trim().equals("") ) { ! System.out.println("many-to-one \"" + name + "\" in class " + getName() + " is missing a class attribute"); ! continue; ! } ! ClassName classType = new ClassName(); ! classType.setFullyQualifiedName(type); ! ! // is it nullable? ! String notnull = manyToOne.getAttributeValue("not-null"); ! boolean nullable = (notnull == null || notnull.equals("false")); ! ! // add an import and field for this property ! addImport(classType); ! Field f = new Field( name, classType.getName(), nullable ); ! f.setClassType(classType); ! fields.add(f); ! } ! ! // collections ! doCollections(classElement, "list", "java.util.List", "java.util.ArrayList"); ! doCollections(classElement, "map", "java.util.Map", "java.util.HashMap"); ! doCollections(classElement, "set", "java.util.Set", "java.util.HashSet"); ! doArrays(classElement, "array"); ! doArrays(classElement, "primitive-array"); ! ! ! // subclasses ! ! for ( Iterator iter = classElement.getChildren("subclass").iterator(); iter.hasNext(); ) { ! Element subclass = (Element) iter.next(); ! ClassMapping subclassMapping = new ClassMapping(name, subclass); ! subclasses.add(subclassMapping); ! } ! ! //components ! ! for ( Iterator iter = classElement.getChildren("component").iterator(); iter.hasNext(); ) { ! Element cmpe = (Element) iter.next(); ! String cmpname = cmpe.getAttributeValue("name"); ! String cmpclass = cmpe.getAttributeValue("class"); ! if ( cmpclass==null || cmpclass.equals("") ) { ! System.out.println("component \"" + cmpname + "\" in class " + getName() + " does not specify a class"); ! continue; ! } ! ClassMapping mapping = new ClassMapping(cmpe, true); ClassName classType = new ClassName(); --- 18,73 ---- public class ClassMapping { ! private ClassName name = null; ! private String superClass = null; ! private String proxyClass = null; ! private List fields = new ArrayList(); ! private TreeSet imports = new TreeSet(); ! private List subclasses = new ArrayList(); ! private static final Map components = new HashMap(); ! ! ! public ClassMapping(ClassName superClass, Element classElement) throws Exception { ! this(classElement); ! ! this.superClass = superClass.getName(); ! addImport(superClass); ! } ! ! public ClassMapping(Element classElement) throws Exception { ! this(classElement, false); ! } ! ! public ClassMapping(Element classElement, boolean component) throws Exception { ! String fullyQualifiedName = classElement.getAttributeValue(component?"class":"name"); ! ! System.out.println("processing mapping for class: " + fullyQualifiedName); ! ! // class & package names ! name = new ClassName(); ! name.setFullyQualifiedName(fullyQualifiedName); ! ! // get the properties defined for this class ! List propertyList = new ArrayList(); ! ! propertyList.addAll( classElement.getChildren("property") ); ! ! Attribute att = classElement.getAttribute("proxy"); ! if (att!=null) proxyClass = att.getValue(); ! ! Element id = classElement.getChild("id"); ! ! if (id != null) propertyList.add(0, id); ! // ! // composite id ! ! Element cmpid = classElement.getChild("composite-id"); ! if (cmpid != null) { ! String cmpname = cmpid.getAttributeValue("name"); ! String cmpclass = cmpid.getAttributeValue("class"); ! if ( cmpclass==null || cmpclass.equals("") ) { ! propertyList.addAll(cmpid.getChildren("key-property")); ! } ! else { ! ClassMapping mapping = new ClassMapping(cmpid, true); ClassName classType = new ClassName(); *************** *** 179,331 **** fields.add(new Field(cmpname, classType.getName(), false)); components.put( mapping.getCanonicalName(), mapping ); ! } ! } ! ! public List getFields() { ! return fields; ! } ! ! public TreeSet getImports() { ! return imports; ! } ! ! public String getCanonicalName() { ! return name.getFullyQualifiedName(); ! } ! ! public String getName() { ! return name.getName(); ! } ! ! public String getProxy() { ! return proxyClass; ! } ! ! public String getPackageName() { ! return name.getPackageName(); ! } ! ! public List getSubclasses() { ! return subclasses; ! } ! ! public String getSuperClass() { ! return superClass; ! } ! ! ! // We need a minimal constructor only if it's different from ! // the full constructor or the no-arg constructor. ! // A minimal construtor is one that lets ! // you specify only the required fields. ! public boolean needsMinimalConstructor() { ! boolean generatedId = true; ! boolean missingId = true; ! int countNull = 0; ! for(Iterator it = fields.iterator(); it.hasNext(); ) { ! Field f = (Field) it.next(); ! if(f.isIdentifier()) { ! generatedId = f.isGenerated(); ! missingId = false; ! } ! else ! if(f.isNullable()) countNull++; ! } ! ! return !(countNull == 0 || ! ((countNull == (fields.size() - 1)) && generatedId) || ! ((countNull == (fields.size()) && missingId))); ! ! } ! ! private void addImport(ClassName className) { ! // if the package is java.lang or our own package don't add ! if ( !className.inJavaLang() && !className.inSamePackage(name) ) { ! imports.add( className.getFullyQualifiedName() ); ! } ! } ! ! public static Iterator getComponents() { ! return components.values().iterator(); ! } ! ! private void doCollections(Element classElement, String xmlName, String interfaceClass, String implementingClass) { ! ! ClassName interfaceClassName = new ClassName(); ! ClassName implementingClassName = new ClassName(); ! ! interfaceClassName.setFullyQualifiedName(interfaceClass); ! implementingClassName.setFullyQualifiedName(implementingClass); ! ! for (Iterator collections = classElement.getChildren(xmlName).iterator(); collections.hasNext();) { ! Element collection = (Element) collections.next(); ! ! String name = collection.getAttributeValue("role"); ! ! // add an import and field for this collection ! addImport(interfaceClassName); ! addImport(implementingClassName); ! ! fields.add(new Field(name, interfaceClassName.getName(), "new " + implementingClassName.getName() + "()", false) ); ! } ! } ! ! private void doArrays(Element classElement, String type) { ! for (Iterator arrays = classElement.getChildren(type).iterator(); arrays.hasNext();) { ! Element array = (Element) arrays.next(); ! String role = array.getAttributeValue("role"); ! String elementClass = array.getAttributeValue("element-class"); ! if (elementClass==null) { ! Element elt = array.getChild("element"); ! if (elt==null) elt = array.getChild("one-to-many"); ! if (elt==null) elt = array.getChild("many-to-many"); ! if (elt==null) elt = array.getChild("composite-element"); ! if (elt==null) { ! System.out.println("skipping collection with subcollections"); ! continue; ! } ! elementClass = elt.getAttributeValue("type"); ! if (elementClass==null) elementClass=elt.getAttributeValue("class"); } ! fields.add( new Field( role, getFieldType(elementClass) + "[]", false ) ); ! } ! } ! ! private String getFieldType(String hibernateType) { ! return getFieldType(hibernateType, false); ! } ! ! private String getFieldType(String hibernateType, boolean needObject) { ! // deal with hibernate binary type ! if ( hibernateType.equals("binary") ) { ! return "byte[]"; ! } ! else { ! Type basicType = TypeFactory.basic(hibernateType); ! if ( basicType!=null ) { ! ! if ( ! (basicType instanceof PrimitiveType) && ! !hibernateType.trim().equals( basicType.returnedClass().getName()) && ! !needObject ! ) { ! return ( (PrimitiveType) basicType ).primitiveClass().getName(); ! } ! else { ! return basicType.returnedClass().getName(); ! } ! } else { ! ClassName classType = new ClassName(); ! classType.setFullyQualifiedName(hibernateType); ! // add an import and field for this property ! addImport(classType); ! return classType.getName(); } ! } ! } ! ! ! } --- 77,333 ---- fields.add(new Field(cmpname, classType.getName(), false)); components.put( mapping.getCanonicalName(), mapping ); ! } ! } ! ! // derive the class imports and fields from the properties ! for (Iterator properties = propertyList.iterator(); properties.hasNext();) { ! Element property = (Element) properties.next(); ! ! String name = property.getAttributeValue("name"); ! if ( name == null || name.trim().equals("") ) { ! continue; //since an id doesn't necessarily need a name ! } ! ! // ensure that the type is specified ! String type = property.getAttributeValue("type"); ! if ( type == null || type.trim().equals("") ) { ! System.out.println("property \"" + name + "\" in class " + getName() + " is missing a type attribute"); ! continue; ! } ! ! // handle in a different way id and properties... ! // ids may be generated and may need to be of object type in order to support ! // the unsaved-value "null" value. ! // Properties may be nullable (whilst ids can not) ! if(property == id) { ! Element generator = property.getChild("generator"); ! String unsavedValue = property.getAttributeValue("unsaved-value"); ! boolean needObject = (unsavedValue != null && unsavedValue.equals("null")); ! boolean generated = !generator.getAttributeValue("class").equals("assigned"); ! Field idField = new Field(name, getFieldType(type, needObject), true, generated); ! fields.add(idField); ! } else { ! String notnull = property.getAttributeValue("not-null"); ! // if not-null property is missing lets see if it has been ! // defined at column level ! if(notnull == null) { ! Element column = property.getChild("column"); ! if(column != null) ! notnull = column.getAttributeValue("not-null"); } ! boolean nullable = (notnull == null || notnull.equals("false")); ! fields.add(new Field(name, getFieldType(type), nullable)); ! } ! } ! ! // many to ones - TODO: consolidate with code above ! for (Iterator manytoOnes = classElement.getChildren("many-to-one").iterator(); manytoOnes.hasNext();) { ! Element manyToOne = (Element) manytoOnes.next(); ! ! String name = manyToOne.getAttributeValue("name"); ! ! // ensure that the type is specified ! String type = manyToOne.getAttributeValue("class"); ! if ( type == null || type.trim().equals("") ) { ! System.out.println("many-to-one \"" + name + "\" in class " + getName() + " is missing a class attribute"); ! continue; ! } ! ClassName classType = new ClassName(); ! classType.setFullyQualifiedName(type); ! ! // is it nullable? ! String notnull = manyToOne.getAttributeValue("not-null"); ! boolean nullable = (notnull == null || notnull.equals("false")); ! ! // add an import and field for this property ! addImport(classType); ! Field f = new Field( name, classType.getName(), nullable ); ! f.setClassType(classType); ! fields.add(f); ! } ! ! // collections ! doCollections(classElement, "list", "java.util.List", "java.util.ArrayList"); ! doCollections(classElement, "map", "java.util.Map", "java.util.HashMap"); ! doCollections(classElement, "set", "java.util.Set", "java.util.HashSet"); ! doArrays(classElement, "array"); ! doArrays(classElement, "primitive-array"); ! ! ! // subclasses ! ! for ( Iterator iter = classElement.getChildren("subclass").iterator(); iter.hasNext(); ) { ! Element subclass = (Element) iter.next(); ! ClassMapping subclassMapping = new ClassMapping(name, subclass); ! subclasses.add(subclassMapping); ! } ! ! //components ! ! for ( Iterator iter = classElement.getChildren("component").iterator(); iter.hasNext(); ) { ! Element cmpe = (Element) iter.next(); ! String cmpname = cmpe.getAttributeValue("name"); ! String cmpclass = cmpe.getAttributeValue("class"); ! if ( cmpclass==null || cmpclass.equals("") ) { ! System.out.println("component \"" + cmpname + "\" in class " + getName() + " does not specify a class"); ! continue; ! } ! ClassMapping mapping = new ClassMapping(cmpe, true); ! ! ClassName classType = new ClassName(); ! classType.setFullyQualifiedName(cmpclass); ! // add an import and field for this property ! addImport(classType); ! fields.add(new Field(cmpname, classType.getName(), false)); ! components.put( mapping.getCanonicalName(), mapping ); ! } ! } ! ! public List getFields() { ! return fields; ! } ! ! public TreeSet getImports() { ! return imports; ! } ! ! public String getCanonicalName() { ! return name.getFullyQualifiedName(); ! } ! ! public String getName() { ! return name.getName(); ! } ! ! public String getProxy() { ! return proxyClass; ! } ! ! public String getPackageName() { ! return name.getPackageName(); ! } ! ! public List getSubclasses() { ! return subclasses; ! } ! ! public String getSuperClass() { ! return superClass; ! } ! ! ! // We need a minimal constructor only if it's different from ! // the full constructor or the no-arg constructor. ! // A minimal construtor is one that lets ! // you specify only the required fields. ! public boolean needsMinimalConstructor() { ! boolean generatedId = true; ! boolean missingId = true; ! int countNull = 0; ! for(Iterator it = fields.iterator(); it.hasNext(); ) { ! Field f = (Field) it.next(); ! if(f.isIdentifier()) { ! generatedId = f.isGenerated(); ! missingId = false; ! } ! else ! if(f.isNullable()) countNull++; ! } ! ! return !(countNull == 0 || ! ((countNull == (fields.size() - 1)) && generatedId) || ! ((countNull == (fields.size()) && missingId))); ! ! } ! ! private void addImport(ClassName className) { ! // if the package is java.lang or our own package don't add ! if ( !className.inJavaLang() && !className.inSamePackage(name) ) { ! imports.add( className.getFullyQualifiedName() ); ! } ! } ! ! public static Iterator getComponents() { ! return components.values().iterator(); ! } ! ! private void doCollections(Element classElement, String xmlName, String interfaceClass, String implementingClass) { ! ! ClassName interfaceClassName = new ClassName(); ! ClassName implementingClassName = new ClassName(); ! ! interfaceClassName.setFullyQualifiedName(interfaceClass); ! implementingClassName.setFullyQualifiedName(implementingClass); ! ! for (Iterator collections = classElement.getChildren(xmlName).iterator(); collections.hasNext();) { ! Element collection = (Element) collections.next(); ! ! String name = collection.getAttributeValue("role"); ! ! // add an import and field for this collection ! addImport(interfaceClassName); ! addImport(implementingClassName); ! ! fields.add(new Field(name, interfaceClassName.getName(), "new " + implementingClassName.getName() + "()", false) ); ! } ! } ! ! private void doArrays(Element classElement, String type) { ! for (Iterator arrays = classElement.getChildren(type).iterator(); arrays.hasNext();) { ! Element array = (Element) arrays.next(); ! String role = array.getAttributeValue("role"); ! String elementClass = array.getAttributeValue("element-class"); ! if (elementClass==null) { ! Element elt = array.getChild("element"); ! if (elt==null) elt = array.getChild("one-to-many"); ! if (elt==null) elt = array.getChild("many-to-many"); ! if (elt==null) elt = array.getChild("composite-element"); ! if (elt==null) { ! System.out.println("skipping collection with subcollections"); ! continue; ! } ! elementClass = elt.getAttributeValue("type"); ! if (elementClass==null) elementClass=elt.getAttributeValue("class"); ! } ! fields.add( new Field( role, getFieldType(elementClass) + "[]", false ) ); ! } ! } ! ! private String getFieldType(String hibernateType) { ! return getFieldType(hibernateType, false); ! } ! ! private String getFieldType(String hibernateType, boolean needObject) { ! // deal with hibernate binary type ! if ( hibernateType.equals("binary") ) { ! return "byte[]"; ! } ! else { ! Type basicType = TypeFactory.basic(hibernateType); ! if ( basicType!=null ) { ! ! if ( ! (basicType instanceof PrimitiveType) && ! !hibernateType.trim().equals( basicType.returnedClass().getName()) && ! !needObject ! ) { ! return ( (PrimitiveType) basicType ).primitiveClass().getName(); } else { ! return basicType.returnedClass().getName(); } ! ! } ! else { ! ClassName classType = new ClassName(); ! classType.setFullyQualifiedName(hibernateType); ! // add an import and field for this property ! addImport(classType); ! return classType.getName(); ! } ! } ! } ! ! ! } |