diff --git a/modello-core/src/main/java/org/codehaus/modello/core/io/ModelReader.java b/modello-core/src/main/java/org/codehaus/modello/core/io/ModelReader.java index bafb3ab83..985044a96 100644 --- a/modello-core/src/main/java/org/codehaus/modello/core/io/ModelReader.java +++ b/modello-core/src/main/java/org/codehaus/modello/core/io/ModelReader.java @@ -246,6 +246,18 @@ else if ( "codeSegments".equals( parser.getName() ) ) { parseCodeSegment( modelInterface, parser ); } + else if ( "typeParameters".equals( parser.getName() ) ) + { + List typeParametersList = new ArrayList(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "typeParameter".equals( parser.getName() ) ) + { + typeParametersList.add( parser.nextText() ); + } + } + modelInterface.setTypeParameters( typeParametersList ); + } else { parser.nextText(); @@ -298,6 +310,18 @@ else if ( "codeSegments".equals( parser.getName() ) ) { parseCodeSegment( modelClass, parser ); } + else if ( "typeParameters".equals( parser.getName() ) ) + { + List typeParametersList = new ArrayList(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "typeParameter".equals( parser.getName() ) ) + { + typeParametersList.add( parser.nextText() ); + } + } + modelClass.setTypeParameters( typeParametersList ); + } else { parser.nextText(); diff --git a/modello-core/src/main/java/org/codehaus/modello/model/ModelClass.java b/modello-core/src/main/java/org/codehaus/modello/model/ModelClass.java index 163c8be01..17f5b4369 100644 --- a/modello-core/src/main/java/org/codehaus/modello/model/ModelClass.java +++ b/modello-core/src/main/java/org/codehaus/modello/model/ModelClass.java @@ -43,6 +43,8 @@ public class ModelClass private boolean isInternalSuperClass; private List interfaces; + + private List typeParameters; private List fields; @@ -67,7 +69,7 @@ public void setSuperClass( String superClass ) { this.superClass = superClass; } - + // ---------------------------------------------------------------------- // Interfaces // ---------------------------------------------------------------------- @@ -96,6 +98,26 @@ public void addInterface( String modelInterface ) getInterfaces().add( modelInterface ); } + + // ---------------------------------------------------------------------- + // TypeVariables + // ---------------------------------------------------------------------- + + public List getTypeParameters() + { + if ( typeParameters == null ) + { + return new ArrayList(); + } + return typeParameters; + } + + public void setTypeParameters( List typeParameters ) + { + this.typeParameters = typeParameters; + } + + // ---------------------------------------------------------------------- // Field diff --git a/modello-core/src/main/java/org/codehaus/modello/model/ModelField.java b/modello-core/src/main/java/org/codehaus/modello/model/ModelField.java index abb49707d..fcc515587 100644 --- a/modello-core/src/main/java/org/codehaus/modello/model/ModelField.java +++ b/modello-core/src/main/java/org/codehaus/modello/model/ModelField.java @@ -210,6 +210,21 @@ else if ( "char".equals( type ) ) } } + public boolean isTypeVariable() + { + String type = getType(); + for ( String t : modelClass.getTypeParameters() ) + { + String name = t.split( " " )[0]; + if ( type.equals( name ) ) + { + return true; + } + } + return false; + } + + public void validateElement() throws ModelValidationException { @@ -219,7 +234,7 @@ public void validateElement() // TODO: these definitions are duplicated throughout. Defined centrally, and loop through in the various uses - if ( !isPrimitive() && !isPrimitiveArray() ) + if ( !isPrimitive() && !isPrimitiveArray() && !isTypeVariable() ) { throw new ModelValidationException( "Field '" + getName() + "': Illegal type: '" + type + "'." ); } diff --git a/modello-core/src/main/java/org/codehaus/modello/model/ModelInterface.java b/modello-core/src/main/java/org/codehaus/modello/model/ModelInterface.java index 34d3a6a60..20b5c5b03 100644 --- a/modello-core/src/main/java/org/codehaus/modello/model/ModelInterface.java +++ b/modello-core/src/main/java/org/codehaus/modello/model/ModelInterface.java @@ -34,6 +34,8 @@ public class ModelInterface extends ModelType { private String superInterface; + + private List typeParameters; public ModelInterface() { @@ -54,6 +56,24 @@ public String getSuperInterface() { return superInterface; } + + // ---------------------------------------------------------------------- + // TypeVariables + // ---------------------------------------------------------------------- + + public List getTypeParameters() + { + if ( typeParameters == null ) + { + return new ArrayList(); + } + return typeParameters; + } + + public void setTypeParameters( List typeParameters ) + { + this.typeParameters = typeParameters; + } /** * {@inheritDoc} diff --git a/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/JavaModelloGenerator.java b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/JavaModelloGenerator.java index 7cadd74a2..b9d967c68 100644 --- a/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/JavaModelloGenerator.java +++ b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/JavaModelloGenerator.java @@ -55,6 +55,7 @@ import org.codehaus.modello.plugin.java.javasource.JSourceCode; import org.codehaus.modello.plugin.java.javasource.JSourceWriter; import org.codehaus.modello.plugin.java.javasource.JType; +import org.codehaus.modello.plugin.java.javasource.JTypeVariable; import org.codehaus.modello.plugin.java.metadata.JavaAssociationMetadata; import org.codehaus.modello.plugin.java.metadata.JavaClassMetadata; import org.codehaus.modello.plugin.java.metadata.JavaFieldMetadata; @@ -126,6 +127,8 @@ private void generateJava() JClass jClass = new JClass( packageName + '.' + modelClass.getName() ); + addTypeParameters( jClass, modelClass ); + initHeader( jClass ); suppressAllWarnings( objectModel, jClass ); @@ -294,6 +297,22 @@ else if ( locationTrackerClass != null && modelClass != sourceTrackerClass && !s } } + private void addTypeParameters( JClass jClass, ModelClass modelClass ) + { + for ( String value : modelClass.getTypeParameters() ) + { + jClass.addTypeParameter( new JTypeVariable( value ) ); + } + } + + private void addTypeParameters( JInterface jInterface, ModelInterface modelInterface) + { + for ( String value : modelInterface.getTypeParameters() ) + { + jInterface.addTypeParameter( new JTypeVariable( value ) ); + } + } + private void generateInterface( ModelInterface modelInterface ) throws ModelloException, IOException { @@ -307,6 +326,8 @@ private void generateInterface( ModelInterface modelInterface ) initHeader( jInterface ); + addTypeParameters( jInterface, modelInterface ); + suppressAllWarnings( objectModel, jInterface ); if ( modelInterface.getSuperInterface() != null ) diff --git a/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JClass.java b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JClass.java index f14068d2b..133d276e7 100644 --- a/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JClass.java +++ b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JClass.java @@ -75,6 +75,7 @@ */ import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.List; @@ -93,6 +94,7 @@ public class JClass extends JStructure { + private List _typeParameters; /** * The list of constructors for this JClass @@ -134,10 +136,11 @@ public JClass( String name ) throws IllegalArgumentException { super( name ); - _constructors = new ArrayList(); + _typeParameters = new ArrayList<>(); + _constructors = new ArrayList<>(); _fields = new LinkedHashMap<>(); - _methods = new ArrayList(); - _innerClasses = new ArrayList(); + _methods = new ArrayList<>(); + _innerClasses = new ArrayList<>(); //-- initialize default Java doc getJDocComment().appendComment( "Class " + getLocalName() + "." ); @@ -200,6 +203,8 @@ public void addField( JField jField ) _fields.put( name, jField ); } //-- addField + + /** * Adds the given JMember to this JClass @@ -513,6 +518,11 @@ public String getSuperClass() { return _superClass; } //-- getSuperClass + + public void addTypeParameter( JTypeVariable typeParameter ) + { + this._typeParameters.add( typeParameter ); + } /** * Prints the source code for this JClass to the given JSourceWriter @@ -596,31 +606,45 @@ public void print( JSourceWriter jsw, boolean classOnly ) JModifiers modifiers = getModifiers(); if ( modifiers.isPrivate() ) { - buffer.append( "private " ); + jsw.write( "private " ); } else if ( modifiers.isPublic() ) { - buffer.append( "public " ); + jsw.write( "public " ); } if ( modifiers.isAbstract() ) { - buffer.append( "abstract " ); + jsw.write( "abstract " ); } if ( this instanceof JInnerClass && modifiers.isStatic() ) { - buffer.append( "static " ); + jsw.write( "static " ); } if ( modifiers.isFinal() ) { - buffer.append( "final " ); + jsw.write( "final " ); } - buffer.append( "class " ); - buffer.append( getLocalName() ); - jsw.writeln( buffer.toString() ); + jsw.write( "class " ); + jsw.write( getLocalName() ); + if ( !_typeParameters.isEmpty() ) + { + jsw.write( '<' ); + Enumeration typeParamEnum = Collections.enumeration( _typeParameters ); + typeParamEnum.nextElement().print( jsw ); + while ( typeParamEnum.hasMoreElements() ) + { + jsw.write( ", " ); + typeParamEnum.nextElement().print( jsw ); + } + jsw.write( '>' ); + } + + jsw.writeln(); + buffer.setLength( 0 ); jsw.indent(); diff --git a/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JInterface.java b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JInterface.java index 28b70693d..605fc197a 100644 --- a/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JInterface.java +++ b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JInterface.java @@ -68,6 +68,7 @@ */ import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.List; @@ -85,7 +86,7 @@ **/ public final class JInterface extends JStructure { - + private List _typeParameters; /** * The fields for this JInterface @@ -109,7 +110,8 @@ public JInterface( String name ) throws IllegalArgumentException { super( name ); - methods = new ArrayList(); + methods = new ArrayList<>(); + _typeParameters = new ArrayList<>(); //-- initialize default Java doc getJDocComment().appendComment( "Interface " + getLocalName() + "." ); @@ -335,7 +337,11 @@ public JMethodSignature getMethod( int index ) return methods.get( index ); } //-- getMethod - + public void addTypeParameter( JTypeVariable typeParameter ) + { + this._typeParameters.add( typeParameter ); + } + /** * Prints the source code for this JInterface to the given JSourceWriter * @@ -386,22 +392,34 @@ public void print( JSourceWriter jsw, boolean classOnly ) JModifiers modifiers = getModifiers(); if ( modifiers.isPrivate() ) { - buffer.append( "private " ); + jsw.write( "private " ); } else if ( modifiers.isPublic() ) { - buffer.append( "public " ); + jsw.write( "public " ); } if ( modifiers.isAbstract() ) { - buffer.append( "abstract " ); + jsw.write( "abstract " ); } - buffer.append( "interface " ); - buffer.append( getLocalName() ); + jsw.write( "interface " ); + jsw.write( getLocalName() ); jsw.writeln( buffer.toString() ); - buffer.setLength( 0 ); + if ( !_typeParameters.isEmpty() ) + { + jsw.write( '<' ); + Enumeration typeParamEnum = Collections.enumeration( _typeParameters ); + typeParamEnum.nextElement().print( jsw ); + while ( typeParamEnum.hasMoreElements() ) + { + jsw.write( ", " ); + typeParamEnum.nextElement().print( jsw ); + } + jsw.write( '>' ); + } + jsw.indent(); if ( getInterfaceCount() > 0 ) diff --git a/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JTypeVariable.java b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JTypeVariable.java new file mode 100644 index 000000000..c74756c03 --- /dev/null +++ b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/javasource/JTypeVariable.java @@ -0,0 +1,24 @@ +package org.codehaus.modello.plugin.java.javasource; + +public class JTypeVariable +{ + private final String value; + + private final String name; + + public JTypeVariable( String value ) + { + this.value = value; + this.name = value.split( " " )[0]; + } + + public String getName() + { + return name; + } + + public void print( JSourceWriter jsw ) + { + jsw.write( value ); + } +} diff --git a/modello-plugins/modello-plugin-java/src/test/java/org/codehaus/modello/plugin/java/TypeVariablesJavaGeneratorTest.java b/modello-plugins/modello-plugin-java/src/test/java/org/codehaus/modello/plugin/java/TypeVariablesJavaGeneratorTest.java new file mode 100644 index 000000000..898890c54 --- /dev/null +++ b/modello-plugins/modello-plugin-java/src/test/java/org/codehaus/modello/plugin/java/TypeVariablesJavaGeneratorTest.java @@ -0,0 +1,62 @@ +package org.codehaus.modello.plugin.java; + +/* + * Copyright (c) 2004, Codehaus.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import java.util.Properties; + +import org.codehaus.modello.AbstractModelloJavaGeneratorTest; +import org.codehaus.modello.core.ModelloCore; +import org.codehaus.modello.model.Model; + +/** + * @version $Id: TmpJavaGeneratorTest.java 1125 2009-01-10 20:29:32Z hboutemy $ + */ +public class TypeVariablesJavaGeneratorTest + extends AbstractModelloJavaGeneratorTest +{ + public TypeVariablesJavaGeneratorTest() + { + super( "typevariables" ); + } + + public void testJavaGeneratorWithAnnotations() + throws Throwable + { + if ( skipJava5FeatureTest() ) + { + return; + } + + ModelloCore modello = (ModelloCore) lookup( ModelloCore.ROLE ); + + Model model = modello.loadModel( getXmlResourceReader( "/models/typevariables.mdo" ) ); + + Properties parameters = getModelloParameters( "1.0.0", true ); + + modello.generate( model, "java", parameters ); + + compileGeneratedSources( true ); + +// verifyCompiledGeneratedSources( "AnnotationsVerifier" ); + } +} \ No newline at end of file diff --git a/modello-plugins/modello-plugin-java/src/test/resources/models/typevariables.mdo b/modello-plugins/modello-plugin-java/src/test/resources/models/typevariables.mdo new file mode 100644 index 000000000..46d9d20c2 --- /dev/null +++ b/modello-plugins/modello-plugin-java/src/test/resources/models/typevariables.mdo @@ -0,0 +1,59 @@ + + + 1.0.0 + untitledModel + + + + Box + 1.0.0 + + T + + + + t + T + + + + + OrderedPair + + K + V + + + Pair<K, V> + + + + key + K + + + value + V + + + + + + + + Pair + + K + V + + + + + K getKey(); + V getValue(); + + + + + +