From 2c551be69467b1c491b6751f75344fd6cfd7411d Mon Sep 17 00:00:00 2001
From: bentmann
Date: Fri, 16 Apr 2010 22:47:30 +0000
Subject: [PATCH 01/10] [MODELLO-240] Provide support to track line/column
number of source elements
o Created feature branch
---
.../org/codehaus/modello/model/Model.java | 58 +++
.../plugin/model/ModelClassMetadata.java | 25 +
.../plugin/model/ModelMetadataPlugin.java | 8 +
.../java/AbstractJavaModelloGenerator.java | 60 ++-
.../plugin/java/JavaModelloGenerator.java | 445 +++++++++++++++---
.../plugin/java/javasource/JClass.java | 5 +
.../plugin/java/javasource/JModifiers.java | 10 +
.../plugin/xpp3/Xpp3ReaderGenerator.java | 288 +++++++++---
.../resources/META-INF/plexus/components.xml | 5 +
pom.xml | 2 +-
src/main/mdo/modello.mdo | 34 +-
11 files changed, 786 insertions(+), 154 deletions(-)
diff --git a/modello-core/src/main/java/org/codehaus/modello/model/Model.java b/modello-core/src/main/java/org/codehaus/modello/model/Model.java
index 7d6f1a54a..db10d2fcb 100644
--- a/modello-core/src/main/java/org/codehaus/modello/model/Model.java
+++ b/modello-core/src/main/java/org/codehaus/modello/model/Model.java
@@ -25,6 +25,7 @@
import org.codehaus.modello.ModelloRuntimeException;
import org.codehaus.modello.metadata.ModelMetadata;
import org.codehaus.modello.plugin.model.ModelClassMetadata;
+import org.codehaus.plexus.util.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
@@ -404,4 +405,61 @@ public void initialize()
public void validateElement()
{
}
+
+ public ModelClass getLocationTracker( Version version )
+ {
+ List modelClasses = getClasses( version );
+
+ ModelClass locationTracker = null;
+
+ for ( ModelClass modelClass : modelClasses )
+ {
+ ModelClassMetadata metadata = (ModelClassMetadata) modelClass.getMetadata( ModelClassMetadata.ID );
+
+ if ( metadata != null && StringUtils.isNotEmpty( metadata.getLocationTracker() ) )
+ {
+ if ( locationTracker == null )
+ {
+ locationTracker = modelClass;
+ }
+ else
+ {
+ throw new ModelloRuntimeException( "There are multiple location tracker classes ("
+ + locationTracker.getName() + " vs. " + modelClass.getName() + ") for this version " + version
+ + "." );
+ }
+ }
+ }
+
+ return locationTracker;
+ }
+
+ public ModelClass getSourceTracker( Version version )
+ {
+ List modelClasses = getClasses( version );
+
+ ModelClass sourceTracker = null;
+
+ for ( ModelClass modelClass : modelClasses )
+ {
+ ModelClassMetadata metadata = (ModelClassMetadata) modelClass.getMetadata( ModelClassMetadata.ID );
+
+ if ( metadata != null && StringUtils.isNotEmpty( metadata.getSourceTracker() ) )
+ {
+ if ( sourceTracker == null )
+ {
+ sourceTracker = modelClass;
+ }
+ else
+ {
+ throw new ModelloRuntimeException( "There are multiple source tracker classes ("
+ + sourceTracker.getName() + " vs. " + modelClass.getName() + ") for this version " + version
+ + "." );
+ }
+ }
+ }
+
+ return sourceTracker;
+ }
+
}
diff --git a/modello-core/src/main/java/org/codehaus/modello/plugin/model/ModelClassMetadata.java b/modello-core/src/main/java/org/codehaus/modello/plugin/model/ModelClassMetadata.java
index 3e4c2c4bb..b1532445c 100644
--- a/modello-core/src/main/java/org/codehaus/modello/plugin/model/ModelClassMetadata.java
+++ b/modello-core/src/main/java/org/codehaus/modello/plugin/model/ModelClassMetadata.java
@@ -35,6 +35,10 @@ public class ModelClassMetadata
private boolean rootElement = false;
+ private String locationTracker;
+
+ private String sourceTracker;
+
public boolean isRootElement()
{
return rootElement;
@@ -44,4 +48,25 @@ public void setRootElement( boolean rootElement )
{
this.rootElement = rootElement;
}
+
+ public String getLocationTracker()
+ {
+ return locationTracker;
+ }
+
+ public void setLocationTracker( String locationTracker )
+ {
+ this.locationTracker = locationTracker;
+ }
+
+ public String getSourceTracker()
+ {
+ return sourceTracker;
+ }
+
+ public void setSourceTracker( String sourceTracker )
+ {
+ this.sourceTracker = sourceTracker;
+ }
+
}
diff --git a/modello-core/src/main/java/org/codehaus/modello/plugin/model/ModelMetadataPlugin.java b/modello-core/src/main/java/org/codehaus/modello/plugin/model/ModelMetadataPlugin.java
index 3385b0863..8ba22a179 100644
--- a/modello-core/src/main/java/org/codehaus/modello/plugin/model/ModelMetadataPlugin.java
+++ b/modello-core/src/main/java/org/codehaus/modello/plugin/model/ModelMetadataPlugin.java
@@ -47,6 +47,10 @@ public class ModelMetadataPlugin
{
public static final String ROOT_ELEMENT = "rootElement";
+ public static final String LOCATION_TRACKER = "locationTracker";
+
+ public static final String SOURCE_TRACKER = "sourceTracker";
+
// ----------------------------------------------------------------------
// Map to Metadata
// ----------------------------------------------------------------------
@@ -62,6 +66,10 @@ public ClassMetadata getClassMetadata( ModelClass clazz, Map dat
metadata.setRootElement( getBoolean( data, ROOT_ELEMENT, false ) );
+ metadata.setLocationTracker( getString( data, LOCATION_TRACKER ) );
+
+ metadata.setSourceTracker( getString( data, SOURCE_TRACKER ) );
+
return metadata;
}
diff --git a/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/AbstractJavaModelloGenerator.java b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/AbstractJavaModelloGenerator.java
index 393577df4..913b44390 100644
--- a/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/AbstractJavaModelloGenerator.java
+++ b/modello-plugins/modello-plugin-java/src/main/java/org/codehaus/modello/plugin/java/AbstractJavaModelloGenerator.java
@@ -44,6 +44,7 @@
import org.codehaus.modello.model.ModelDefault;
import org.codehaus.modello.model.ModelField;
import org.codehaus.modello.model.ModelInterface;
+import org.codehaus.modello.model.ModelType;
import org.codehaus.modello.plugin.AbstractModelloGenerator;
import org.codehaus.modello.plugin.java.javasource.JClass;
import org.codehaus.modello.plugin.java.javasource.JComment;
@@ -53,6 +54,7 @@
import org.codehaus.modello.plugin.java.metadata.JavaClassMetadata;
import org.codehaus.modello.plugin.java.metadata.JavaFieldMetadata;
import org.codehaus.modello.plugin.java.metadata.JavaModelMetadata;
+import org.codehaus.modello.plugin.model.ModelClassMetadata;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.WriterFactory;
@@ -136,44 +138,31 @@ protected void addModelImports( JClass jClass, BaseElement baseElem )
throws ModelloException
{
String basePackageName = null;
- if ( baseElem != null )
+ if ( baseElem instanceof ModelType )
{
- if ( baseElem instanceof ModelInterface )
- {
- basePackageName =
- ( (ModelInterface) baseElem ).getPackageName( isPackageWithVersion(), getGeneratedVersion() );
- }
- else if ( baseElem instanceof ModelClass )
- {
- basePackageName =
- ( (ModelClass) baseElem ).getPackageName( isPackageWithVersion(), getGeneratedVersion() );
- }
+ basePackageName = ( (ModelType) baseElem ).getPackageName( isPackageWithVersion(), getGeneratedVersion() );
}
// import interfaces
for ( ModelInterface modelInterface : getModel().getInterfaces( getGeneratedVersion() ) )
{
- String packageName = modelInterface.getPackageName( isPackageWithVersion(), getGeneratedVersion() );
-
- if ( packageName.equals( basePackageName ) )
- {
- continue;
- }
-
- jClass.addImport( packageName + '.' + modelInterface.getName() );
+ addModelImport( jClass, modelInterface, basePackageName );
}
// import classes
for ( ModelClass modelClass : getClasses( getModel() ) )
{
- String packageName = modelClass.getPackageName( isPackageWithVersion(), getGeneratedVersion() );
+ addModelImport( jClass, modelClass, basePackageName );
+ }
+ }
- if ( packageName.equals( basePackageName ) )
- {
- continue;
- }
+ private void addModelImport( JClass jClass, ModelType modelType, String basePackageName )
+ {
+ String packageName = modelType.getPackageName( isPackageWithVersion(), getGeneratedVersion() );
- jClass.addImport( packageName + '.' + modelClass.getName() );
+ if ( !packageName.equals( basePackageName ) )
+ {
+ jClass.addImport( packageName + '.' + modelType.getName() );
}
}
@@ -276,9 +265,28 @@ protected List getClasses( Model model )
}
protected boolean isRelevant( ModelClass modelClass )
+ {
+ return isJavaEnabled( modelClass ) && !isTrackingSupport( modelClass );
+ }
+
+ protected boolean isJavaEnabled( ModelClass modelClass )
{
JavaClassMetadata javaClassMetadata = (JavaClassMetadata) modelClass.getMetadata( JavaClassMetadata.ID );
- return javaClassMetadata != null && javaClassMetadata.isEnabled();
+ return javaClassMetadata.isEnabled();
+ }
+
+ protected boolean isTrackingSupport( ModelClass modelClass )
+ {
+ ModelClassMetadata modelClassMetadata = (ModelClassMetadata) modelClass.getMetadata( ModelClassMetadata.ID );
+ if ( StringUtils.isNotEmpty( modelClassMetadata.getLocationTracker() ) )
+ {
+ return true;
+ }
+ if ( StringUtils.isNotEmpty( modelClassMetadata.getSourceTracker() ) )
+ {
+ return true;
+ }
+ return false;
}
}
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 05034de5a..e59de2781 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
@@ -47,6 +47,7 @@
import org.codehaus.modello.plugin.java.javasource.JField;
import org.codehaus.modello.plugin.java.javasource.JInterface;
import org.codehaus.modello.plugin.java.javasource.JMethod;
+import org.codehaus.modello.plugin.java.javasource.JMethodSignature;
import org.codehaus.modello.plugin.java.javasource.JParameter;
import org.codehaus.modello.plugin.java.javasource.JSourceCode;
import org.codehaus.modello.plugin.java.javasource.JSourceWriter;
@@ -89,66 +90,20 @@ private void generateJava()
{
Model objectModel = getModel();
+ ModelClass locationTrackerClass = objectModel.getLocationTracker( getGeneratedVersion() );
+ ModelClass sourceTrackerClass = objectModel.getSourceTracker( getGeneratedVersion() );
+
// ----------------------------------------------------------------------
// Generate the interfaces.
// ----------------------------------------------------------------------
for ( ModelInterface modelInterface : objectModel.getInterfaces( getGeneratedVersion() ) )
{
- String packageName = modelInterface.getPackageName( isPackageWithVersion(), getGeneratedVersion() );
-
- JSourceWriter sourceWriter = newJSourceWriter( packageName, modelInterface.getName() );
-
- JInterface jInterface = new JInterface( packageName + '.' + modelInterface.getName() );
-
- initHeader( jInterface );
-
- suppressAllWarnings( objectModel, jInterface );
-
- if ( modelInterface.getSuperInterface() != null )
- {
- // check if we need an import: if it is a generated superInterface in another package
- try
- {
- ModelInterface superInterface =
- objectModel.getInterface( modelInterface.getSuperInterface(), getGeneratedVersion() );
- String superPackageName =
- superInterface.getPackageName( isPackageWithVersion(), getGeneratedVersion() );
-
- if ( !packageName.equals( superPackageName ) )
- {
- jInterface.addImport( superPackageName + '.' + superInterface.getName() );
- }
- }
- catch ( ModelloRuntimeException mre )
- {
- // no problem if the interface does not exist in the model, it can be in the jdk
- }
-
- jInterface.addInterface( modelInterface.getSuperInterface() );
- }
-
- if ( modelInterface.getCodeSegments( getGeneratedVersion() ) != null )
- {
- for ( CodeSegment codeSegment : modelInterface.getCodeSegments( getGeneratedVersion() ) )
- {
- jInterface.addSourceCode( codeSegment.getCode() );
- }
- }
-
- if ( useJava5 && !modelInterface.getAnnotations().isEmpty() )
- {
- for ( String annotation : modelInterface.getAnnotations() )
- {
- jInterface.appendAnnotation( annotation );
- }
- }
-
- jInterface.print( sourceWriter );
-
- sourceWriter.close();
+ generateInterface( modelInterface );
}
+ String locationTrackerInterface = generateLocationTracker( objectModel, locationTrackerClass );
+
// ----------------------------------------------------------------------
// Generate the classes.
// ----------------------------------------------------------------------
@@ -182,9 +137,11 @@ private void generateJava()
jClass.getModifiers().setAbstract( javaClassMetadata.isAbstract() );
+ boolean superClassInModel = false;
if ( modelClass.getSuperClass() != null )
{
jClass.setSuperClass( modelClass.getSuperClass() );
+ superClassInModel = isClassInModel( modelClass.getSuperClass(), objectModel );
}
for ( String implementedInterface : modelClass.getInterfaces() )
@@ -245,7 +202,8 @@ private void generateJava()
jClass.addMethod( toString );
}
- JMethod[] cloneMethods = generateClone( modelClass );
+ boolean cloneLocations = !superClassInModel && modelClass != sourceTrackerClass;
+ JMethod[] cloneMethods = generateClone( modelClass, cloneLocations ? locationTrackerClass : null );
if ( cloneMethods.length > 0 )
{
jClass.addInterface( Cloneable.class.getName() );
@@ -260,15 +218,33 @@ private void generateJava()
}
}
- ModelClassMetadata metadata = (ModelClassMetadata) modelClass.getMetadata( ModelClassMetadata.ID );
+ ModelClassMetadata modelClassMetadata = (ModelClassMetadata) modelClass.getMetadata( ModelClassMetadata.ID );
+
+ if ( modelClassMetadata != null )
+ {
+ if ( modelClassMetadata.isRootElement() )
+ {
+ ModelField modelEncoding = new ModelField( modelClass, "modelEncoding" );
+ modelEncoding.setType( "String" );
+ modelEncoding.setDefaultValue( "UTF-8" );
+ modelEncoding.addMetadata( new JavaFieldMetadata() );
+ createField( jClass, modelEncoding );
+ }
+ }
+
+ if ( modelClass == locationTrackerClass )
+ {
+ jClass.addInterface( locationTrackerInterface );
+
+ generateLocationBean( jClass, modelClass, sourceTrackerClass );
- if ( ( metadata != null ) && metadata.isRootElement() )
+ generateLocationTracking( jClass, modelClass, locationTrackerClass );
+ }
+ else if ( locationTrackerClass != null && modelClass != sourceTrackerClass && !superClassInModel)
{
- ModelField modelEncoding = new ModelField( modelClass, "modelEncoding" );
- modelEncoding.setType( "String" );
- modelEncoding.setDefaultValue( "UTF-8" );
- modelEncoding.addMetadata( new JavaFieldMetadata() );
- createField( jClass, modelEncoding );
+ jClass.addInterface( locationTrackerInterface );
+
+ generateLocationTracking( jClass, modelClass, locationTrackerClass );
}
jClass.print( sourceWriter );
@@ -277,6 +253,64 @@ private void generateJava()
}
}
+ private void generateInterface( ModelInterface modelInterface )
+ throws ModelloException, IOException
+ {
+ Model objectModel = modelInterface.getModel();
+
+ String packageName = modelInterface.getPackageName( isPackageWithVersion(), getGeneratedVersion() );
+
+ JSourceWriter sourceWriter = newJSourceWriter( packageName, modelInterface.getName() );
+
+ JInterface jInterface = new JInterface( packageName + '.' + modelInterface.getName() );
+
+ initHeader( jInterface );
+
+ suppressAllWarnings( objectModel, jInterface );
+
+ if ( modelInterface.getSuperInterface() != null )
+ {
+ // check if we need an import: if it is a generated superInterface in another package
+ try
+ {
+ ModelInterface superInterface =
+ objectModel.getInterface( modelInterface.getSuperInterface(), getGeneratedVersion() );
+ String superPackageName = superInterface.getPackageName( isPackageWithVersion(), getGeneratedVersion() );
+
+ if ( !packageName.equals( superPackageName ) )
+ {
+ jInterface.addImport( superPackageName + '.' + superInterface.getName() );
+ }
+ }
+ catch ( ModelloRuntimeException mre )
+ {
+ // no problem if the interface does not exist in the model, it can be in the jdk
+ }
+
+ jInterface.addInterface( modelInterface.getSuperInterface() );
+ }
+
+ if ( modelInterface.getCodeSegments( getGeneratedVersion() ) != null )
+ {
+ for ( CodeSegment codeSegment : modelInterface.getCodeSegments( getGeneratedVersion() ) )
+ {
+ jInterface.addSourceCode( codeSegment.getCode() );
+ }
+ }
+
+ if ( useJava5 && !modelInterface.getAnnotations().isEmpty() )
+ {
+ for ( String annotation : modelInterface.getAnnotations() )
+ {
+ jInterface.appendAnnotation( annotation );
+ }
+ }
+
+ jInterface.print( sourceWriter );
+
+ sourceWriter.close();
+ }
+
private JMethod generateEquals( ModelClass modelClass )
{
JMethod equals = new JMethod( "equals", JType.BOOLEAN, null );
@@ -421,7 +455,7 @@ private JMethod generateHashCode( ModelClass modelClass )
return hashCode;
}
- private JMethod[] generateClone( ModelClass modelClass )
+ private JMethod[] generateClone( ModelClass modelClass, ModelClass locationClass )
throws ModelloException
{
String cloneModeClass = getCloneMode( modelClass );
@@ -555,6 +589,19 @@ else if ( isMap( modelField.getType() ) )
}
}
+ if ( locationClass != null )
+ {
+ String locationField =
+ ( (ModelClassMetadata) locationClass.getMetadata( ModelClassMetadata.ID ) ).getLocationTracker();
+ sc.add( "if ( copy." + locationField + " != null )" );
+ sc.add( "{" );
+ sc.indent();
+ sc.add( "copy." + locationField + " = new java.util.LinkedHashMap" + "( copy." + locationField + " );" );
+ sc.unindent();
+ sc.add( "}" );
+ sc.add( "" );
+ }
+
String cloneHook = getCloneHook( modelClass );
if ( StringUtils.isNotEmpty( cloneHook ) && !"false".equalsIgnoreCase( cloneHook ) )
@@ -652,6 +699,282 @@ private String getCloneHook( ModelClass modelClass )
return javaClassMetadata.getCloneHook();
}
+ private String generateLocationTracker( Model objectModel, ModelClass locationClass )
+ throws ModelloException, IOException
+ {
+ if ( locationClass == null )
+ {
+ return null;
+ }
+
+ String locationField =
+ ( (ModelClassMetadata) locationClass.getMetadata( ModelClassMetadata.ID ) ).getLocationTracker();
+
+ String propertyName = capitalise( singular( locationField ) );
+
+ String interfaceName = propertyName + "Tracker";
+
+ String packageName = locationClass.getPackageName( isPackageWithVersion(), getGeneratedVersion() );
+
+ JSourceWriter sourceWriter = newJSourceWriter( packageName, interfaceName );
+
+ JInterface jInterface = new JInterface( packageName + '.' + interfaceName );
+
+ initHeader( jInterface );
+
+ suppressAllWarnings( objectModel, jInterface );
+
+ JMethodSignature jMethod = new JMethodSignature( "get" + propertyName, new JType( locationClass.getName() ) );
+ jMethod.addParameter( new JParameter( new JType( "Object" ), "field" ) );
+ jInterface.addMethod( jMethod );
+
+ jMethod = new JMethodSignature( "set" + propertyName, null );
+ jMethod.addParameter( new JParameter( new JType( "Object" ), "field" ) );
+ jMethod.addParameter( new JParameter( new JType( locationClass.getName() ), singular( locationField ) ) );
+ jInterface.addMethod( jMethod );
+
+ jInterface.print( sourceWriter );
+
+ sourceWriter.close();
+
+ return jInterface.getName();
+ }
+
+ private void generateLocationTracking( JClass jClass, ModelClass modelClass, ModelClass locationClass )
+ throws ModelloException
+ {
+ if ( locationClass == null )
+ {
+ return;
+ }
+
+ String superClass = modelClass.getSuperClass();
+ if ( StringUtils.isNotEmpty( superClass ) && isClassInModel( superClass, getModel() ) )
+ {
+ return;
+ }
+
+ ModelClassMetadata metadata = (ModelClassMetadata) locationClass.getMetadata( ModelClassMetadata.ID );
+ String locationField = metadata.getLocationTracker();
+
+ String fieldType = "java.util.Map" + ( useJava5 ? "
-
-
+