Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkmoore2011-01-31 16:48:09 -0500
committerkmoore2011-01-31 16:48:09 -0500
commitd573fb171a36de122ae964b913a1a8b6e1c95e7e (patch)
tree33bf57a8bd9f893f51498b332504d19e67e31ee1 /common/plugins
parent750f1789146ac827adb3667026b96a794fdcb875 (diff)
downloadwebtools.dali-d573fb171a36de122ae964b913a1a8b6e1c95e7e.tar.gz
webtools.dali-d573fb171a36de122ae964b913a1a8b6e1c95e7e.tar.xz
webtools.dali-d573fb171a36de122ae964b913a1a8b6e1c95e7e.zip
Phase 1 - refactoring to org.eclipse.jpt.common.*
Diffstat (limited to 'common/plugins')
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/.classpath13
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/.project28
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/.settings/org.eclipse.jdt.core.prefs8
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/META-INF/MANIFEST.MF63
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/about.html34
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/build.properties21
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/plugin.properties31
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/plugin.xml150
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/property_files/jpt_common_core.properties22
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/schema/libraryValidators.exsd154
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/schema/resourceLocators.exsd191
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/IResourcePart.java34
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptCommonCorePlugin.java167
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceModel.java44
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceModelListener.java34
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceType.java99
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/JptCommonCoreMessages.java44
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/ResourceAdapterFactory.java49
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/XPointUtil.java143
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/gen/AbstractJptGenerator.java369
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/JptOsgiBundlesLibraryProviderInstallOperationConfig.java45
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/JptUserLibraryProviderInstallOperationConfig.java45
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/LibraryProviderPropertyTester.java41
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libval/LibraryValidatorConfig.java97
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libval/LibraryValidatorManager.java149
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/operations/AbstractJptFileCreationDataModelProvider.java137
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/operations/JptFileCreationDataModelProperties.java33
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ModuleResourceLocator.java79
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/PluginResourceLocator.java93
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ResourceLocatorConfig.java168
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ResourceLocatorManager.java167
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/SimpleJavaResourceLocator.java152
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/WebModuleResourceLocator.java54
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/CallbackJobSynchronizer.java154
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/JobCommand.java96
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/JobSynchronizer.java198
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/PlatformTools.java96
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/SimpleSchedulingRule.java38
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/SimpleTextRange.java41
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ASTNodeTextRange.java39
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ASTTools.java250
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractAnnotationAdapter.java165
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractDeclarationAnnotationAdapter.java153
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractExpressionConverter.java82
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractJDTType.java198
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractNestedDeclarationAnnotationAdapter.java403
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AnnotatedElementAnnotationElementAdapter.java99
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AnnotationStringArrayExpressionConverter.java107
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/BooleanExpressionConverter.java51
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/CharacterStringExpressionConverter.java53
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/CombinationIndexedDeclarationAnnotationAdapter.java500
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ConversionDeclarationAnnotationElementAdapter.java154
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/DefaultAnnotationEditFormatter.java219
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ElementAnnotationAdapter.java27
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ElementIndexedAnnotationAdapter.java74
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/EnumArrayDeclarationAnnotationElementAdapter.java150
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/EnumDeclarationAnnotationElementAdapter.java119
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ExpressionDeclarationAnnotationElementAdapter.java327
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/GenericVisitor.java791
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTAnnotatedElement.java201
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTEnum.java132
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTEnumConstant.java121
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTFieldAttribute.java216
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTMember.java90
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTMethodAttribute.java263
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTModifiedDeclaration.java584
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTPackage.java65
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTTools.java236
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTType.java207
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JPTTools.java283
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NameStringExpressionConverter.java57
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NestedDeclarationAnnotationAdapter.java90
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NestedIndexedDeclarationAnnotationAdapter.java325
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullAnnotationEditFormatter.java42
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullDeclarationAnnotationAdapter.java82
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullDeclarationAnnotationElementAdapter.java60
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullExpressionConverter.java54
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NumberIntegerExpressionConverter.java51
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/PrimitiveTypeStringExpressionConverter.java61
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ShortCircuitAnnotationElementAdapter.java104
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ShortCircuitArrayAnnotationElementAdapter.java43
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/SimpleDeclarationAnnotationAdapter.java62
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/SimpleTypeStringExpressionConverter.java63
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/StringArrayExpressionConverter.java104
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/StringExpressionConverter.java52
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/TypeStringExpressionConverter.java55
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/BooleanTranslator.java36
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/EmptyTagBooleanTranslator.java53
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/EnumeratedValueTranslator.java45
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/SimpleRootTranslator.java92
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/SimpleTranslator.java135
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/libprov/JptLibraryProviderInstallOperationConfig.java31
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/libval/LibraryValidator.java31
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/resource/ResourceLocator.java50
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/AbstractTextRange.java71
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/BodySourceWriter.java303
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/TextRange.java119
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AbstractType.java38
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotatedElement.java82
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotatedPackage.java40
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationAdapter.java63
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationEditFormatter.java34
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationElementAdapter.java68
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Attribute.java46
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/DeclarationAnnotationAdapter.java72
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/DeclarationAnnotationElementAdapter.java63
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Enum.java39
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/EnumConstant.java41
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/ExpressionConverter.java44
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/FieldAttribute.java39
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/IndexedAnnotationAdapter.java37
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/IndexedDeclarationAnnotationAdapter.java37
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Member.java39
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/MethodAttribute.java45
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/ModifiedDeclaration.java105
-rw-r--r--common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Type.java56
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/.classpath13
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/.project28
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/.settings/org.eclipse.jdt.core.prefs8
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/META-INF/MANIFEST.MF36
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/about.html34
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/build.properties19
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/plugin.properties23
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/property_files/jpt_common_ui.properties28
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/JptCommonUiPlugin.java65
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/WidgetFactory.java240
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/JptCommonUiMessages.java53
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/Tracing.java161
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/AbstractItemLabelProvider.java224
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/AbstractTreeItemContentProvider.java204
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/ArchiveFileViewerFilter.java71
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/DelegatingTreeContentAndLabelProvider.java58
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/ImageImageDescriptor.java47
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/NullLabelProvider.java60
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/NullTreeContentProvider.java60
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/StructuredContentProviderAdapter.java265
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTCollectionChangeListenerWrapper.java151
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTListChangeListenerWrapper.java201
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTPropertyChangeListenerWrapper.java82
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTStateChangeListenerWrapper.java79
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/listeners/SWTTreeChangeListenerWrapper.java151
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/properties/JptProjectPropertiesPage.java432
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/swt/AbstractComboModelAdapter.java699
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/swt/ColumnAdapter.java55
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/swt/ComboModelAdapter.java210
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/swt/DateTimeModelAdapter.java352
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/swt/SpinnerModelAdapter.java214
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/swt/TableItemModelAdapter.java209
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/swt/TableModelAdapter.java746
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/swt/TriStateCheckBoxModelAdapter.java188
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/ControlAligner.java913
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/ControlSwitcher.java130
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledButton.java64
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControl.java37
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledControlUpdater.java130
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/LabeledLabel.java64
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/PaneEnabler.java175
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/PaneVisibilityEnabler.java173
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/SWTUtil.java447
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/StateController.java320
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/util/TableLayoutComposite.java207
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/AsynchronousUiCommandExecutor.java49
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/SynchronousUiCommandExecutor.java49
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/AbstractListWidgetAdapter.java42
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/BooleanButtonModelBinding.java190
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/BooleanStateController.java188
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/DropDownListBoxSelectionBinding.java283
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/ListBoxSelectionBinding.java305
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/ListWidgetModelBinding.java428
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/MultiControlBooleanStateController.java157
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/SWTComboAdapter.java67
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/SWTListAdapter.java49
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/SWTTools.java392
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/SimpleBooleanStateController.java68
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/utility/swt/TextFieldModelBinding.java196
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/AddRemoveListPane.java554
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/AddRemovePane.java923
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/AddRemoveTablePane.java314
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/ChooserPane.java167
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/ClassChooserComboPane.java92
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/ClassChooserPane.java368
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/ComboPane.java289
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/DefaultWidgetFactory.java260
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Dialog.java350
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/DialogPane.java109
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/EnumComboViewer.java369
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/EnumDialogComboViewer.java77
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/EnumFormComboViewer.java77
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/FileChooserComboPane.java105
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/FileChooserPane.java167
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/FolderChooserComboPane.java106
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/FolderChooserPane.java140
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/FormWidgetFactory.java338
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/IntegerCombo.java188
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/NewNameDialog.java166
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/NewNameDialogBuilder.java179
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/NewNameStateObject.java146
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/NullPostExecution.java56
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/PackageChooserPane.java237
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Pane.java3722
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/PostExecution.java31
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/PropertySheetWidgetFactory.java61
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/TriStateCheckBox.java287
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/ValidatingDialog.java233
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/jface/DelegatingContentAndLabelProvider.java207
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/jface/ItemContentProvider.java36
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/jface/ItemContentProviderFactory.java26
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/jface/ItemLabelProvider.java47
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/jface/ItemLabelProviderFactory.java26
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/jface/TreeItemContentProvider.java40
-rw-r--r--common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/jface/TreeItemContentProviderFactory.java26
211 files changed, 34307 insertions, 0 deletions
diff --git a/common/plugins/org.eclipse.jpt.common.core/.classpath b/common/plugins/org.eclipse.jpt.common.core/.classpath
new file mode 100644
index 0000000000..c91454c302
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/.classpath
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+ <accessrules>
+ <accessrule kind="accessible" pattern="org/eclipse/jst/**"/>
+ <accessrule kind="accessible" pattern="org/eclipse/wst/**"/>
+ </accessrules>
+ </classpathentry>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="property_files"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/common/plugins/org.eclipse.jpt.common.core/.project b/common/plugins/org.eclipse.jpt.common.core/.project
new file mode 100644
index 0000000000..5513a1552d
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.jpt.common.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/common/plugins/org.eclipse.jpt.common.core/.settings/org.eclipse.jdt.core.prefs b/common/plugins/org.eclipse.jpt.common.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..4743c715ac
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Fri Jan 21 15:45:07 EST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/common/plugins/org.eclipse.jpt.common.core/META-INF/MANIFEST.MF b/common/plugins/org.eclipse.jpt.common.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..e9fd34312e
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/META-INF/MANIFEST.MF
@@ -0,0 +1,63 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-SymbolicName: org.eclipse.jpt.common.core;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.jpt.common.core.JptCommonCorePlugin
+Bundle-ActivationPolicy: lazy
+Bundle-ClassPath: .
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Require-Bundle: org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.core.filebuffers;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.debug.core;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.emf.ecore.xmi;bundle-version="[2.4.0,3.0.0)",
+ org.eclipse.jdt.core;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.jdt.launching;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.jpt.utility;bundle-version="[1.2.0,2.0.0)",
+ org.eclipse.jst.common.project.facet.core;bundle-version="[1.3.100,2.0.0)",
+ org.eclipse.jst.j2ee;bundle-version="[1.1.200,2.0.0)",
+ org.eclipse.pde.core;bundle-version="[3.6.0,4.0.0)";resolution:=optional,
+ org.eclipse.text;bundle-version="[3.5.100,4.0.0)",
+ org.eclipse.wst.common.emf;bundle-version="[1.1.200,2.0.0)",
+ org.eclipse.wst.common.frameworks;bundle-version="[1.1.200,2.0.0)",
+ org.eclipse.wst.common.project.facet.core;bundle-version="[1.3.0,2.0.0)",
+ org.eclipse.wst.validation;bundle-version="[1.2.0,2.0.0)"
+Export-Package: org.eclipse.jpt.common.core,
+ org.eclipse.jpt.common.core.internal;
+ x-friends:="org.eclipse.jpt.core,
+ org.eclipse.jpt.jaxb.core",
+ org.eclipse.jpt.common.core.internal.gen;
+ x-friends:="org.eclipse.jpt.core,
+ org.eclipse.jpt.jaxb.core",
+ org.eclipse.jpt.common.core.internal.libprov;
+ x-friends:="org.eclipse.jpt.core,
+ org.eclipse.jpt.jaxb.core",
+ org.eclipse.jpt.common.core.internal.libval;
+ x-friends:="org.eclipse.jpt.core,
+ org.eclipse.jpt.jaxb.core",
+ org.eclipse.jpt.common.core.internal.operations;
+ x-friends:="org.eclipse.jpt.core,
+ org.eclipse.jpt.jaxb.core",
+ org.eclipse.jpt.common.core.internal.resource;
+ x-friends:="org.eclipse.jpt.core,
+ org.eclipse.jpt.jaxb.core",
+ org.eclipse.jpt.common.core.internal.utility;
+ x-friends:="org.eclipse.jpt.core,
+ org.eclipse.jpt.jaxb.core",
+ org.eclipse.jpt.common.core.internal.utility.jdt;
+ x-friends:="org.eclipse.jpt.common.ui,
+ org.eclipse.jpt.core,
+ org.eclipse.jpt.jaxb.core",
+ org.eclipse.jpt.common.core.internal.utility.translators;
+ x-friends:="org.eclipse.jpt.core,
+ org.eclipse.jpt.jaxb.core",
+ org.eclipse.jpt.common.core.libprov,
+ org.eclipse.jpt.common.core.libval,
+ org.eclipse.jpt.common.core.resource,
+ org.eclipse.jpt.common.core.utility,
+ org.eclipse.jpt.common.core.utility.jdt
+Import-Package: com.ibm.icu.text;version="4.0.1"
diff --git a/common/plugins/org.eclipse.jpt.common.core/about.html b/common/plugins/org.eclipse.jpt.common.core/about.html
new file mode 100644
index 0000000000..be534ba44f
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/about.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+
+<BODY lang="EN-US">
+
+<H3>About This Content</H3>
+
+<P>May 02, 2008</P>
+
+<H3>License</H3>
+
+<P>The Eclipse Foundation makes available all content in this plug-in
+("Content"). Unless otherwise indicated below, the Content is provided to you
+under the terms and conditions of the Eclipse Public License Version 1.0
+("EPL"). A copy of the EPL is available at
+<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>.
+For purposes of the EPL, "Program" will mean the Content.</P>
+
+<P>If you did not receive this Content directly from the Eclipse Foundation, the
+Content is being redistributed by another party ("Redistributor") and different
+terms and conditions may apply to your use of any object code in the Content.
+Check the Redistributor's license that was provided with the Content. If no such
+license exists, contact the Redistributor. Unless otherwise indicated below, the
+terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at
+<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
+
+</BODY>
+</HTML>
diff --git a/common/plugins/org.eclipse.jpt.common.core/build.properties b/common/plugins/org.eclipse.jpt.common.core/build.properties
new file mode 100644
index 0000000000..750874fe97
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/build.properties
@@ -0,0 +1,21 @@
+################################################################################
+# Copyright (c) 2011 Oracle. All rights reserved.
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v1.0, which accompanies this distribution
+# and is available at http://www.eclipse.org/legal/epl-v10.html.
+#
+# Contributors:
+# Oracle - initial API and implementation
+################################################################################
+javacSource=1.5
+javacTarget=1.5
+source.. = src/,\
+ property_files/
+output.. = bin/
+bin.includes = .,\
+ META-INF/,\
+ about.html,\
+ plugin.xml,\
+ plugin.properties
+jars.compile.order = .
+src.includes = schema/
diff --git a/common/plugins/org.eclipse.jpt.common.core/plugin.properties b/common/plugins/org.eclipse.jpt.common.core/plugin.properties
new file mode 100644
index 0000000000..a38a4a43c3
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/plugin.properties
@@ -0,0 +1,31 @@
+###############################################################################
+# Copyright (c) 2011 Oracle. All rights reserved.
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v1.0, which accompanies this distribution
+# and is available at http://www.eclipse.org/legal/epl-v10.html.
+#
+# Contributors:
+# Oracle - initial API and implementation
+###############################################################################
+# ====================================================================
+# To code developer:
+# Do NOT change the properties between this line and the
+# "%%% END OF TRANSLATED PROPERTIES %%%" line.
+# Make a new property name, append to the end of the file and change
+# the code to use the new property.
+# ====================================================================
+
+# ====================================================================
+# %%% END OF TRANSLATED PROPERTIES %%%
+# ====================================================================
+
+pluginName = Dali Java Persistence Tools - Common Core
+providerName = Eclipse Web Tools Platform
+
+LIBRARY_VALIDATORS=Library Validators
+RESOURCE_LOCATORS=Resource Locators
+
+JAR_CONTENT = JAR Content
+JAVA_PACKAGE_INFO_CONTENT = package-info.java
+
+NO_OP_LIBRARY_PROVIDER_WARNING = Library configuration is disabled. The user may need to configure further classpath changes later.
diff --git a/common/plugins/org.eclipse.jpt.common.core/plugin.xml b/common/plugins/org.eclipse.jpt.common.core/plugin.xml
new file mode 100644
index 0000000000..d819517442
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/plugin.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<!--
+ Copyright (c) 2011 Oracle. All rights reserved.
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0, which accompanies this distribution
+ and is available at http://www.eclipse.org/legal/epl-v10.html.
+
+ Contributors:
+ Oracle - initial API and implementation
+ -->
+
+<plugin>
+
+ <!-- ***** extension points ***** -->
+
+ <extension-point
+ id="org.eclipse.jpt.common.core.libraryValidators"
+ name="%LIBRARY_VALIDATORS"
+ schema="schema/libraryValidators.exsd"/>
+
+
+ <extension-point
+ id="org.eclipse.jpt.common.core.resourceLocators"
+ name="%RESOURCE_LOCATORS"
+ schema="schema/resourceLocators.exsd"/>
+
+
+ <!-- ***** Eclipse core extensions ***** -->
+
+ <extension
+ point="org.eclipse.core.contenttype.contentTypes">
+
+ <!-- JAR content type -->
+ <content-type
+ id="org.eclipse.jpt.common.core.content.jar"
+ name="%JAR_CONTENT"
+ file-extensions="jar, zip">
+ <describer
+ class="org.eclipse.core.runtime.content.BinarySignatureDescriber">
+ <parameter name="signature" value="50 4B 03 04"/>
+ </describer>
+ </content-type>
+
+ <!-- package-info.java content type (for package annotations) -->
+ <content-type
+ id="org.eclipse.jpt.common.core.content.javaPackageInfo"
+ name="%JAVA_PACKAGE_INFO_CONTENT"
+ base-type="org.eclipse.jdt.core.javaSource"
+ file-names="package-info.java"
+ priority="normal">
+ </content-type>
+
+ </extension>
+ <extension
+ point="org.eclipse.core.runtime.adapters">
+
+ <factory
+ class="org.eclipse.jpt.common.core.internal.ResourceAdapterFactory"
+ adaptableType="org.eclipse.core.resources.IResource">
+ <adapter type="org.eclipse.jpt.common.core.IResourcePart"/>
+ </factory>
+
+ </extension>
+ <extension
+ point="org.eclipse.core.expressions.propertyTesters">
+
+ <propertyTester
+ id="org.eclipse.jpt.common.core.propertyTester.libraryProvider"
+ type="org.eclipse.jst.common.project.facet.core.libprov.ILibraryProvider"
+ namespace="org.eclipse.jpt.common.core"
+ properties="id, extendsId"
+ class="org.eclipse.jpt.common.core.internal.libprov.LibraryProviderPropertyTester"/>
+
+ </extension>
+ <extension
+ point="org.eclipse.jpt.common.core.resourceLocators">
+
+ <resourceLocator
+ id="simpleJavaResourceLocator"
+ class="org.eclipse.jpt.common.core.internal.resource.SimpleJavaResourceLocator"
+ priority="lowest">
+ <enablement>
+ <with variable="project">
+ <test
+ property="org.eclipse.wst.common.project.facet.core.projectFacet"
+ value="java"
+ forcePluginActivation="true"/>
+ </with>
+ </enablement>
+ </resourceLocator>
+
+ <resourceLocator
+ id="moduleResourceLocator"
+ class="org.eclipse.jpt.common.core.internal.resource.ModuleResourceLocator"
+ priority="lower">
+ <enablement>
+ <with variable="project">
+ <test
+ property="org.eclipse.core.resources.projectNature"
+ value="org.eclipse.wst.common.modulecore.ModuleCoreNature"
+ forcePluginActivation="true"/>
+ </with>
+ </enablement>
+ </resourceLocator>
+
+ <resourceLocator
+ id="webModuleResourceLocator"
+ class="org.eclipse.jpt.common.core.internal.resource.WebModuleResourceLocator"
+ priority="low">
+ <enablement>
+ <with variable="project">
+ <test
+ property="org.eclipse.wst.common.project.facet.core.projectFacet"
+ value="jst.web"
+ forcePluginActivation="true"/>
+ </with>
+ </enablement>
+ </resourceLocator>
+
+ <resourceLocator
+ id="pluginResourceLocator"
+ class="org.eclipse.jpt.common.core.internal.resource.PluginResourceLocator"
+ priority="normal">
+ <enablement>
+ <with variable="project">
+ <test
+ property="org.eclipse.core.resources.projectNature"
+ value="org.eclipse.pde.PluginNature"
+ forcePluginActivation="true"/>
+ </with>
+ </enablement>
+ </resourceLocator>
+
+ </extension>
+ <extension
+ point="org.eclipse.jst.common.project.facet.core.libraryProviders">
+
+ <provider
+ id="jpt-no-op-library-provider"
+ extends="no-op-library-provider"
+ abstract="true">
+ <param name="warning" value="%NO_OP_LIBRARY_PROVIDER_WARNING"/>
+
+ </provider>
+
+ </extension>
+
+
+</plugin>
diff --git a/common/plugins/org.eclipse.jpt.common.core/property_files/jpt_common_core.properties b/common/plugins/org.eclipse.jpt.common.core/property_files/jpt_common_core.properties
new file mode 100644
index 0000000000..3db352b1b7
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/property_files/jpt_common_core.properties
@@ -0,0 +1,22 @@
+################################################################################
+# Copyright (c) 2011 Oracle. All rights reserved.
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v1.0, which accompanies this distribution
+# and is available at http://www.eclipse.org/legal/epl-v10.html.
+#
+# Contributors:
+# Oracle - initial API and implementation
+################################################################################
+DALI_EVENT_HANDLER_THREAD_NAME=Dali Event Handler
+GENERATION_CREATING_LAUNCH_CONFIG_TASK=Creating launch configuration
+GENERATION_SAVING_LAUNCH_CONFIG_TASK=Saving launch configuration
+GENERATION_LAUNCHING_CONFIG_TASK=Launching configuration
+REGISTRY_MISSING_ATTRIBUTE=Missing required attribute ''{0}'' for element ''{1}'' in extension ''{1}'' from plug-in ''{2}''.
+REGISTRY_INVALID_VALUE=Invalid value ''{0}'' for ''{1}'' in extension ''{2}'' from plug-in ''{3}''.
+REGISTRY_DUPLICATE=An extension of ''{0}'' with the ''{1}'' value of ''{2}'' is already registered.
+REGISTRY_FAILED_CLASS_LOAD=Unable to load the class ''{0}'' declared for the extension point ''{1}'' in the plug-in ''{2}''.
+REGISTRY_FAILED_INTERFACE_ASSIGNMENT=Unable to assign the class ''{0}'' declared for the extension point ''{1}'' in the plug-in ''{2}'' to the interface ''{3}''.
+REGISTRY_FAILED_INSTANTIATION=Unable to instantiate the class ''{0}'' declared for the extension point ''{1}'' in the plug-in ''{2}''.
+VALIDATE_CONTAINER_NOT_SPECIFIED=Parent folder must be specified
+VALIDATE_FILE_NAME_NOT_SPECIFIED=File name must be specified
+VALIDATE_FILE_ALREADY_EXISTS=File already exist \ No newline at end of file
diff --git a/common/plugins/org.eclipse.jpt.common.core/schema/libraryValidators.exsd b/common/plugins/org.eclipse.jpt.common.core/schema/libraryValidators.exsd
new file mode 100644
index 0000000000..abfe03b046
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/schema/libraryValidators.exsd
@@ -0,0 +1,154 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.jpt.common.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.jpt.common.core" id="libraryValidators" name="Library Validators"/>
+ </appinfo>
+ <documentation>
+ Used to provide custom library validation to JPT project configuration.
+ </documentation>
+ </annotation>
+
+ <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="libraryValidator" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="libraryValidator">
+ <annotation>
+ <documentation>
+ Declares a library validator. See &lt;samp&gt;org.eclipse.jpt.core.libval.LibraryValidator&lt;/samp&gt; for more information on library validators.
+ </documentation>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="enablement" minOccurs="0" maxOccurs="1"/>
+ </sequence>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ A unique identifier for the declared library validator.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ The implementation class, which implements &lt;samp&gt;org.eclipse.jpt.core.libval.LibraryValidator&lt;/samp&gt;.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.jpt.core.libval.LibraryValidator"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ JPT 3.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ &lt;br&gt;
+&lt;p&gt;
+The following example is the included generic library validator, which is used for user library validation for projects of the generic JPA platform group.
+&lt;p&gt;
+&lt;pre&gt;
+&lt;extension
+ point=&quot;org.eclipse.jpt.common.core.libraryValidators&quot;&gt;
+ &lt;libraryValidator
+ id=&quot;genericUserLibraryValidator&quot;
+ class=&quot;org.eclipse.jpt.core.internal.libval.GenericJpaUserLibraryValidator&quot;&gt;
+ &lt;enablement&gt;
+ &lt;with variable=&quot;libraryProvider&quot;&gt;
+ &lt;test property=&quot;org.eclipse.jpt.core.extendsId&quot; value=&quot;jpa-user-library-provider&quot;/&gt;
+ &lt;/with&gt;
+ &lt;/enablement&gt;
+ &lt;/libraryValidator&gt;
+&lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="apiinfo"/>
+ </appinfo>
+ <documentation>
+ &lt;p&gt;
+The contributed resource locator class must implement &lt;code&gt;org.eclipse.jpt.common.core.resource.ResourceLocator&lt;/code&gt;.
+&lt;p&gt;
+The enablement variables include:
+&lt;ul&gt;
+&lt;li&gt;&quot;libraryProvider&quot; which gives the current ILibraryProvider.&lt;/li&gt;
+&lt;li&gt;&quot;jpaPlatform&quot; which gives the current JpaPlatformDescription.&lt;/li&gt;
+&lt;/ul&gt;
+&lt;/p&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="implementation"/>
+ </appinfo>
+ <documentation>
+ &lt;p&gt;The org.eclipse.jpt.core plug-in provides the following library validators:
+&lt;ul&gt;
+&lt;li&gt;genericUserLibraryValidator&lt;/li&gt;
+&lt;li&gt;genericEclipselinkBundlesLibraryValidator&lt;/li&gt;
+&lt;/ul&gt;
+&lt;/p&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="copyright"/>
+ </appinfo>
+ <documentation>
+ Copyright (c) 2010, 2011 Oracle. All rights reserved.
+This program and the accompanying materials are made available under the
+terms of the Eclipse Public License v1.0, which accompanies this distribution
+and is available at http://www.eclipse.org/legal/epl-v10.html.
+
+Contributors:
+Oracle - initial API and implementation
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/common/plugins/org.eclipse.jpt.common.core/schema/resourceLocators.exsd b/common/plugins/org.eclipse.jpt.common.core/schema/resourceLocators.exsd
new file mode 100644
index 0000000000..5eaf59b07a
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/schema/resourceLocators.exsd
@@ -0,0 +1,191 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.jpt.common.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appinfo>
+ <meta.schema plugin="org.eclipse.jpt.common.core" id="resourceLocators" name="Resource Locators"/>
+ </appinfo>
+ <documentation>
+ Used to provide custom (non-java) resource location logic to JPT projects.
+ </documentation>
+ </annotation>
+
+ <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
+
+ <element name="extension">
+ <annotation>
+ <appinfo>
+ <meta.element />
+ </appinfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="resourceLocator" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appinfo>
+ <meta.attribute translatable="true"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="resourceLocator">
+ <annotation>
+ <documentation>
+ Declares a resource locator. See &lt;samp&gt;org.eclipse.jpt.common.core.resource.ResourceLocator&lt;/samp&gt; for more information on resource locators.
+ </documentation>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="enablement" minOccurs="0" maxOccurs="1"/>
+ </sequence>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ A unique identifier for the declared resource locator.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ The implementation class, which implements &lt;samp&gt;org.eclipse.jpt.common.core.resource.ResourceLocator&lt;/samp&gt;.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.jpt.common.core.resource.ResourceLocator"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ <attribute name="priority">
+ <annotation>
+ <documentation>
+ Indicates the relative priority of this extension to other extensions. Used by the resource locator manager to determine which extension should be used in the case that multiple extensions apply to a given project. Defaults to &quot;normal&quot;.
+ </documentation>
+ </annotation>
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="lowest">
+ </enumeration>
+ <enumeration value="lower">
+ </enumeration>
+ <enumeration value="low">
+ </enumeration>
+ <enumeration value="normal">
+ </enumeration>
+ <enumeration value="high">
+ </enumeration>
+ <enumeration value="higher">
+ </enumeration>
+ <enumeration value="highest">
+ </enumeration>
+ </restriction>
+ </simpleType>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="since"/>
+ </appinfo>
+ <documentation>
+ JPT 3.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="examples"/>
+ </appinfo>
+ <documentation>
+ &lt;br&gt;
+&lt;p&gt;
+The following example is the included simple java resource locator, which is used for simple java projects. It is of &quot;lowest&quot; priority, since all JPT projects will at their roots be simple java projects.
+&lt;p&gt;
+&lt;pre&gt;
+&lt;extension
+ point=&quot;org.eclipse.jpt.common.core.resourceLocators&quot;&gt;
+ &lt;resourceLocator
+ id=&quot;simpleJavaResourceLocator&quot;
+ class=&quot;org.eclipse.jpt.common.core.internal.resource.SimpleJavaResourceLocator&quot;
+ priority=&quot;lowest&quot;
+ &lt;enablement&gt;
+ &lt;with variable=&quot;project&quot;&gt;
+ &lt;test property=&quot;org.eclipse.wst.common.project.facet.core.projectFacet&quot; value=&quot;java&quot; forcePluginActivation=&quot;true&quot;/&gt;
+ &lt;/with&gt;
+ &lt;/enablement&gt;
+ &lt;/resourceLocator&gt;
+&lt;/extension&gt;
+&lt;/pre&gt;
+&lt;/p&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="apiinfo"/>
+ </appinfo>
+ <documentation>
+ &lt;p&gt;
+The contributed resource locator class must implement &lt;code&gt;org.eclipse.jpt.co9mmon.core.resource.ResourceLocator&lt;/code&gt;.
+&lt;p&gt;
+The enablement variables include:
+&lt;ul&gt;
+&lt;li&gt;&quot;project&quot; which gives the current IProject.&lt;/li&gt;
+&lt;/ul&gt;
+&lt;/p&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="implementation"/>
+ </appinfo>
+ <documentation>
+ &lt;p&gt;The org.eclipse.jpt.common.core plug-in provides the following resource locators:
+&lt;ul&gt;
+&lt;li&gt;simpleJavaResourceLocator&lt;/li&gt;
+&lt;li&gt;moduleResourceLocator&lt;/li&gt;
+&lt;li&gt;webModuleResourceLocator&lt;/li&gt;
+&lt;li&gt;pluginResourceLocator&lt;/li&gt;
+&lt;/ul&gt;
+&lt;/p&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appinfo>
+ <meta.section type="copyright"/>
+ </appinfo>
+ <documentation>
+ Copyright (c) 2011 Oracle. All rights reserved.
+This program and the accompanying materials are made available under the
+terms of the Eclipse Public License v1.0, which accompanies this distribution
+and is available at http://www.eclipse.org/legal/epl-v10.html.
+
+Contributors:
+Oracle - initial API and implementation
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/IResourcePart.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/IResourcePart.java
new file mode 100644
index 0000000000..e5e6a4251a
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/IResourcePart.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Oracle.
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core;
+
+import org.eclipse.core.resources.IResource;
+
+
+/**
+ * Represents an object that can be described as being part of an {@link IResource}
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * @version 2.1
+ * @since 2.1
+ */
+public interface IResourcePart
+{
+ /**
+ * Return the resource of which this object is a part
+ */
+ IResource getResource();
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptCommonCorePlugin.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptCommonCorePlugin.java
new file mode 100644
index 0000000000..a615cc78e1
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptCommonCorePlugin.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jpt.common.core.internal.libval.LibraryValidatorManager;
+import org.eclipse.jpt.common.core.internal.resource.ResourceLocatorManager;
+import org.eclipse.jpt.common.core.libprov.JptLibraryProviderInstallOperationConfig;
+import org.eclipse.jpt.common.core.libval.LibraryValidator;
+import org.eclipse.jpt.common.core.resource.ResourceLocator;
+import org.osgi.framework.BundleContext;
+
+public class JptCommonCorePlugin
+ extends Plugin
+{
+
+ // ********** public constants **********
+
+ /**
+ * The plug-in identifier of the jpt common core support
+ * (value <code>"org.eclipse.jpt.common.core"</code>).
+ */
+ public static final String PLUGIN_ID = "org.eclipse.jpt.common.core"; //$NON-NLS-1$
+ public static final String PLUGIN_ID_ = PLUGIN_ID + '.';
+
+
+ /**
+ * The content type for Java source code files.
+ */
+ public static final IContentType JAVA_SOURCE_CONTENT_TYPE = getContentType(JavaCore.JAVA_SOURCE_CONTENT_TYPE);
+
+ /**
+ * The resource type for Java source code files
+ */
+ public static final JptResourceType JAVA_SOURCE_RESOURCE_TYPE = new JptResourceType(JAVA_SOURCE_CONTENT_TYPE);
+
+ /**
+ * The content type for Java archives (JARs).
+ */
+ public static final IContentType JAR_CONTENT_TYPE = getJptContentType("jar"); //$NON-NLS-1$
+
+ /**
+ * The resource type for Java archives (JARs).
+ */
+ public static final JptResourceType JAR_RESOURCE_TYPE = new JptResourceType(JptCommonCorePlugin.JAR_CONTENT_TYPE);
+
+ /**
+ * The content type for package-info Java code files.
+ */
+ public static final IContentType JAVA_SOURCE_PACKAGE_INFO_CONTENT_TYPE = getJptContentType("javaPackageInfo"); //$NON-NLS-1$
+
+ /**
+ * The resource type for package-info Java code files
+ */
+ public static final JptResourceType JAVA_SOURCE_PACKAGE_INFO_RESOURCE_TYPE = new JptResourceType(JAVA_SOURCE_PACKAGE_INFO_CONTENT_TYPE);
+
+
+ private static final String JPT_CONTENT_PREFIX = PLUGIN_ID_ + "content"; //$NON-NLS-1$
+
+ private static final String JPT_CONTENT_PREFIX_ = JPT_CONTENT_PREFIX + '.';
+
+ private static IContentType getJptContentType(String jptContentType) {
+ return getContentType(JPT_CONTENT_PREFIX_ + jptContentType);
+ }
+
+ private static IContentType getContentType(String contentType) {
+ return Platform.getContentTypeManager().getContentType(contentType);
+ }
+
+ public static ResourceLocator getResourceLocator(IProject project) {
+ return ResourceLocatorManager.instance().getResourceLocator(project);
+ }
+
+ public static IFile getPlatformFile(IProject project, IPath runtimePath) {
+ ResourceLocator resourceLocator = getResourceLocator(project);
+ if (resourceLocator == null) {
+ return null;
+ }
+ IPath sourcePath = resourceLocator.getResourcePath(project, runtimePath);
+ if (sourcePath == null) {
+ return null;
+ }
+ return project.getWorkspace().getRoot().getFile(sourcePath);
+ }
+
+ public static Iterable<LibraryValidator> getLibraryValidators(
+ JptLibraryProviderInstallOperationConfig config) {
+ return LibraryValidatorManager.instance().getLibraryValidators(config);
+ }
+
+ // ********** singleton **********
+
+ private static JptCommonCorePlugin INSTANCE;
+
+ /**
+ * Return the singleton jpt common core plug-in.
+ */
+ public static JptCommonCorePlugin instance() {
+ return INSTANCE;
+ }
+
+
+ // ********** public static methods **********
+
+ /**
+ * Log the specified status.
+ */
+ public static void log(IStatus status) {
+ INSTANCE.getLog().log(status);
+ }
+
+ /**
+ * Log the specified message.
+ */
+ public static void log(String msg) {
+ log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, msg, null));
+ }
+
+ /**
+ * Log the specified exception or error.
+ */
+ public static void log(Throwable throwable) {
+ log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, throwable.getLocalizedMessage(), throwable));
+ }
+
+
+ // ********** plug-in implementation **********
+
+ public JptCommonCorePlugin() {
+ super();
+ if (INSTANCE != null) {
+ throw new IllegalStateException();
+ }
+ // this convention is *wack*... ~bjv
+ INSTANCE = this;
+ }
+
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ // nothing yet...
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ // nothing yet...
+ }
+
+}
+
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceModel.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceModel.java
new file mode 100644
index 0000000000..db1cf21f26
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceModel.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core;
+
+/**
+ * Listeners are notified whenever anything in the JPT resource model changes.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * @version 2.3
+ * @since 2.2
+ */
+public interface JptResourceModel {
+
+ /**
+ * Return the resource type of the model. This may potentially change.
+ * Return null if it cannot be determined, the content type or version is null.
+ */
+ JptResourceType getResourceType();
+
+ /**
+ * Changes to the resource model result in events.
+ * In particular, the JPA project performs an "update" whenever a resource
+ * model changes.
+ */
+ void addResourceModelListener(JptResourceModelListener listener);
+
+ /**
+ * @see #addResourceModelListener(ResourceModelListener)
+ */
+ void removeResourceModelListener(JptResourceModelListener listener);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceModelListener.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceModelListener.java
new file mode 100644
index 0000000000..a0d0d3f046
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceModelListener.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core;
+
+import java.util.EventListener;
+
+/**
+ * The listener is notified whenever anything in the JPA resource model changes.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * @version 2.3
+ * @since 2.2
+ */
+public interface JptResourceModelListener
+ extends EventListener
+{
+ void resourceModelChanged(JptResourceModel jpaResourceModel);
+
+ void resourceModelReverted(JptResourceModel jpaResourceModel);
+
+ void resourceModelUnloaded(JptResourceModel jpaResourceModel);
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceType.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceType.java
new file mode 100644
index 0000000000..e86355e266
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/JptResourceType.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core;
+
+import org.eclipse.core.runtime.content.IContentType;
+
+/**
+ * Describes the file content type and version for JPA resources.
+ * This is a value object that defines an {@link #equals(Object)} method.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * @version 2.3
+ * @since 2.3
+ */
+public class JptResourceType
+{
+ private final IContentType contentType;
+
+ private final String version;
+
+
+ /**
+ * Version used when version can not be determined or when there is no
+ * sense of version (e.g. Java).
+ */
+ public static final String UNDETERMINED_VERSION = "<undetermined>"; //$NON-NLS-1$
+
+
+ public JptResourceType(IContentType contentType) {
+ this(contentType, UNDETERMINED_VERSION);
+ }
+
+ public JptResourceType(IContentType contentType, String version) {
+ super();
+ if (contentType == null) {
+ throw new NullPointerException("content type"); //$NON-NLS-1$
+ }
+ if (version == null) {
+ throw new NullPointerException("version"); //$NON-NLS-1$
+ }
+ this.contentType = contentType;
+ this.version = version;
+ }
+
+
+ public IContentType getContentType() {
+ return this.contentType;
+ }
+
+ public String getVersion() {
+ return this.version;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if ((obj == null) || (obj.getClass() != this.getClass())) {
+ return false;
+ }
+ JptResourceType other = (JptResourceType) obj;
+ return this.contentType.equals(other.contentType) && this.version.equals(other.version);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int hash = 17;
+ hash = hash * prime + this.contentType.hashCode();
+ hash = hash * prime + this.version.hashCode();
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.getClass().getSimpleName());
+ sb.append("(content = "); //$NON-NLS-1$
+ sb.append(this.contentType);
+ sb.append(", "); //$NON-NLS-1$
+ sb.append("version = "); //$NON-NLS-1$
+ sb.append(this.version);
+ sb.append(')');
+ return sb.toString();
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/JptCommonCoreMessages.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/JptCommonCoreMessages.java
new file mode 100644
index 0000000000..3b43e56034
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/JptCommonCoreMessages.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Localized messages used by Dali common core.
+ */
+public class JptCommonCoreMessages {
+
+
+ public static String DALI_EVENT_HANDLER_THREAD_NAME;
+ public static String GENERATION_CREATING_LAUNCH_CONFIG_TASK;
+ public static String GENERATION_SAVING_LAUNCH_CONFIG_TASK;
+ public static String GENERATION_LAUNCHING_CONFIG_TASK;
+ public static String REGISTRY_MISSING_ATTRIBUTE;
+ public static String REGISTRY_INVALID_VALUE;
+ public static String REGISTRY_DUPLICATE;
+ public static String REGISTRY_FAILED_CLASS_LOAD;
+ public static String REGISTRY_FAILED_INTERFACE_ASSIGNMENT;
+ public static String REGISTRY_FAILED_INSTANTIATION;
+ public static String VALIDATE_CONTAINER_NOT_SPECIFIED;
+ public static String VALIDATE_FILE_NAME_NOT_SPECIFIED;
+ public static String VALIDATE_FILE_ALREADY_EXISTS;
+
+ private static final String BUNDLE_NAME = "jpt_common_core"; //$NON-NLS-1$
+ private static final Class<?> BUNDLE_CLASS = JptCommonCoreMessages.class;
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS);
+ }
+
+ private JptCommonCoreMessages() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/ResourceAdapterFactory.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/ResourceAdapterFactory.java
new file mode 100644
index 0000000000..16c22cb19e
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/ResourceAdapterFactory.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.jpt.common.core.IResourcePart;
+
+/**
+ * Factory to build adapters for Eclipse resources:
+ * - resource part
+ *
+ * See org.eclipse.jpt.common.core plugin.xml.
+ */
+public class ResourceAdapterFactory
+ implements IAdapterFactory
+{
+ private static final Class<?>[] ADAPTER_LIST = new Class[] { IResourcePart.class };
+
+ public Class<?>[] getAdapterList() {
+ return ADAPTER_LIST;
+ }
+
+ public Object getAdapter(Object adaptableObject, @SuppressWarnings("unchecked") Class adapterType) {
+ if (adaptableObject instanceof IResource) {
+ return this.getAdapter((IResource) adaptableObject, adapterType);
+ }
+ return null;
+ }
+
+ private Object getAdapter(final IResource resource, Class <?>adapterType) {
+ if (adapterType == IResourcePart.class) {
+ return new IResourcePart() {
+ public IResource getResource() {
+ return resource;
+ }
+ };
+ }
+ return null;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/XPointUtil.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/XPointUtil.java
new file mode 100644
index 0000000000..81a9d963c4
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/XPointUtil.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.Bundle;
+
+/**
+ * Utilities for extension point management, validation, etc.
+ */
+public class XPointUtil {
+
+ public static String findRequiredAttribute(
+ IConfigurationElement configElement, String attributeName)
+ throws XPointException {
+
+ String val = configElement.getAttribute(attributeName);
+ if (val == null) {
+ logMissingAttribute(configElement, attributeName);
+ throw new XPointException();
+ }
+ return val;
+ }
+
+ public static <T> T instantiate(
+ String pluginId, String extensionPoint, String className, Class<T> interfaze) {
+
+ Class<T> clazz = loadClass(pluginId, extensionPoint, className, interfaze);
+ if (clazz == null) {
+ return null;
+ }
+ return instantiate(pluginId, extensionPoint, clazz);
+ }
+
+ public static <T> T instantiate(String pluginId, String extensionPoint, Class<T> clazz) {
+
+ try {
+ return clazz.newInstance();
+ }
+ catch (Exception e) {
+ logFailedInstantiation(pluginId, extensionPoint, clazz.getName());
+ return null;
+ }
+ }
+
+ public static <T> Class<T> loadClass(
+ String pluginId, String extensionPoint, String className, Class<T> interfaze) {
+
+ Bundle bundle = Platform.getBundle(pluginId);
+ Class<?> clazz;
+
+ try {
+ clazz = bundle.loadClass(className);
+ }
+ catch (Exception e) {
+ logFailedClassLoad(pluginId, extensionPoint, className);
+ return null;
+ }
+
+ if (interfaze != null && ! interfaze.isAssignableFrom(clazz)) {
+ logFailedInterfaceAssignment(pluginId, extensionPoint, className, interfaze.getName());
+ return null;
+ }
+
+ return (Class<T>) clazz;
+ }
+
+ public static void logDuplicateExtension(String extensionPoint, String nodeName, String value) {
+
+ log(JptCommonCoreMessages.REGISTRY_DUPLICATE, extensionPoint, nodeName, value);
+ }
+
+ public static void logMissingAttribute(
+ IConfigurationElement configElement, String attributeName) {
+
+ log(JptCommonCoreMessages.REGISTRY_MISSING_ATTRIBUTE,
+ attributeName,
+ configElement.getName(),
+ configElement.getDeclaringExtension().getExtensionPointUniqueIdentifier(),
+ configElement.getContributor().getName());
+ }
+
+ public static void logInvalidValue(
+ IConfigurationElement configElement, String nodeName, String invalidValue) {
+
+ log(JptCommonCoreMessages.REGISTRY_INVALID_VALUE,
+ invalidValue,
+ nodeName,
+ configElement.getDeclaringExtension().getExtensionPointUniqueIdentifier(),
+ configElement.getContributor().getName());
+ }
+
+ private static void logFailedClassLoad(String pluginId, String extensionPoint, String className) {
+
+ log(JptCommonCoreMessages.REGISTRY_FAILED_CLASS_LOAD,
+ className,
+ extensionPoint,
+ pluginId);
+ }
+
+ private static void logFailedInterfaceAssignment(
+ String pluginId, String extensionPoint, String className, String interfaceName) {
+
+ log(JptCommonCoreMessages.REGISTRY_FAILED_INTERFACE_ASSIGNMENT,
+ className,
+ extensionPoint,
+ pluginId,
+ interfaceName);
+ }
+
+ private static void logFailedInstantiation(String pluginId, String extensionPoint, String className) {
+
+ log(JptCommonCoreMessages.REGISTRY_FAILED_INSTANTIATION,
+ className,
+ extensionPoint,
+ pluginId);
+ }
+
+ public static void log(String msg, String... bindings) {
+ JptCommonCorePlugin.log(NLS.bind(msg, bindings));
+ }
+
+ public static void log(Exception e) {
+ JptCommonCorePlugin.log(e);
+ }
+
+
+ public static final class XPointException
+ extends Exception {
+
+ private static final long serialVersionUID = 1L;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/gen/AbstractJptGenerator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/gen/AbstractJptGenerator.java
new file mode 100644
index 0000000000..eeee457a07
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/gen/AbstractJptGenerator.java
@@ -0,0 +1,369 @@
+/*******************************************************************************
+* Copyright (c) 2008, 2011 Oracle. All rights reserved.
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0, which accompanies this distribution
+* and is available at http://www.eclipse.org/legal/epl-v10.html.
+*
+* Contributors:
+* Oracle - initial API and implementation
+*******************************************************************************/
+package org.eclipse.jpt.common.core.internal.gen;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.ILaunchesListener2;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
+import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
+import org.eclipse.jdt.launching.IVMInstall;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.internal.JptCommonCoreMessages;
+import org.eclipse.osgi.service.datalocation.Location;
+import org.osgi.framework.Bundle;
+
+public abstract class AbstractJptGenerator
+{
+ public static final String PLUGINS_DIR = "plugins/"; //$NON-NLS-1$
+
+ private IVMInstall jre;
+ protected ILaunchConfigurationWorkingCopy launchConfig;
+ private ILaunch launch;
+
+ protected final IJavaProject javaProject;
+ protected final String projectLocation;
+
+ private final boolean isDebug = true;
+
+ // ********** constructors **********
+
+ protected AbstractJptGenerator(IJavaProject javaProject) {
+ super();
+ this.javaProject = javaProject;
+ this.projectLocation = javaProject.getProject().getLocation().toString();
+ this.initialize();
+ }
+
+ // ********** abstract methods **********
+
+ protected abstract String getMainType();
+
+ protected abstract String getLaunchConfigName();
+
+ protected String getBootstrapJarPrefix() {
+ throw new RuntimeException("Bootstrap JAR not specified."); //$NON-NLS-1$;
+ }
+
+ protected abstract void specifyProgramArguments();
+
+ protected abstract List<String> buildClasspath() throws CoreException;
+
+ // ********** behavior **********
+
+ protected void initialize() {
+ try {
+ this.jre = this.getProjectJRE();
+ if (this.jre == null) {
+ String message = "Could not identify the VM."; //$NON-NLS-1$
+ throw new RuntimeException(message);
+ }
+ this.launchConfig = this.buildLaunchConfiguration();
+ }
+ catch (CoreException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void generate(IProgressMonitor monitor) {
+ SubMonitor sm = SubMonitor.convert(monitor, 10);
+ this.preGenerate(sm.newChild(2));
+ if (sm.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ sm.subTask(JptCommonCoreMessages.GENERATION_CREATING_LAUNCH_CONFIG_TASK);
+ this.initializeLaunchConfiguration();
+ sm.worked(1);
+ if (sm.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+
+ this.addLaunchListener();
+ sm.worked(1);
+
+ if (sm.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ this.launch = this.saveAndLaunchConfig(sm.newChild(6));
+ }
+
+ private void initializeLaunchConfiguration() {
+ this.specifyJRE();
+
+ this.specifyProject();
+ this.specifyMainType();
+
+ this.specifyProgramArguments();
+ this.specifyWorkingDir();
+
+ this.specifyClasspathProperties();
+ }
+
+ private void addLaunchListener() {
+
+ this.getLaunchManager().addLaunchListener(this.buildLaunchListener());
+ }
+
+ protected abstract void preGenerate(IProgressMonitor monitor);
+
+ protected void postGenerate() {
+ try {
+ if( ! this.isDebug) {
+ this.removeLaunchConfiguration();
+ }
+ }
+ catch(CoreException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private ILaunchesListener2 buildLaunchListener() {
+ return new ILaunchesListener2() {
+
+ public void launchesTerminated(ILaunch[] launches) {
+ for(int i = 0; i < launches.length; i++) {
+ ILaunch launch = launches[i];
+ if (launch.equals(AbstractJptGenerator.this.getLaunch())) {
+
+ AbstractJptGenerator.this.postGenerate();
+ return;
+ }
+ }
+ }
+
+ public void launchesAdded(ILaunch[] launches) {
+ // not interested to this event
+ }
+
+ public void launchesChanged(ILaunch[] launches) {
+ // not interested to this event
+ }
+
+ public void launchesRemoved(ILaunch[] launches) {
+ // not interested to this event
+ }
+ };
+ }
+
+ // ********** Setting Launch Configuration **********
+
+ private void specifyJRE() {
+ String jreName = this.jre.getName();
+ String vmId = this.jre.getVMInstallType().getId();
+ this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, jreName);
+ this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, vmId);
+ }
+
+ private void specifyProject() {
+ String projectName = this.getProject().getName();
+ this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectName);
+ }
+
+ protected IProject getProject() {
+ return this.javaProject.getProject();
+ }
+
+ private void specifyMainType() {
+ this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, this.getMainType());
+ }
+
+ protected void specifyClasspathProperties() {
+ List<String> classpath;
+ try {
+ classpath = this.buildClasspath();
+ }
+ catch (CoreException e) {
+ throw new RuntimeException("An error occured generating a memento", e); //$NON-NLS-1$
+ }
+ this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, classpath);
+ this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, false);
+ }
+
+ // ********** ClasspathEntry **********
+
+ protected IRuntimeClasspathEntry getSystemLibraryClasspathEntry() throws CoreException {
+
+ IPath systemLibsPath = new Path(JavaRuntime.JRE_CONTAINER);
+ return JavaRuntime.newRuntimeContainerClasspathEntry(systemLibsPath, IRuntimeClasspathEntry.STANDARD_CLASSES);
+ }
+
+ protected IRuntimeClasspathEntry getDefaultProjectClasspathEntry() {
+
+ IRuntimeClasspathEntry projectEntry = JavaRuntime.newDefaultProjectClasspathEntry(this.javaProject);
+ projectEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES);
+
+ return projectEntry;
+ }
+
+ protected static IRuntimeClasspathEntry getArchiveClasspathEntry(IPath archivePath) {
+ IRuntimeClasspathEntry archiveEntry = JavaRuntime.newArchiveRuntimeClasspathEntry(archivePath);
+ archiveEntry.setClasspathProperty(IRuntimeClasspathEntry.USER_CLASSES);
+
+ return archiveEntry;
+ }
+
+
+ // ********** LaunchConfig **********
+
+ private ILaunch saveAndLaunchConfig(IProgressMonitor monitor) {
+ SubMonitor sm = SubMonitor.convert(monitor, 10);
+ ILaunchConfiguration configuration = null;
+ ILaunch result = null;
+ try {
+ sm.subTask(JptCommonCoreMessages.GENERATION_SAVING_LAUNCH_CONFIG_TASK);
+ configuration = this.launchConfig.doSave();
+ }
+ catch (CoreException saveException) {
+ throw new RuntimeException("Could not save LaunchConfig", saveException); //$NON-NLS-1$
+ }
+ sm.worked(1);
+ if (sm.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ try {
+ sm.subTask(JptCommonCoreMessages.GENERATION_LAUNCHING_CONFIG_TASK);
+ result = configuration.launch(ILaunchManager.RUN_MODE, sm.newChild(9));
+ }
+ catch (CoreException launchException) {
+ throw new RuntimeException("An error occured during launch", launchException); //$NON-NLS-1$
+ }
+ return result;
+ }
+
+ // ********** Main arguments **********
+
+ protected void appendDebugArgument(StringBuffer sb) {
+ if (this.isDebug) {
+ sb.append(" -debug"); //$NON-NLS-1$
+ }
+ }
+
+ // ********** Queries **********
+
+ protected ILaunch getLaunch() {
+ return this.launch;
+ }
+
+ protected ILaunchManager getLaunchManager() {
+ return DebugPlugin.getDefault().getLaunchManager();
+ }
+
+ private IVMInstall getProjectJRE() throws CoreException {
+ return JavaRuntime.getVMInstall(this.javaProject);
+ }
+
+ // ********** Utilities **********
+
+ protected IRuntimeClasspathEntry getBootstrapJarClasspathEntry() {
+ return getArchiveClasspathEntry(this.buildBootstrapJarPath());
+ }
+
+ protected IPath buildBootstrapJarPath() {
+ return this.findGenJarStartingWith(this.getBootstrapJarPrefix());
+ }
+
+ protected IPath findGenJarStartingWith(String genJarName) {
+ try {
+ File jarInstallDir = this.getBundleParentDir(JptCommonCorePlugin.PLUGIN_ID);
+
+ List<File> result = new ArrayList<File>();
+ this.findFileStartingWith(genJarName, jarInstallDir, result);
+ if (result.isEmpty()) {
+ throw new RuntimeException("Could not find: " + genJarName + "#.#.#v###.jar in: " + jarInstallDir); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ File genJarFile = result.get(0);
+ String genJarPath = genJarFile.getCanonicalPath();
+ return new Path(genJarPath);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // ********** private methods **********
+
+ private File getBundleParentDir(String bundleName) throws IOException {
+
+ if (Platform.inDevelopmentMode()) {
+ Location eclipseHomeLoc = Platform.getInstallLocation();
+ String eclipseHome = eclipseHomeLoc.getURL().getPath();
+ if ( ! eclipseHome.endsWith(PLUGINS_DIR)) {
+ eclipseHome += PLUGINS_DIR;
+ }
+ return new File(eclipseHome);
+ }
+ Bundle bundle = Platform.getBundle(bundleName);
+ return FileLocator.getBundleFile(bundle).getParentFile();
+ }
+
+ private ILaunchConfigurationWorkingCopy buildLaunchConfiguration() throws CoreException {
+ this.removeLaunchConfiguration();
+
+ ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
+ ILaunchConfigurationType type = manager.getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
+
+ return type.newInstance(null, this.getLaunchConfigName());
+ }
+
+ private void removeLaunchConfiguration() throws CoreException {
+
+ ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
+ ILaunchConfigurationType type = manager.getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
+
+ ILaunchConfiguration[] configurations = manager.getLaunchConfigurations(type);
+ for (int i = 0; i < configurations.length; i++) {
+ ILaunchConfiguration configuration = configurations[i];
+ if (configuration.getName().equals(this.getLaunchConfigName())) {
+ configuration.delete();
+ break;
+ }
+ }
+ }
+
+ private void findFileStartingWith(String fileName, File directory, List<? super File> list) {
+ if(directory.listFiles() == null) {
+ throw new RuntimeException("Could not find directory: " + directory); //$NON-NLS-1$
+ }
+ for (File file : directory.listFiles()) {
+ if (file.getName().startsWith(fileName)) {
+ list.add(file);
+ }
+ if (file.isDirectory()) {
+ this.findFileStartingWith(fileName, file, list);
+ }
+ }
+ }
+
+ private void specifyWorkingDir() {
+ File workingDir = new Path(this.projectLocation).toFile();
+ this.launchConfig.setAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, workingDir.getAbsolutePath());
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/JptOsgiBundlesLibraryProviderInstallOperationConfig.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/JptOsgiBundlesLibraryProviderInstallOperationConfig.java
new file mode 100644
index 0000000000..b91c73b440
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/JptOsgiBundlesLibraryProviderInstallOperationConfig.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.libprov;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.libprov.JptLibraryProviderInstallOperationConfig;
+import org.eclipse.jpt.common.core.libval.LibraryValidator;
+import org.eclipse.jst.j2ee.internal.common.classpath.WtpOsgiBundlesLibraryProviderInstallOperationConfig;
+
+
+public abstract class JptOsgiBundlesLibraryProviderInstallOperationConfig
+ extends WtpOsgiBundlesLibraryProviderInstallOperationConfig
+ implements JptLibraryProviderInstallOperationConfig {
+
+ protected JptOsgiBundlesLibraryProviderInstallOperationConfig() {
+ super();
+ }
+
+
+ @Override
+ public synchronized IStatus validate() {
+ IStatus status = super.validate();
+ if (! status.isOK()) {
+ return status;
+ }
+
+ for (LibraryValidator libraryValidator : JptCommonCorePlugin.getLibraryValidators(this)) {
+ status = libraryValidator.validate(this);
+ if (! status.isOK()) {
+ return status;
+ }
+ }
+
+ return Status.OK_STATUS;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/JptUserLibraryProviderInstallOperationConfig.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/JptUserLibraryProviderInstallOperationConfig.java
new file mode 100644
index 0000000000..224f52afe2
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/JptUserLibraryProviderInstallOperationConfig.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.libprov;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.libprov.JptLibraryProviderInstallOperationConfig;
+import org.eclipse.jpt.common.core.libval.LibraryValidator;
+import org.eclipse.jst.j2ee.internal.common.classpath.WtpUserLibraryProviderInstallOperationConfig;
+
+
+public abstract class JptUserLibraryProviderInstallOperationConfig
+ extends WtpUserLibraryProviderInstallOperationConfig
+ implements JptLibraryProviderInstallOperationConfig {
+
+ protected JptUserLibraryProviderInstallOperationConfig() {
+ super();
+ }
+
+
+ @Override
+ public synchronized IStatus validate() {
+ IStatus status = super.validate();
+ if (! status.isOK()) {
+ return status;
+ }
+
+ for (LibraryValidator libraryValidator : JptCommonCorePlugin.getLibraryValidators(this)) {
+ status = libraryValidator.validate(this);
+ if (! status.isOK()) {
+ return status;
+ }
+ }
+
+ return Status.OK_STATUS;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/LibraryProviderPropertyTester.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/LibraryProviderPropertyTester.java
new file mode 100644
index 0000000000..e3bb569eed
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libprov/LibraryProviderPropertyTester.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.libprov;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.jst.common.project.facet.core.libprov.ILibraryProvider;
+
+public class LibraryProviderPropertyTester
+ extends PropertyTester {
+
+ public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+ if (! (property.equals("id") || property.equals("extendsId")) //$NON-NLS-1$ //$NON-NLS-2$
+ || ! (receiver instanceof ILibraryProvider)
+ || ! (expectedValue instanceof String)) {
+ return false;
+ }
+
+ ILibraryProvider libraryProvider = (ILibraryProvider) receiver;
+
+ if (property.equals("id")) { //$NON-NLS-1$
+ return libraryProvider.getId().equals(expectedValue);
+ }
+ else if (property.equals("extendsId")) { //$NON-NLS-1$
+ while (libraryProvider != null) {
+ if (libraryProvider.getId().equals(expectedValue)) {
+ return true;
+ }
+ libraryProvider = libraryProvider.getBaseProvider();
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libval/LibraryValidatorConfig.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libval/LibraryValidatorConfig.java
new file mode 100644
index 0000000000..05c340df35
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libval/LibraryValidatorConfig.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.libval;
+
+import static org.eclipse.jst.common.project.facet.core.internal.FacetedProjectFrameworkJavaPlugin.log;
+import org.eclipse.core.expressions.EvaluationContext;
+import org.eclipse.core.expressions.EvaluationResult;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jpt.common.core.internal.XPointUtil;
+import org.eclipse.jpt.common.core.libprov.JptLibraryProviderInstallOperationConfig;
+import org.eclipse.jpt.common.core.libval.LibraryValidator;
+
+public class LibraryValidatorConfig {
+
+ public static final String CONFIG_EXPR_VAR = "config"; //$NON-NLS-1$
+ public static final String LIBRARY_PROVIDER_EXPR_VAR = "libraryProvider"; //$NON-NLS-1$
+
+
+ private String id;
+ private String pluginId;
+ private String className;
+ private Expression enablementCondition;
+
+
+ LibraryValidatorConfig() {
+ super();
+ }
+
+
+ public String getId() {
+ return this.id;
+ }
+
+ void setId(String id) {
+ this.id = id;
+ }
+
+ public String getPluginId() {
+ return this.pluginId;
+ }
+
+ void setPluginId(String pluginId) {
+ this.pluginId = pluginId;
+ }
+
+ public String getClassName() {
+ return this.className;
+ }
+
+ void setClassName(String className) {
+ this.className = className;
+ }
+
+ public Expression getEnablementCondition() {
+ return this.enablementCondition;
+ }
+
+ void setEnablementCondition(Expression enablementCondition) {
+ this.enablementCondition = enablementCondition;
+ }
+
+ public LibraryValidator getLibraryValidator() {
+ return XPointUtil.instantiate(
+ this.pluginId, LibraryValidatorManager.QUALIFIED_EXTENSION_POINT_ID,
+ this.className, LibraryValidator.class);
+ }
+
+ public boolean isEnabledFor(JptLibraryProviderInstallOperationConfig config) {
+ EvaluationContext evalContext = new EvaluationContext(null, config);
+ evalContext.setAllowPluginActivation(true);
+ evalContext.addVariable(CONFIG_EXPR_VAR, config);
+ evalContext.addVariable(LIBRARY_PROVIDER_EXPR_VAR, config.getLibraryProvider());
+
+ if (this.enablementCondition != null) {
+ try {
+ EvaluationResult evalResult = this.enablementCondition.evaluate(evalContext);
+
+ if (evalResult == EvaluationResult.FALSE) {
+ return false;
+ }
+ }
+ catch (CoreException e) {
+ log(e);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libval/LibraryValidatorManager.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libval/LibraryValidatorManager.java
new file mode 100644
index 0000000000..ccca3239a0
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/libval/LibraryValidatorManager.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.libval;
+
+import static org.eclipse.jpt.common.core.internal.XPointUtil.*;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.expressions.ExpressionConverter;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.internal.XPointUtil.XPointException;
+import org.eclipse.jpt.common.core.libprov.JptLibraryProviderInstallOperationConfig;
+import org.eclipse.jpt.common.core.libval.LibraryValidator;
+import org.eclipse.jpt.utility.internal.KeyedSet;
+import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;
+
+public class LibraryValidatorManager {
+
+ public static final String EXTENSION_POINT_ID = "libraryValidators"; //$NON-NLS-1$
+ public static final String QUALIFIED_EXTENSION_POINT_ID = JptCommonCorePlugin.PLUGIN_ID_ + EXTENSION_POINT_ID;
+ public static final String LIBRARY_VALIDATOR_ELEMENT = "libraryValidator"; //$NON-NLS-1$
+ public static final String ID_ATTRIBUTE = "id"; //$NON-NLS-1$
+ public static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
+ public static final String ENABLEMENT_ELEMENT = "enablement"; //$NON-NLS-1$
+
+
+ private static LibraryValidatorManager INSTANCE = new LibraryValidatorManager();
+
+
+ public static LibraryValidatorManager instance() {
+ return INSTANCE;
+ }
+
+
+ private KeyedSet<String, LibraryValidatorConfig> libraryValidatorConfigs;
+
+
+ private LibraryValidatorManager() {
+ this.libraryValidatorConfigs = new KeyedSet<String, LibraryValidatorConfig>();
+ readExtensions();
+ }
+
+
+ /**
+ * Return the {@link LibraryValidator}s
+ */
+ public Iterable<LibraryValidator> getLibraryValidators(final JptLibraryProviderInstallOperationConfig config) {
+ return new FilteringIterable<LibraryValidator>(
+ new TransformationIterable<LibraryValidatorConfig, LibraryValidator>(
+ new FilteringIterable<LibraryValidatorConfig>(
+ this.libraryValidatorConfigs.getItemSet()) {
+ @Override
+ protected boolean accept(LibraryValidatorConfig o) {
+ return o.isEnabledFor(config);
+ }
+ }) {
+ @Override
+ protected LibraryValidator transform(LibraryValidatorConfig o) {
+ return o.getLibraryValidator();
+ }
+ }) {
+ @Override
+ protected boolean accept(LibraryValidator o) {
+ return o != null;
+ }
+ };
+ }
+
+ private void readExtensions() {
+ final IExtensionRegistry registry = Platform.getExtensionRegistry();
+
+ final IExtensionPoint xpoint
+ = registry.getExtensionPoint(QUALIFIED_EXTENSION_POINT_ID);
+
+ if (xpoint == null) {
+ throw new IllegalStateException();
+ }
+
+ final List<IConfigurationElement> configs = new ArrayList<IConfigurationElement>();
+
+ for (IExtension extension : xpoint.getExtensions()) {
+ for (IConfigurationElement element : extension.getConfigurationElements()) {
+ configs.add(element);
+ }
+ }
+
+ for (IConfigurationElement element : configs) {
+ if (element.getName().equals(LIBRARY_VALIDATOR_ELEMENT)) {
+ readExtension(element);
+ }
+ }
+ }
+
+ private void readExtension(IConfigurationElement element) {
+ try {
+ final LibraryValidatorConfig lvConfig = new LibraryValidatorConfig();
+
+ // plug-in id
+ lvConfig.setPluginId(element.getContributor().getName());
+
+ // resource locator id
+ lvConfig.setId(findRequiredAttribute(element, ID_ATTRIBUTE));
+
+ if (this.libraryValidatorConfigs.containsKey(lvConfig.getId())) {
+ logDuplicateExtension(QUALIFIED_EXTENSION_POINT_ID, ID_ATTRIBUTE, lvConfig.getId());
+ throw new XPointException();
+ }
+
+ // resource locator class name
+ lvConfig.setClassName(findRequiredAttribute(element, CLASS_ATTRIBUTE));
+
+ // enablement
+ for (IConfigurationElement child : element.getChildren()) {
+ String childName = child.getName();
+ if (childName.equals(ENABLEMENT_ELEMENT)) {
+ Expression expr;
+ try {
+ expr = ExpressionConverter.getDefault().perform(child);
+ }
+ catch (CoreException e) {
+ log(e);
+ throw new XPointException();
+ }
+ lvConfig.setEnablementCondition(expr);
+ }
+ }
+
+ this.libraryValidatorConfigs.addItem(lvConfig.getId(), lvConfig);
+ }
+ catch (XPointException e) {
+ // Ignore and continue. The problem has already been reported to the user
+ // in the log.
+ }
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/operations/AbstractJptFileCreationDataModelProvider.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/operations/AbstractJptFileCreationDataModelProvider.java
new file mode 100644
index 0000000000..0288eb7d0a
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/operations/AbstractJptFileCreationDataModelProvider.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.operations;
+
+import java.util.Set;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.internal.JptCommonCoreMessages;
+import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
+import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelProvider;
+
+public abstract class AbstractJptFileCreationDataModelProvider
+ extends AbstractDataModelProvider
+ implements JptFileCreationDataModelProperties
+{
+ protected AbstractJptFileCreationDataModelProvider() {
+ super();
+ }
+
+
+ @Override
+ public Set<String> getPropertyNames() {
+ @SuppressWarnings("unchecked")
+ Set<String> propertyNames = super.getPropertyNames();
+ propertyNames.add(PROJECT);
+ propertyNames.add(CONTAINER_PATH);
+ propertyNames.add(FILE_NAME);
+ return propertyNames;
+ }
+
+ @Override
+ public Object getDefaultProperty(String propertyName) {
+ if (propertyName.equals(CONTAINER_PATH)) {
+ IContainer sourceLocation = getDefaultContainer();
+ if (sourceLocation != null && sourceLocation.exists()) {
+ return sourceLocation.getFullPath();
+ }
+ }
+ else if (propertyName.equals(FILE_NAME)) {
+ return getDefaultFileName();
+ }
+ return super.getDefaultProperty(propertyName);
+ }
+
+ protected abstract String getDefaultFileName();
+
+
+ // **************** validation *********************************************
+
+ @Override
+ public IStatus validate(String propertyName) {
+ IStatus status = Status.OK_STATUS;
+ if (propertyName.equals(CONTAINER_PATH)
+ || propertyName.equals(FILE_NAME)) {
+ status = validateContainerPathAndFileName();
+ }
+ if (! status.isOK()) {
+ return status;
+ }
+
+ return status;
+ }
+
+ protected IStatus validateContainerPathAndFileName() {
+ IContainer container = getContainer();
+ if (container == null) {
+ // verifies container has been specified, but should be unnecessary in most cases.
+ // there is almost always a default, and the new file wizard does this validation as well.
+ return new Status(
+ IStatus.ERROR, JptCommonCorePlugin.PLUGIN_ID,
+ JptCommonCoreMessages.VALIDATE_CONTAINER_NOT_SPECIFIED);
+ }
+ String fileName = getStringProperty(FILE_NAME);
+ if (StringTools.stringIsEmpty(fileName)) {
+ // verifies file name has been specified, but should be unnecessary in most cases.
+ // there is almost always a default, and the new file wizard does this validation as well.
+ return new Status(
+ IStatus.ERROR, JptCommonCorePlugin.PLUGIN_ID,
+ JptCommonCoreMessages.VALIDATE_FILE_NAME_NOT_SPECIFIED);
+ }
+ if (container.getFile(new Path(fileName)).exists()) {
+ // verifies file does not exist, but should be unnecessary in most cases.
+ // the new file wizard does this validation as well.
+ return new Status(
+ IStatus.ERROR, JptCommonCorePlugin.PLUGIN_ID,
+ JptCommonCoreMessages.VALIDATE_FILE_ALREADY_EXISTS);
+ }
+ return Status.OK_STATUS;
+ }
+
+
+ // **************** helper methods *****************************************
+
+ protected IPath getContainerPath() {
+ return (IPath) this.model.getProperty(CONTAINER_PATH);
+ }
+
+ protected IContainer getContainer() {
+ IPath containerPath = getContainerPath();
+ if (containerPath == null) {
+ return null;
+ }
+ return PlatformTools.getContainer(containerPath);
+ }
+
+ protected IProject getProject() {
+ return getProject(getContainer());
+ }
+
+ protected IProject getProject(IContainer container) {
+ return (container == null) ? null : container.getProject();
+ }
+
+ /**
+ * Return a best guess source location for the for the specified project
+ */
+ protected IContainer getDefaultContainer() {
+ IProject project = (IProject) this.model.getProperty(PROJECT);
+ if (project != null) {
+ return JptCommonCorePlugin.getResourceLocator(project).getDefaultResourceLocation(project);
+ }
+ return null;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/operations/JptFileCreationDataModelProperties.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/operations/JptFileCreationDataModelProperties.java
new file mode 100644
index 0000000000..5c635c98c8
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/operations/JptFileCreationDataModelProperties.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 Oracle.
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.operations;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+
+public interface JptFileCreationDataModelProperties
+{
+ /**
+ * Optional, type {@link IProject}, gives a clue as to the default container path
+ */
+ String PROJECT = "JptFileCreationDataModelProperties.PROJECT"; //$NON-NLS-1$
+
+ /**
+ * Required, type {@link IPath}, identifies the full path to the container in which
+ * the file should be created
+ */
+ String CONTAINER_PATH = "JptFileCreationDataModelProperties.CONTAINER_PATH"; //$NON-NLS-1$
+
+ /**
+ * Required, type {@link String}, identifies the file name
+ */
+ String FILE_NAME = "JptFileCreationDataModelProperties.FILE_NAME"; //$NON-NLS-1$
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ModuleResourceLocator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ModuleResourceLocator.java
new file mode 100644
index 0000000000..104081ec57
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ModuleResourceLocator.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.resource;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
+import org.eclipse.wst.common.componentcore.ComponentCore;
+import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
+import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
+import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
+import org.eclipse.wst.common.componentcore.resources.IVirtualResource;
+
+public class ModuleResourceLocator
+ extends SimpleJavaResourceLocator {
+
+ /**
+ * Return the folder representing the "META-INF" runtime location
+ */
+ @Override
+ public IContainer getDefaultResourceLocation(IProject project) {
+ IVirtualComponent component = ComponentCore.createComponent(project);
+ return component.getRootFolder().getFolder(META_INF_PATH).getUnderlyingFolder();
+ }
+
+ @Override
+ public IPath getResourcePath(IProject project, IPath runtimePath) {
+ IVirtualComponent component = ComponentCore.createComponent(project);
+ return component.getRootFolder().getFile(runtimePath).getWorkspaceRelativePath();
+ }
+
+ @Override
+ public IPath getRuntimePath(IProject project, IPath resourcePath) {
+ IFile file = PlatformTools.getFile(resourcePath);
+ IVirtualComponent component = ComponentCore.createComponent(project);
+ IVirtualFolder root = component.getRootFolder();
+ IVirtualFile vFile = findVirtualFile(root, file);
+ if (vFile != null) {
+ return vFile.getRuntimePath().makeRelative();
+ }
+ // couldn't find it. try the super-case
+ return super.getRuntimePath(project, resourcePath);
+ }
+
+ private IVirtualFile findVirtualFile(IVirtualFolder vFolder, IFile file) {
+ try {
+ for (IVirtualResource vResource : vFolder.members()) {
+ if (vResource.getType() == IVirtualResource.FILE) {
+ IVirtualFile vFile = (IVirtualFile) vResource;
+ if (file.equals(vFile.getUnderlyingResource())) {
+ return vFile;
+ }
+ }
+ else if (vResource.getType() == IVirtualResource.FOLDER) {
+ IVirtualFile vFile = findVirtualFile((IVirtualFolder) vResource, file);
+ if (vFile != null) {
+ return vFile;
+ }
+ }
+ }
+ }
+ catch (CoreException ce) {
+ // fall through
+ JptCommonCorePlugin.log(ce);
+ }
+ return null;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/PluginResourceLocator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/PluginResourceLocator.java
new file mode 100644
index 0000000000..4dcd3fd221
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/PluginResourceLocator.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.resource;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
+import org.eclipse.pde.core.project.IBundleProjectDescription;
+import org.eclipse.pde.core.project.IBundleProjectService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class PluginResourceLocator
+ extends SimpleJavaResourceLocator {
+
+ @Override
+ public IContainer getDefaultResourceLocation(IProject project) {
+ try {
+ IContainer root = getBundleRoot(project);
+ return root.getFolder(META_INF_PATH);
+ }
+ catch (CoreException ce) {
+ // fall through
+ JptCommonCorePlugin.log(ce);
+ }
+ return super.getDefaultResourceLocation(project);
+ }
+
+ @Override
+ public IPath getResourcePath(IProject project, IPath runtimePath) {
+ try {
+ IContainer root = getBundleRoot(project);
+ IPath resourcePath = root.getFullPath().append(runtimePath);
+ if (project.getWorkspace().getRoot().getFile(resourcePath).exists()) {
+ return resourcePath;
+ }
+ }
+ catch (CoreException ce) {
+ // fall through
+ JptCommonCorePlugin.log(ce);
+ }
+ return super.getResourcePath(project, runtimePath);
+ }
+
+ @Override
+ public IPath getRuntimePath(IProject project, IPath resourcePath) {
+ IFile file = PlatformTools.getFile(resourcePath);
+ try {
+ IContainer root = getBundleRoot(project);
+ if (root.contains(file)) {
+ return resourcePath.makeRelativeTo(root.getFullPath());
+ }
+ }
+ catch (CoreException ce) {
+ // fall through
+ JptCommonCorePlugin.log(ce);
+ }
+ return super.getRuntimePath(project, resourcePath);
+ }
+
+ protected IContainer getBundleRoot(IProject project)
+ throws CoreException {
+
+ IBundleProjectService service = getBundleProjectService();
+ IBundleProjectDescription description = service.getDescription(project);
+ IPath path = description.getBundleRoot();
+ return (path == null) ? project : project.getFolder(path);
+ }
+
+ protected IBundleProjectService getBundleProjectService() {
+ BundleContext context = JptCommonCorePlugin.instance().getBundle().getBundleContext();
+ ServiceReference<IBundleProjectService> reference = context.getServiceReference(IBundleProjectService.class);
+ if (reference == null) {
+ return null;
+ }
+ IBundleProjectService service = context.getService(reference);
+ if (service != null) {
+ context.ungetService(reference);
+ }
+ return service;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ResourceLocatorConfig.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ResourceLocatorConfig.java
new file mode 100644
index 0000000000..66993d6c1c
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ResourceLocatorConfig.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.resource;
+
+import static org.eclipse.jst.common.project.facet.core.internal.FacetedProjectFrameworkJavaPlugin.log;
+import org.eclipse.core.expressions.EvaluationContext;
+import org.eclipse.core.expressions.EvaluationResult;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.internal.XPointUtil;
+import org.eclipse.jpt.common.core.resource.ResourceLocator;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+public class ResourceLocatorConfig
+ implements Comparable<ResourceLocatorConfig> {
+
+ public static final String PROJECT_ENABLEMENT_VARIABLE = "project"; //$NON-NLS-1$
+
+ private String id;
+ private String pluginId;
+ private String className;
+ private Priority priority;
+ private Expression enablementCondition;
+
+
+ ResourceLocatorConfig() {
+ super();
+ }
+
+
+ public String getId() {
+ return this.id;
+ }
+
+ void setId(String id) {
+ this.id = id;
+ }
+
+ public String getPluginId() {
+ return this.pluginId;
+ }
+
+ void setPluginId(String pluginId) {
+ this.pluginId = pluginId;
+ }
+
+ public String getClassName() {
+ return this.className;
+ }
+
+ void setClassName(String className) {
+ this.className = className;
+ }
+
+ public Priority getPriority() {
+ return this.priority;
+ }
+
+ void setPriority(Priority priority) {
+ this.priority = priority;
+ }
+
+ public Expression getEnablementCondition() {
+ return this.enablementCondition;
+ }
+
+ void setEnablementCondition(Expression enablementCondition) {
+ this.enablementCondition = enablementCondition;
+ }
+
+ public ResourceLocator getResourceLocator() {
+ return XPointUtil.instantiate(
+ JptCommonCorePlugin.PLUGIN_ID, ResourceLocatorManager.QUALIFIED_EXTENSION_POINT_ID,
+ this.className, ResourceLocator.class);
+ }
+
+ public boolean isEnabledFor(IProject project) {
+ EvaluationContext evalContext = new EvaluationContext(null, project);
+ evalContext.setAllowPluginActivation(true);
+ evalContext.addVariable(PROJECT_ENABLEMENT_VARIABLE, project);
+
+ if (this.enablementCondition != null) {
+ try {
+ EvaluationResult evalResult = this.enablementCondition.evaluate(evalContext);
+
+ if (evalResult == EvaluationResult.FALSE) {
+ return false;
+ }
+ }
+ catch (CoreException e) {
+ log(e);
+ }
+ }
+
+ return true;
+ }
+
+ public int compareTo(ResourceLocatorConfig other) {
+ return Priority.compare(this.priority, other.priority);
+ }
+
+
+ public static enum Priority {
+
+ /* The lowest priority for a resource locator */
+ LOWEST(6, "lowest"), //$NON-NLS-1$
+
+ /* The second lowest priority for a resource locator */
+ LOWER(5, "lower"), //$NON-NLS-1$
+
+ /* The third lowest priority for a resource locator */
+ LOW(4, "low"), //$NON-NLS-1$
+
+ /* The default priority for a resource locator */
+ NORMAL(3, "normal"), //$NON-NLS-1$
+
+ /* The third highest priority for a resource locator */
+ HIGH(2, "high"), //$NON-NLS-1$
+
+ /* The second highest priority for a resource locator */
+ HIGHER(1, "higher"), //$NON-NLS-1$
+
+ /* The highest priority for a resource locator */
+ HIGHEST(0, "highest"); //$NON-NLS-1$
+
+
+ public static int compare(Priority priority1, Priority priority2) {
+ return priority1.value.compareTo(priority2.value);
+ }
+
+ public static Priority get(String literal) {
+ if (literal == null) {
+ return NORMAL;
+ }
+ for (Priority priority : values()) {
+ if (StringTools.stringsAreEqual(literal, priority.literal)) {
+ return priority;
+ }
+ }
+ return null;
+ }
+
+
+ private Integer value;
+ private String literal;
+
+
+ private Priority(int value, String literal) {
+ this.value = Integer.valueOf(value);
+ this.literal = literal;
+ }
+
+
+ @Override
+ public String toString() {
+ return this.literal;
+ }
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ResourceLocatorManager.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ResourceLocatorManager.java
new file mode 100644
index 0000000000..6f3ec6944f
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/ResourceLocatorManager.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.resource;
+
+import static org.eclipse.jpt.common.core.internal.XPointUtil.findRequiredAttribute;
+import static org.eclipse.jpt.common.core.internal.XPointUtil.log;
+import static org.eclipse.jpt.common.core.internal.XPointUtil.logDuplicateExtension;
+import static org.eclipse.jpt.common.core.internal.XPointUtil.logInvalidValue;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeSet;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.expressions.ExpressionConverter;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.internal.XPointUtil.XPointException;
+import org.eclipse.jpt.common.core.internal.resource.ResourceLocatorConfig.Priority;
+import org.eclipse.jpt.common.core.resource.ResourceLocator;
+import org.eclipse.jpt.utility.internal.KeyedSet;
+import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;
+
+public class ResourceLocatorManager {
+
+ public static final String EXTENSION_POINT_ID = "resourceLocators"; //$NON-NLS-1$
+ public static final String QUALIFIED_EXTENSION_POINT_ID = JptCommonCorePlugin.PLUGIN_ID_ + EXTENSION_POINT_ID;
+ public static final String RESOURCE_LOCATOR_ELEMENT = "resourceLocator"; //$NON-NLS-1$
+ public static final String ID_ATTRIBUTE = "id"; //$NON-NLS-1$
+ public static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
+ public static final String PRIORITY_ATTRIBUTE = "priority"; //$NON-NLS-1$
+ public static final String ENABLEMENT_ELEMENT = "enablement"; //$NON-NLS-1$
+
+
+ private static ResourceLocatorManager INSTANCE = new ResourceLocatorManager();
+
+
+ public static ResourceLocatorManager instance() {
+ return INSTANCE;
+ }
+
+
+ private KeyedSet<String, ResourceLocatorConfig> resourceLocatorConfigs;
+
+
+ private ResourceLocatorManager() {
+ this.resourceLocatorConfigs = new KeyedSet<String, ResourceLocatorConfig>();
+ readExtensions();
+ }
+
+
+ /**
+ * Return the {@link ResourceLocator} of highest priority that is acceptable
+ * for the given project
+ */
+ public ResourceLocator getResourceLocator(final IProject project) {
+ Iterator<ResourceLocator> stream = new FilteringIterable<ResourceLocator>(
+ new TransformationIterable<ResourceLocatorConfig, ResourceLocator>(
+ new FilteringIterable<ResourceLocatorConfig>(
+ new TreeSet<ResourceLocatorConfig>(this.resourceLocatorConfigs.getItemSet())) {
+ @Override
+ protected boolean accept(ResourceLocatorConfig o) {
+ return o.isEnabledFor(project);
+ }
+ }) {
+ @Override
+ protected ResourceLocator transform(ResourceLocatorConfig o) {
+ return o.getResourceLocator();
+ }
+ }) {
+ @Override
+ protected boolean accept(ResourceLocator o) {
+ return o != null;
+ }
+ }.iterator();
+ return (stream.hasNext()) ? stream.next() : null;
+ }
+
+ private void readExtensions() {
+ final IExtensionRegistry registry = Platform.getExtensionRegistry();
+
+ final IExtensionPoint xpoint
+ = registry.getExtensionPoint(QUALIFIED_EXTENSION_POINT_ID);
+
+ if (xpoint == null) {
+ throw new IllegalStateException();
+ }
+
+ final List<IConfigurationElement> configs = new ArrayList<IConfigurationElement>();
+
+ for (IExtension extension : xpoint.getExtensions()) {
+ for (IConfigurationElement element : extension.getConfigurationElements()) {
+ configs.add(element);
+ }
+ }
+
+ for (IConfigurationElement element : configs) {
+ if (element.getName().equals(RESOURCE_LOCATOR_ELEMENT)) {
+ readExtension(element);
+ }
+ }
+ }
+
+ private void readExtension(IConfigurationElement element) {
+ try {
+ final ResourceLocatorConfig rlConfig = new ResourceLocatorConfig();
+
+ // plug-in id
+ rlConfig.setPluginId(element.getContributor().getName());
+
+ // resource locator id
+ rlConfig.setId(findRequiredAttribute(element, ID_ATTRIBUTE));
+
+ if (this.resourceLocatorConfigs.containsKey(rlConfig.getId())) {
+ logDuplicateExtension(QUALIFIED_EXTENSION_POINT_ID, ID_ATTRIBUTE, rlConfig.getId());
+ throw new XPointException();
+ }
+
+ // resource locator class name
+ rlConfig.setClassName(findRequiredAttribute(element, CLASS_ATTRIBUTE));
+
+ // priority
+ String priorityString = element.getAttribute(PRIORITY_ATTRIBUTE).trim();
+ Priority priority = Priority.get(priorityString);
+ if (priority == null) {
+ logInvalidValue(element, PRIORITY_ATTRIBUTE, priorityString);
+ throw new XPointException();
+ }
+ rlConfig.setPriority(priority);
+
+ // enablement
+ for (IConfigurationElement child : element.getChildren()) {
+ String childName = child.getName();
+ if (childName.equals(ENABLEMENT_ELEMENT)) {
+ Expression expr;
+ try {
+ expr = ExpressionConverter.getDefault().perform(child);
+ }
+ catch (CoreException e) {
+ log(e);
+ throw new XPointException();
+ }
+ rlConfig.setEnablementCondition(expr);
+ }
+ }
+
+ this.resourceLocatorConfigs.addItem(rlConfig.getId(), rlConfig);
+ }
+ catch (XPointException e) {
+ // Ignore and continue. The problem has already been reported to the user
+ // in the log.
+ }
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/SimpleJavaResourceLocator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/SimpleJavaResourceLocator.java
new file mode 100644
index 0000000000..2050f09006
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/SimpleJavaResourceLocator.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.resource;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.internal.utility.PlatformTools;
+import org.eclipse.jpt.common.core.resource.ResourceLocator;
+import org.eclipse.jst.j2ee.internal.J2EEConstants;
+
+public class SimpleJavaResourceLocator
+ implements ResourceLocator {
+
+ protected static IPath META_INF_PATH = new Path(J2EEConstants.META_INF);
+
+ /**
+ * Simply ensure the container is either:
+ * - on the java project classpath
+ * or
+ * - in the non-java resources, but not in the project output location
+ */
+ public boolean acceptResourceLocation(IProject project, IContainer container) {
+ IJavaProject javaProject = getJavaProject(project);
+ if (javaProject.isOnClasspath(container)) {
+ return true;
+ }
+ try {
+ IPath outputLocation = javaProject.getOutputLocation();
+ if (container.equals(project) && outputLocation.isPrefixOf(container.getFullPath())) {
+ return true;
+ }
+ for (Object resource : javaProject.getNonJavaResources()) {
+ if (resource instanceof IFolder) {
+ IFolder folder = (IFolder) resource;
+ if ((folder.equals(container) || folder.contains(container))
+ && ! outputLocation.isPrefixOf(container.getFullPath())) {
+ return true;
+ }
+ }
+ }
+ }
+ catch (JavaModelException jme) {
+ JptCommonCorePlugin.log(jme);
+ // only happens if the java project doesn't exist. fall through.
+ }
+ return false;
+ }
+
+ /**
+ * Return
+ * - the first package fragment root (source folder) META-INF folder if it exists,
+ * or
+ * - the project rooted META-INF folder if it exists
+ * or
+ * - the non-existent META-INF folder in the first package fragment root (source folder)
+ */
+ public IContainer getDefaultResourceLocation(IProject project) {
+ IJavaProject javaProject = getJavaProject(project);
+ IContainer defaultLocation = null;
+ try {
+ for (IPackageFragmentRoot root : javaProject.getPackageFragmentRoots()) {
+ if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
+ IContainer rootContainer = (IContainer) root.getUnderlyingResource();
+ IFolder metaInfFolder = rootContainer.getFolder(META_INF_PATH);
+ if (metaInfFolder.exists()) {
+ return metaInfFolder;
+ }
+ if (defaultLocation == null) {
+ // hold on to this in case the META-INF folder can't be found
+ defaultLocation = metaInfFolder;
+ }
+ }
+ }
+ IFolder metaInfFolder = project.getFolder(META_INF_PATH);
+ if (metaInfFolder.exists()) {
+ return metaInfFolder;
+ }
+ }
+ catch (JavaModelException jme) {
+ // only happens if the java project doesn't exist or there is some problem with the
+ // java resources. fall through.
+ JptCommonCorePlugin.log(jme);
+ }
+
+ return defaultLocation;
+ }
+
+ public IPath getResourcePath(IProject project, IPath runtimePath) {
+ IJavaProject javaProject = getJavaProject(project);
+ IPath firstResourcePath = null;
+ try {
+ for (IPackageFragmentRoot root : javaProject.getPackageFragmentRoots()) {
+ if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
+ IContainer rootContainer = (IContainer) root.getUnderlyingResource();
+ IPath resourcePath = rootContainer.getFullPath().append(runtimePath);
+ if (firstResourcePath == null) {
+ firstResourcePath = resourcePath;
+ }
+ IFile file = project.getWorkspace().getRoot().getFile(resourcePath);
+ if (file.exists()) {
+ return file.getFullPath();
+ }
+ }
+ }
+ }
+ catch (JavaModelException jme) {
+ JptCommonCorePlugin.log(jme);
+ return null;
+ }
+ return firstResourcePath;
+ }
+
+ public IPath getRuntimePath(IProject project, IPath resourcePath) {
+ IJavaProject javaProject = getJavaProject(project);
+ IFile file = PlatformTools.getFile(resourcePath);
+ try {
+ for (IPackageFragmentRoot root : javaProject.getPackageFragmentRoots()) {
+ if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
+ IContainer rootContainer = (IContainer) root.getUnderlyingResource();
+ if (rootContainer.contains(file)) {
+ return resourcePath.makeRelativeTo(rootContainer.getFullPath());
+ }
+ }
+ }
+ }
+ catch (JavaModelException jme) {
+ // fall through
+ JptCommonCorePlugin.log(jme);
+ }
+ return resourcePath.makeRelativeTo(project.getFullPath());
+ }
+
+ private IJavaProject getJavaProject(IProject project) {
+ return JavaCore.create(project);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/WebModuleResourceLocator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/WebModuleResourceLocator.java
new file mode 100644
index 0000000000..a7fffe7e8c
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/resource/WebModuleResourceLocator.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.resource;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jst.j2ee.internal.J2EEConstants;
+import org.eclipse.wst.common.componentcore.ComponentCore;
+import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
+
+public class WebModuleResourceLocator
+ extends ModuleResourceLocator{
+
+ protected static IPath WEB_INF_CLASSES_PATH = new Path(J2EEConstants.WEB_INF_CLASSES);
+
+ /**
+ * Return the folder representing the "WEB-INF/classes/META-INF" location
+ */
+ @Override
+ public IContainer getDefaultResourceLocation(IProject project) {
+ IVirtualComponent component = ComponentCore.createComponent(project);
+ return component.getRootFolder().getFolder(WEB_INF_CLASSES_PATH.append(META_INF_PATH)).getUnderlyingFolder();
+ }
+
+ /**
+ * Return the full resource path representing the given runtime location appended
+ * to the "WEB-INF/classes" location
+ */
+ @Override
+ public IPath getResourcePath(IProject project, IPath runtimePath) {
+ return super.getResourcePath(project, WEB_INF_CLASSES_PATH.append(runtimePath));
+ }
+
+ /**
+ *
+ */
+ @Override
+ public IPath getRuntimePath(IProject project, IPath resourcePath) {
+ IPath runtimePath = super.getRuntimePath(project, resourcePath);
+ if (WEB_INF_CLASSES_PATH.isPrefixOf(runtimePath)) {
+ return runtimePath.makeRelativeTo(WEB_INF_CLASSES_PATH);
+ }
+ return runtimePath;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/CallbackJobSynchronizer.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/CallbackJobSynchronizer.java
new file mode 100644
index 0000000000..4d5b94e0cb
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/CallbackJobSynchronizer.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jpt.utility.internal.ListenerList;
+import org.eclipse.jpt.utility.synchronizers.CallbackSynchronizer;
+
+/**
+ * Extend the job synchronizer to notify listeners
+ * when a synchronization "cycle" is complete; i.e. the synchronization has,
+ * for the moment, handled every "synchronize" request and quiesced.
+ * This notification is <em>not</em> guaranteed to occur with <em>every</em>
+ * synchronization "cycle";
+ * since other, unrelated, synchronizations can be triggered concurrently;
+ * preventing the synchronization from quiescing.
+ */
+public class CallbackJobSynchronizer
+ extends JobSynchronizer
+ implements CallbackSynchronizer
+{
+ private final ListenerList<Listener> listenerList = new ListenerList<Listener>(Listener.class);
+
+
+ // ********** construction **********
+
+ /**
+ * Construct a callback job synchronizer that uses the specified job command to
+ * perform the synchronization. Assign the generated Eclipse job the
+ * specified name.
+ */
+ public CallbackJobSynchronizer(String jobName, JobCommand command) {
+ super(jobName, command);
+ }
+
+ /**
+ * Construct a callback job synchronizer that uses the specified job command to
+ * perform the synchronization. Assign the generated Eclipse job the
+ * specified name and scheduling rule.
+ */
+ public CallbackJobSynchronizer(String jobName, JobCommand command, ISchedulingRule schedulingRule) {
+ super(jobName, command, schedulingRule);
+ }
+
+ /**
+ * Build a job that will let us know when the synchronization has
+ * quiesced.
+ */
+ @Override
+ SynchronizationJob buildJob(String jobName, JobCommand command, ISchedulingRule schedulingRule) {
+ return new CallbackSynchronizationJob(jobName, command, schedulingRule);
+ }
+
+
+ // ********** CallbackSynchronizer implementation **********
+
+ public void addListener(Listener listener) {
+ this.listenerList.add(listener);
+ }
+
+ public void removeListener(Listener listener) {
+ this.listenerList.remove(listener);
+ }
+
+ /**
+ * Notify our listeners.
+ */
+ void synchronizationQuiesced() {
+ for (Listener listener : this.listenerList.getListeners()) {
+ listener.synchronizationQuiesced(this);
+ }
+ }
+
+
+ // ********** synchronization job **********
+
+ /**
+ * Extend {@link JobSynchronizer.SynchronizationJob}
+ * to notify the synchronizer when the synchronization has quiesced
+ * (i.e. the command has finished executing and there are no further
+ * requests for synchronization).
+ * Because synchronization occurs during the job's execution,
+ * no other thread will be able to
+ * initiate another synchronization until the synchronizer's listeners have been
+ * notified. Note also, the synchronizer's listeners can, themselves,
+ * trigger another synchronization (by directly or indirectly calling
+ * {@link org.eclipse.jpt.utility.synchronizers.Synchronizer#synchronize()});
+ * but this synchronization will not occur until <em>after</em> all the
+ * listeners have been notified.
+ */
+ class CallbackSynchronizationJob
+ extends SynchronizationJob
+ {
+ /**
+ * When this flag is set to true, the job has been scheduled to run.
+ * We need this because {@link org.eclipse.core.runtime.jobs.Job Job}
+ * has no public API for discovering whether a job is "scheduled".
+ */
+ // use 'volatile' because synchronization isn't really required
+ private volatile boolean scheduled;
+
+
+ CallbackSynchronizationJob(String jobName, JobCommand command, ISchedulingRule schedulingRule) {
+ super(jobName, command, schedulingRule);
+ this.scheduled = false;
+ }
+
+ /**
+ * If we are allowing the job to be scheduled (i.e. {@link #start()}
+ * was called), set the "scheduled" flag.
+ */
+ @Override
+ void synchronize() {
+ if (this.shouldSchedule) {
+ this.scheduled = true;
+ }
+ super.synchronize();
+ }
+
+ /**
+ * Clear the "scheduled" flag; perform the synchronization; and,
+ * if the "scheduled" flag is still clear (i.e. there have been no
+ * further calls to {@link #synchronize()}), notify our listeners.
+ */
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ this.scheduled = false;
+ IStatus status = super.run(monitor);
+ // hmmm - we will notify listeners even when we our job is "stopped";
+ // that seems ok... ~bjv
+ if ( ! this.scheduled) {
+ CallbackJobSynchronizer.this.synchronizationQuiesced();
+ }
+ return status;
+ }
+
+ @Override
+ void stop() {
+ this.scheduled = false;
+ super.stop();
+ }
+
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/JobCommand.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/JobCommand.java
new file mode 100644
index 0000000000..0a46bb470d
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/JobCommand.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility;
+
+import java.io.Serializable;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Simple interface for implementing the GOF Command design pattern in an
+ * Eclipse job.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ */
+public interface JobCommand {
+
+ /**
+ * Execute the command. The semantics of the command
+ * is determined by the contract between the client and server.
+ * The command should check, as appropriate, whether the specified progress
+ * monitor is {@link IProgressMonitor#isCanceled() "canceled"}; if it is,
+ * the command should throw an
+ * {@link org.eclipse.core.runtime.OperationCanceledException OperationCanceledException}.
+ * @see IProgressMonitor#isCanceled()
+ */
+ IStatus execute(IProgressMonitor monitor);
+
+ /**
+ * Singleton implementation of the job command interface that will do
+ * nothing when executed.
+ */
+ final class Null implements JobCommand, Serializable {
+ public static final JobCommand INSTANCE = new Null();
+ public static JobCommand instance() {
+ return INSTANCE;
+ }
+ // ensure single instance
+ private Null() {
+ super();
+ }
+ public IStatus execute(IProgressMonitor arg0) {
+ return Status.OK_STATUS;
+ }
+ @Override
+ public String toString() {
+ return "JobCommand.Null"; //$NON-NLS-1$
+ }
+ private static final long serialVersionUID = 1L;
+ private Object readResolve() {
+ // replace this object with the singleton
+ return INSTANCE;
+ }
+ }
+
+ /**
+ * Singleton implementation of the job command interface that will throw an
+ * exception when executed.
+ */
+ final class Disabled implements JobCommand, Serializable {
+ public static final JobCommand INSTANCE = new Disabled();
+ public static JobCommand instance() {
+ return INSTANCE;
+ }
+ // ensure single instance
+ private Disabled() {
+ super();
+ }
+ // throw an exception
+ public IStatus execute(IProgressMonitor arg0) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public String toString() {
+ return "JobCommand.Disabled"; //$NON-NLS-1$
+ }
+ private static final long serialVersionUID = 1L;
+ private Object readResolve() {
+ // replace this object with the singleton
+ return INSTANCE;
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/JobSynchronizer.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/JobSynchronizer.java
new file mode 100644
index 0000000000..1fbe59a5d8
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/JobSynchronizer.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.jpt.utility.synchronizers.Synchronizer;
+
+/**
+ * This synchronizer will perform synchronizations in an Eclipse job on a
+ * separate thread, allowing calls to {@link Synchronizer#synchronize()}
+ * to return immediately.
+ * <p>
+ * If necessary, the client-supplied job command should handle any
+ * exceptions appropriately. Although, the default exception-handling provided
+ * by the Eclipse Job Framework is probably adequate in most cases:<ul>
+ * <li>An {@link org.eclipse.core.runtime.OperationCanceledException OperationCanceledException}
+ * results in a {@link org.eclipse.core.runtime.Status#CANCEL_STATUS CANCEL_STATUS}.
+ * <li>Any non-{@link ThreadDeath} {@link Throwable}
+ * results in a {@link org.eclipse.core.runtime.IStatus#ERROR ERROR}
+ * {@link org.eclipse.core.runtime.IStatus IStatus}
+ * </ul>
+ * @see org.eclipse.core.internal.jobs.Worker#run()
+ */
+public class JobSynchronizer
+ implements Synchronizer
+{
+ /**
+ * The synchronization is performed by this job. The same job is used
+ * for every start/stop cycle (since a job can be re-started).
+ */
+ private final SynchronizationJob job;
+
+
+ // ********** construction **********
+
+ /**
+ * Construct a job synchronizer that uses the specified job command to
+ * perform the synchronization. Assign the generated Eclipse job the
+ * specified name.
+ */
+ public JobSynchronizer(String jobName, JobCommand command) {
+ this(jobName, command, null);
+ }
+
+ /**
+ * Construct a job synchronizer that uses the specified job command to
+ * perform the synchronization. Assign the generated Eclipse job the
+ * specified name and scheduling rule.
+ */
+ public JobSynchronizer(String jobName, JobCommand command, ISchedulingRule schedulingRule) {
+ super();
+ this.job = this.buildJob(jobName, command, schedulingRule);
+ }
+
+ SynchronizationJob buildJob(String jobName, JobCommand command, ISchedulingRule schedulingRule) {
+ return new SynchronizationJob(jobName, command, schedulingRule);
+ }
+
+
+ // ********** Synchronizer implementation **********
+
+ /**
+ * Allow the job to be scheduled, but postpone the first synchronization
+ * until requested, via {@link #synchronize()}.
+ */
+ public void start() {
+ this.job.start();
+ }
+
+ /**
+ * "Schedule" the job.
+ */
+ public void synchronize() {
+ this.job.synchronize();
+ }
+
+ /**
+ * Wait for the current job execution to complete.
+ */
+ public void stop() {
+ this.job.stop();
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.job);
+ }
+
+
+ // ********** synchronization job **********
+
+ /**
+ * This is the job that gets scheduled by the job synchronizer.
+ * When the job is run it executes the client-supplied job command.
+ */
+ static class SynchronizationJob extends Job {
+ /**
+ * The client-supplied job command that executes every time the job
+ * runs.
+ */
+ private final JobCommand command;
+
+ /**
+ * When this flag is set to false, the job does not stop immediately;
+ * but it will not be scheduled to run again.
+ */
+ // use 'volatile' because synchronization isn't really required
+ volatile boolean shouldSchedule;
+
+
+ SynchronizationJob(String jobName, JobCommand command, ISchedulingRule schedulingRule) {
+ super(jobName);
+ if (command == null) {
+ throw new NullPointerException();
+ }
+ this.command = command;
+ this.shouldSchedule = false;
+ this.setRule(schedulingRule);
+ }
+
+ /**
+ * Just set the "should schedule" flag so the job <em>can</em> be
+ * scheduled; but don't actually schedule it.
+ */
+ void start() {
+ if (this.shouldSchedule) {
+ throw new IllegalStateException("The Synchronizer was not stopped."); //$NON-NLS-1$
+ }
+ this.shouldSchedule = true;
+ }
+
+ /**
+ * Simply re-schedule the job, allowing the current execution
+ * to run to completion (i.e. do not try to cancel it prematurely).
+ * This should minimize the number of times the job is re-executed
+ * (recursively and otherwise).
+ */
+ void synchronize() {
+ this.schedule();
+ }
+
+ /**
+ * Any uncaught exceptions thrown by the command will be reasonably
+ * handled by the Job Framework.
+ * @see org.eclipse.core.internal.jobs.Worker#run()
+ */
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ return this.command.execute(monitor);
+ }
+
+ /**
+ * Prevent the job from running again and wait for the current
+ * execution, if there is any, to end before returning.
+ */
+ void stop() {
+ if ( ! this.shouldSchedule) {
+ throw new IllegalStateException("The Synchronizer was not started."); //$NON-NLS-1$
+ }
+ // this will prevent the job from being scheduled to run again
+ this.shouldSchedule = false;
+ // this will cancel the job if it has already been scheduled, but is currently WAITING
+ this.cancel();
+ try {
+ // if the job is currently RUNNING, wait until it is done before returning
+ this.join();
+ } catch (InterruptedException ex) {
+ // the thread that called #stop() was interrupted while waiting to
+ // join the synchronization job - ignore;
+ // 'shouldSchedule' is still set to 'false', so the job loop will still stop - we
+ // just won't wait around for it...
+ }
+ }
+
+ /**
+ * This is part of the normal {@link Job} behavior. By default, it is
+ * not used (i.e. it always returns <code>true</code>).
+ * We implement it here.
+ */
+ @Override
+ public boolean shouldSchedule() {
+ return this.shouldSchedule;
+ }
+
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/PlatformTools.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/PlatformTools.java
new file mode 100644
index 0000000000..6981696e0d
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/PlatformTools.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility;
+
+import java.io.IOException;
+import java.io.InputStream;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.content.IContentTypeManager;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+
+/**
+ * A collection of utilities for dealing with the Eclipse platform API.
+ */
+public class PlatformTools {
+
+ /**
+ * Return the {@link IContainer} with the workspace relative "full" path
+ */
+ public static IContainer getContainer(IPath fullContainerPath) {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ return root.getContainerForLocation(root.getLocation().append(fullContainerPath));
+ }
+
+ /**
+ * Return the {@link IFile} with the workspace relative "full" path
+ */
+ public static IFile getFile(IPath fullFilePath) {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ return root.getFileForLocation(root.getLocation().append(fullFilePath));
+ }
+
+ /**
+ * Return the specified file's content type,
+ * using the Eclipse platform's content type manager.
+ */
+ public static IContentType getContentType(IFile file) {
+ String fileName = file.getName();
+ InputStream fileContents = null;
+ try {
+ fileContents = file.getContents();
+ } catch (CoreException ex) {
+ // seems like we can ignore any exception that might occur here;
+ // e.g. we get a FNFE if the workspace is out of synch with the O/S file system
+ // JptCorePlugin.log(ex);
+
+ // look for content type based on the file name only(?)
+ return findContentTypeFor(fileName);
+ }
+
+ IContentType contentType = null;
+ try {
+ contentType = findContentTypeFor(fileContents, fileName);
+ } catch (IOException ex) {
+ JptCommonCorePlugin.log(ex);
+ } finally {
+ try {
+ fileContents.close();
+ } catch (IOException ex) {
+ JptCommonCorePlugin.log(ex);
+ }
+ }
+ return contentType;
+ }
+
+ private static IContentType findContentTypeFor(InputStream fileContents, String fileName) throws IOException {
+ return getContentTypeManager().findContentTypeFor(fileContents, fileName);
+ }
+
+ private static IContentType findContentTypeFor(String fileName) {
+ return getContentTypeManager().findContentTypeFor(fileName);
+ }
+
+ private static IContentTypeManager getContentTypeManager() {
+ return Platform.getContentTypeManager();
+ }
+
+ private PlatformTools() {
+ super();
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/SimpleSchedulingRule.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/SimpleSchedulingRule.java
new file mode 100644
index 0000000000..e0fa369de8
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/SimpleSchedulingRule.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility;
+
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * A job scheduling rule that conflicts only with itself.
+ */
+public final class SimpleSchedulingRule
+ implements ISchedulingRule
+{
+ public SimpleSchedulingRule() {
+ super();
+ }
+
+ public boolean contains(ISchedulingRule rule) {
+ return rule == this;
+ }
+
+ public boolean isConflicting(ISchedulingRule rule) {
+ return rule == this;
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/SimpleTextRange.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/SimpleTextRange.java
new file mode 100644
index 0000000000..f7d5dc90a1
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/SimpleTextRange.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility;
+
+import org.eclipse.jpt.common.core.utility.AbstractTextRange;
+
+/**
+ * Straightforward implementation of TextRange.
+ */
+public class SimpleTextRange extends AbstractTextRange {
+ private final int offset;
+ private final int length;
+ private final int lineNumber;
+
+ public SimpleTextRange(int offset, int length, int lineNumber) {
+ super();
+ this.offset = offset;
+ this.length = length;
+ this.lineNumber = lineNumber;
+ }
+
+ public int getOffset() {
+ return this.offset;
+ }
+
+ public int getLength() {
+ return this.length;
+ }
+
+ public int getLineNumber() {
+ return this.lineNumber;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ASTNodeTextRange.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ASTNodeTextRange.java
new file mode 100644
index 0000000000..1d44f9fcdb
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ASTNodeTextRange.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.AbstractTextRange;
+
+/**
+ * Adapt an ASTNode to the TextRange interface.
+ */
+public class ASTNodeTextRange extends AbstractTextRange {
+ private final ASTNode astNode;
+
+ public ASTNodeTextRange(ASTNode astNode) {
+ super();
+ this.astNode = astNode;
+ }
+
+ public int getOffset() {
+ return this.astNode.getStartPosition();
+ }
+
+ public int getLength() {
+ return this.astNode.getLength();
+ }
+
+ public int getLineNumber() {
+ return ((CompilationUnit) this.astNode.getRoot()).getLineNumber(this.getOffset());
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ASTTools.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ASTTools.java
new file mode 100644
index 0000000000..205244291c
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ASTTools.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.HashSet;
+import java.util.List;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.IAnnotationBinding;
+import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.TypeLiteral;
+import org.eclipse.jpt.utility.JavaType;
+import org.eclipse.jpt.utility.MethodSignature;
+import org.eclipse.jpt.utility.internal.SimpleJavaType;
+import org.eclipse.jpt.utility.internal.SimpleMethodSignature;
+
+/**
+ * Convenience methods for dealing with JDT ASTs.
+ */
+public class ASTTools {
+
+ /**
+ * Build an AST without method bodies for the specified compilation unit
+ * with its bindings resolved (and the resultant performance hit).
+ */
+ public static CompilationUnit buildASTRoot(ICompilationUnit compilationUnit) {
+ ASTParser parser = ASTParser.newParser(AST.JLS3);
+ parser.setSource(compilationUnit);
+ parser.setIgnoreMethodBodies(true); // we don't need method bodies
+ parser.setResolveBindings(true);
+ parser.setBindingsRecovery(true); // see bugs 196200, 222735
+ return (CompilationUnit) parser.createAST(null);
+ }
+
+
+ // ********** JDT DOM **********
+
+ public static String resolveEnum(Expression expression) {
+ if (expression == null) {
+ return null;
+ }
+ switch (expression.getNodeType()) {
+ case ASTNode.QUALIFIED_NAME:
+ case ASTNode.SIMPLE_NAME:
+ return resolveEnum((Name) expression);
+ default:
+ return null;
+ }
+ }
+
+ public static String resolveEnum(Name enumExpression) {
+ IBinding binding = enumExpression.resolveBinding();
+ if (binding == null) {
+ return null; // TODO figure out why this is null sometimes
+ }
+ if (binding.getKind() != IBinding.VARIABLE) {
+ return null;
+ }
+ IVariableBinding variableBinding = (IVariableBinding) binding;
+ return variableBinding.getType().getQualifiedName() + '.' + variableBinding.getName();
+ }
+
+ /**
+ * Return the fully-qualified name of the specified node's annotation
+ * class.
+ */
+ public static String resolveAnnotation(Annotation node) {
+ IAnnotationBinding annotationBinding = node.resolveAnnotationBinding();
+ if (annotationBinding == null) {
+ return null;
+ }
+ ITypeBinding annotationTypeBinding = annotationBinding.getAnnotationType();
+ return (annotationTypeBinding == null) ? null : annotationTypeBinding.getQualifiedName();
+ }
+
+ /**
+ * If the specified expression is a type literal, return the type's fully-
+ * qualified name. Return null otherwise.
+ */
+ public static String resolveFullyQualifiedName(Expression expression) {
+ ITypeBinding resolvedTypeBinding = resolveTypeBinding(expression);
+ return (resolvedTypeBinding == null) ? null : resolvedTypeBinding.getQualifiedName();
+ }
+
+ /**
+ * If the specified expression is a type literal, return the corresponding
+ * type binding.
+ */
+ public static ITypeBinding resolveTypeBinding(Expression expression) {
+ if (expression.getNodeType() == ASTNode.TYPE_LITERAL) {
+ return ((TypeLiteral) expression).getType().resolveBinding();
+ }
+ return null;
+ }
+
+ public static MethodSignature buildMethodSignature(MethodDeclaration methodDeclaration) {
+ return new SimpleMethodSignature(
+ methodDeclaration.getName().getFullyQualifiedName(),
+ buildParameterTypes(methodDeclaration)
+ );
+ }
+
+ public static JavaType[] buildParameterTypes(MethodDeclaration methodDeclaration) {
+ List<SingleVariableDeclaration> parameters = parameters(methodDeclaration);
+ int len = parameters.size();
+ JavaType[] parameterTypes = new JavaType[len];
+ for (int i = 0; i < len; i++) {
+ ITypeBinding type = parameters.get(i).getType().resolveBinding();
+ parameterTypes[i] = new SimpleJavaType(type.getQualifiedName(), type.getDimensions());
+ }
+ return parameterTypes;
+ }
+
+ // minimize scope of suppressed warnings
+ @SuppressWarnings("unchecked")
+ private static List<SingleVariableDeclaration> parameters(MethodDeclaration methodDeclaration) {
+ return methodDeclaration.parameters();
+ }
+
+ /**
+ * Return whether the specified expression is a type literal and the type binding
+ * corresponding to the specified type name exists in the type
+ * literal's inheritance hierarchy (superclasses and interfaces).
+ * Return null otherwise.
+ */
+ public static boolean typeIsSubTypeOf(Expression expression, String searchTypeName) {
+ return findTypeInHierarchy(expression, searchTypeName) != null;
+ }
+
+ /**
+ * If the specified expression is a type literal, return the type binding
+ * corresponding to the specified type name if it exists in the type
+ * literal's inheritance hierarchy (superclasses and interfaces).
+ * Return null otherwise.
+ */
+ public static ITypeBinding findTypeInHierarchy(Expression expression, String searchTypeName) {
+ ITypeBinding typeBinding = resolveTypeBinding(expression);
+ return (typeBinding == null) ? null : findTypeInHierarchy(typeBinding, searchTypeName);
+ }
+
+ /**
+ * Return whether a type binding with the specified type name exists in
+ * the specified type binding's inheritance hierarchy (superclasses
+ * and interfaces).
+ */
+ public static boolean typeIsSubTypeOf(ITypeBinding typeBinding, String searchTypeName) {
+ return findTypeInHierarchy(typeBinding, searchTypeName) != null;
+ }
+
+ /**
+ * Return the type binding corresponding to the specified type name if it
+ * exists in the specified type binding's inheritance hierarchy (superclasses
+ * and interfaces). Return null otherwise.
+ */
+ public static ITypeBinding findTypeInHierarchy(ITypeBinding typeBinding, String searchTypeName) {
+ return findTypeInHierarchy(typeBinding, searchTypeName, new HashSet<String>());
+ }
+
+ private static ITypeBinding findTypeInHierarchy(ITypeBinding typeBinding, String searchTypeName, HashSet<String> visited) {
+ String typeName = typeBinding.getQualifiedName();
+ if (visited.contains(typeName)) {
+ return null;
+ }
+ if (typeName.equals(searchTypeName)) {
+ return typeBinding;
+ }
+ visited.add(typeName);
+
+ ITypeBinding interfaceBinding = findTypeInInterfaces(typeBinding, searchTypeName, visited);
+ if (interfaceBinding != null) {
+ return interfaceBinding;
+ }
+
+ return findTypeInSuperclasses(typeBinding, searchTypeName, visited);
+ }
+
+ private static ITypeBinding findTypeInInterfaces(ITypeBinding typeBinding, String searchTypeName, HashSet<String> visited) {
+ ITypeBinding[] interfaceBindings = typeBinding.getInterfaces();
+ for (ITypeBinding interfaceBinding : interfaceBindings) { // recurse up interfaces
+ ITypeBinding result = findTypeInHierarchy(interfaceBinding, searchTypeName, visited);
+ if (result != null) {
+ return result;
+ }
+ }
+ return null;
+ }
+
+ private static ITypeBinding findTypeInSuperclasses(ITypeBinding typeBinding, String searchTypeName, HashSet<String> visited) {
+ ITypeBinding superBinding = typeBinding.getSuperclass();
+ if (superBinding != null) { // recurse up superclasses
+ ITypeBinding result = findTypeInHierarchy(superBinding, searchTypeName, visited);
+ if (result != null) {
+ return result;
+ }
+ }
+ return null;
+ }
+ /**
+ * Return whether the specified expression is a type literal and the type binding
+ * corresponding to the specified interface name exists in the type
+ * literal's inheritance hierarchy (superclasses and interfaces).
+ * Return null otherwise.
+ */
+ public static boolean typeImplementsInterface(Expression expression, String searchInterfaceName) {
+ ITypeBinding typeBinding = resolveTypeBinding(expression);
+ if (typeBinding == null) {
+ return false;
+ }
+ return findInterfaceInHierarchy(typeBinding, searchInterfaceName) != null;
+ }
+
+ /**
+ * Return whether a type binding with the specified interface name exists in
+ * the specified type binding's inheritance hierarchy (superclasses
+ * and interfaces).
+ */
+ public static boolean typeImplementsInterface(ITypeBinding typeBinding, String searchInterfaceName) {
+ return findInterfaceInHierarchy(typeBinding, searchInterfaceName) != null;
+ }
+
+ private static ITypeBinding findInterfaceInHierarchy(ITypeBinding typeBinding, String searchInterfaceName) {
+ HashSet<String> visited = new HashSet<String>();
+ ITypeBinding interfaceBinding = findTypeInInterfaces(typeBinding, searchInterfaceName, visited);
+ if (interfaceBinding != null) {
+ return interfaceBinding;
+ }
+
+ return findTypeInSuperclasses(typeBinding, searchInterfaceName, visited);
+
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractAnnotationAdapter.java
new file mode 100644
index 0000000000..80d5c3e376
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractAnnotationAdapter.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotatedElement;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Adapt an annotated element and a declaration annotation adapter.
+ */
+public abstract class AbstractAnnotationAdapter implements AnnotationAdapter {
+ private final AnnotatedElement annotatedElement;
+ private final DeclarationAnnotationAdapter daa;
+
+
+ // ********** constructor **********
+
+ public AbstractAnnotationAdapter(AnnotatedElement annotatedElement, DeclarationAnnotationAdapter daa) {
+ super();
+ this.annotatedElement = annotatedElement;
+ this.daa = daa;
+ }
+
+
+ // ********** AnnotationAdapter implementation **********
+
+ public Annotation getAnnotation(CompilationUnit astRoot) {
+ return this.daa.getAnnotation(this.annotatedElement.getModifiedDeclaration(astRoot));
+ }
+
+ public void newMarkerAnnotation() {
+ this.edit(this.buildNewMarkerAnnotationEditor());
+ }
+
+ public void newSingleMemberAnnotation() {
+ this.edit(this.buildNewSingleMemberAnnotationEditor());
+ }
+
+ public void newNormalAnnotation() {
+ this.edit(this.buildNewNormalAnnotationEditor());
+ }
+
+ public void removeAnnotation() {
+ this.edit(this.buildRemoveAnnotationEditor());
+ }
+
+ public ASTNode getAstNode(CompilationUnit astRoot) {
+ return this.daa.getAstNode(this.annotatedElement.getModifiedDeclaration(astRoot));
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.daa);
+ }
+
+
+ // ********** internal methods **********
+
+ protected void edit(AnnotatedElement.Editor editor) {
+ this.annotatedElement.edit(editor);
+ }
+
+
+ // ********** factory methods **********
+
+ protected AnnotatedElement.Editor buildNewMarkerAnnotationEditor() {
+ return new NewMarkerAnnotationEditor(this.daa);
+ }
+
+ protected AnnotatedElement.Editor buildNewSingleMemberAnnotationEditor() {
+ return new NewSingleMemberAnnotationEditor(this.daa);
+ }
+
+ protected AnnotatedElement.Editor buildNewNormalAnnotationEditor() {
+ return new NewNormalAnnotationEditor(this.daa);
+ }
+
+ protected AnnotatedElement.Editor buildRemoveAnnotationEditor() {
+ return new RemoveAnnotationEditor(this.daa);
+ }
+
+
+ // ********** member classes **********
+
+ protected static class NewMarkerAnnotationEditor implements AnnotatedElement.Editor {
+ private final DeclarationAnnotationAdapter daa;
+
+ NewMarkerAnnotationEditor(DeclarationAnnotationAdapter daa) {
+ super();
+ this.daa = daa;
+ }
+ public void edit(ModifiedDeclaration declaration) {
+ this.daa.newMarkerAnnotation(declaration);
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+ }
+
+
+ protected static class NewSingleMemberAnnotationEditor implements AnnotatedElement.Editor {
+ private final DeclarationAnnotationAdapter daa;
+
+ NewSingleMemberAnnotationEditor(DeclarationAnnotationAdapter daa) {
+ super();
+ this.daa = daa;
+ }
+ public void edit(ModifiedDeclaration declaration) {
+ this.daa.newSingleMemberAnnotation(declaration);
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+ }
+
+
+ protected static class NewNormalAnnotationEditor implements AnnotatedElement.Editor {
+ private final DeclarationAnnotationAdapter daa;
+
+ NewNormalAnnotationEditor(DeclarationAnnotationAdapter daa) {
+ super();
+ this.daa = daa;
+ }
+ public void edit(ModifiedDeclaration declaration) {
+ this.daa.newNormalAnnotation(declaration);
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+ }
+
+
+ protected static class RemoveAnnotationEditor implements AnnotatedElement.Editor {
+ private final DeclarationAnnotationAdapter daa;
+
+ RemoveAnnotationEditor(DeclarationAnnotationAdapter daa) {
+ super();
+ this.daa = daa;
+ }
+ public void edit(ModifiedDeclaration declaration) {
+ this.daa.removeAnnotation(declaration);
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractDeclarationAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractDeclarationAnnotationAdapter.java
new file mode 100644
index 0000000000..9c3520d5ca
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractDeclarationAnnotationAdapter.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.List;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.MarkerAnnotation;
+import org.eclipse.jdt.core.dom.MemberValuePair;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ *
+ */
+public abstract class AbstractDeclarationAnnotationAdapter implements DeclarationAnnotationAdapter {
+ private final String annotationName;
+
+
+ // ********** constructors **********
+
+ protected AbstractDeclarationAnnotationAdapter(String annotationName) {
+ super();
+ this.annotationName = annotationName;
+ }
+
+
+ // ********** DeclarationAnnotationAdapter implementation **********
+
+ public MarkerAnnotation newMarkerAnnotation(ModifiedDeclaration declaration) {
+ MarkerAnnotation annotation = this.newMarkerAnnotation(declaration.getAst());
+ this.addAnnotationAndImport(declaration, annotation);
+ return annotation;
+ }
+
+ public SingleMemberAnnotation newSingleMemberAnnotation(ModifiedDeclaration declaration) {
+ SingleMemberAnnotation annotation = this.newSingleMemberAnnotation(declaration.getAst());
+ this.addAnnotationAndImport(declaration, annotation);
+ return annotation;
+ }
+
+ public NormalAnnotation newNormalAnnotation(ModifiedDeclaration declaration) {
+ NormalAnnotation annotation = this.newNormalAnnotation(declaration.getAst());
+ this.addAnnotationAndImport(declaration, annotation);
+ return annotation;
+ }
+
+ /**
+ * Add the appropriate import statement, then shorten the annotation's
+ * name before adding it to the declaration.
+ */
+ protected void addAnnotationAndImport(ModifiedDeclaration declaration, Annotation annotation) {
+ annotation.setTypeName(declaration.getAst().newName(this.getSourceCodeAnnotationName(declaration)));
+ this.addAnnotation(declaration, annotation);
+ }
+
+ /**
+ * Return the annotation's name as it can be used in source code;
+ * i.e. if we can add it to the compilation unit's imports, return the short
+ * name; if we can't (because of a collision), return the fully-qualified name.
+ * NB: an import may be added as a side-effect :-(
+ */
+ protected String getSourceCodeAnnotationName(ModifiedDeclaration declaration) {
+ return declaration.addImport(this.annotationName) ? this.getShortAnnotationName() : this.annotationName;
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.annotationName);
+ }
+
+ /**
+ * Add the specified annotation to the specified declaration,
+ * replacing the original annotation if present.
+ */
+ protected abstract void addAnnotation(ModifiedDeclaration declaration, Annotation annotation);
+
+
+ // ********** public methods **********
+
+ /**
+ * This is 'public' because we use it in CombinationIndexedDeclarationAnnotationAdapter
+ * to get the annotation name from a NestedIndexedDeclarationAnnotationAdapter.
+ */
+ public String getAnnotationName() {
+ return this.annotationName;
+ }
+
+
+ // ********** helper methods **********
+
+ protected boolean nameMatches(ModifiedDeclaration declaration, Annotation annotation) {
+ return this.nameMatches(declaration, annotation, this.annotationName);
+ }
+
+ protected boolean nameMatches(ModifiedDeclaration declaration, Annotation annotation, String name) {
+ return declaration.annotationIsNamed(annotation, name);
+ }
+
+ protected MarkerAnnotation newMarkerAnnotation(AST ast) {
+ return this.newMarkerAnnotation(ast, this.annotationName);
+ }
+
+ protected MarkerAnnotation newMarkerAnnotation(AST ast, String name) {
+ MarkerAnnotation annotation = ast.newMarkerAnnotation();
+ annotation.setTypeName(ast.newName(name));
+ return annotation;
+ }
+
+ protected SingleMemberAnnotation newSingleMemberAnnotation(AST ast) {
+ return this.newSingleMemberAnnotation(ast, this.annotationName);
+ }
+
+ protected SingleMemberAnnotation newSingleMemberAnnotation(AST ast, String name) {
+ SingleMemberAnnotation annotation = ast.newSingleMemberAnnotation();
+ annotation.setTypeName(ast.newName(name));
+ return annotation;
+ }
+
+ protected NormalAnnotation newNormalAnnotation(AST ast) {
+ return this.newNormalAnnotation(ast, this.annotationName);
+ }
+
+ protected NormalAnnotation newNormalAnnotation(AST ast, String name) {
+ NormalAnnotation annotation = ast.newNormalAnnotation();
+ annotation.setTypeName(ast.newName(name));
+ return annotation;
+ }
+
+ protected String getShortAnnotationName() {
+ return convertToShortName(this.annotationName);
+ }
+
+ protected static String convertToShortName(String name) {
+ return name.substring(name.lastIndexOf('.') + 1);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected List<MemberValuePair> values(NormalAnnotation na) {
+ return na.values();
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractExpressionConverter.java
new file mode 100644
index 0000000000..2f7a571fd6
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractExpressionConverter.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Gather together the common implementation behavior.
+ * T is the type of the object to be converted to and from an expression.
+ *
+ * We're still figuring out Java Generics here.... The methods in this abstract
+ * class work fine with any subclass of Expression E; but a ClassCastException
+ * will occur as soon as we call any method implemented by a subclass
+ * (e.g. StringExpressionConverter) that expects a particular subclass of
+ * Expression (e.g. StringLiteral).
+ */
+public abstract class AbstractExpressionConverter<T>
+ implements ExpressionConverter<T>
+{
+
+ protected AbstractExpressionConverter() {
+ super();
+ }
+
+
+ // ********** object -> expression **********
+
+ public Expression convert(T object, AST ast) {
+ return (object == null) ? this.convertNull(ast) : this.convertObject(object, ast);
+ }
+
+ /**
+ * Return the expression for a null object. By default, a null object will
+ * be converted into a null expression.
+ */
+ protected Expression convertNull(@SuppressWarnings("unused") AST ast) {
+ return null;
+ }
+
+ /**
+ * The specified object is not null.
+ * @see #convert(Object, AST)
+ */
+ protected abstract Expression convertObject(T object, AST ast);
+
+
+ // ********** expression -> object **********
+
+ public T convert(Expression expression) {
+ return (expression == null) ? this.convertNull() : this.convertExpression(expression);
+ }
+
+ /**
+ * Return the object for a null expression. By default, a null expression will
+ * be converted into a null object.
+ */
+ protected T convertNull() {
+ return null;
+ }
+
+ /**
+ * The specified expression is not null.
+ * @see #convert(Expression)
+ */
+ protected abstract T convertExpression(Expression expression);
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractJDTType.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractJDTType.java
new file mode 100644
index 0000000000..9f5035da49
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractJDTType.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
+import org.eclipse.jdt.core.dom.BodyDeclaration;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.core.utility.jdt.AbstractType;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.jpt.common.core.utility.jdt.Type;
+import org.eclipse.jpt.utility.CommandExecutor;
+
+/**
+ * Adapt and extend a JDT abstract type.
+ */
+public abstract class AbstractJDTType
+ extends JDTMember
+ implements AbstractType
+{
+
+ /**
+ * constructor for the compilation unit's primary type
+ */
+ protected AbstractJDTType(
+ AbstractTypeDeclaration typeDeclaration,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(typeDeclaration, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ /**
+ * constructor for the compilation unit's primary type
+ */
+ protected AbstractJDTType(
+ AbstractTypeDeclaration typeDeclaration,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ this(null, typeDeclaration, 1, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ /**
+ * constructor for nested types
+ */
+ protected AbstractJDTType(
+ Type declaringType,
+ AbstractTypeDeclaration typeDeclaration,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(declaringType, typeDeclaration, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ /**
+ * constructor for nested types
+ */
+ protected AbstractJDTType(
+ Type declaringType,
+ AbstractTypeDeclaration typeDeclaration,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super(declaringType, typeDeclaration.getName().getFullyQualifiedName(), occurrence, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ /**
+ * constructor for testing
+ */
+ protected AbstractJDTType(Type declaringType, String name, int occurrence, ICompilationUnit compilationUnit) {
+ super(declaringType, name, occurrence, compilationUnit, CommandExecutor.Default.instance(), DefaultAnnotationEditFormatter.instance());
+ }
+
+ @Override
+ protected Type getDeclaringType() {
+ return (Type) super.getDeclaringType();
+ }
+
+ // ********** Member/Type implementation **********
+
+ public ITypeBinding getBinding(CompilationUnit astRoot) {
+ AbstractTypeDeclaration td = this.getBodyDeclaration(astRoot);
+ return (td == null) ? null : td.resolveBinding();
+ }
+
+ /**
+ * find the type's body declaration in the specified AST
+ */
+ @Override
+ public AbstractTypeDeclaration getBodyDeclaration(CompilationUnit astRoot) {
+ Type declaringType = this.getDeclaringType();
+ if (declaringType == null) {
+ return this.getTopLevelTypeDeclaration(astRoot);
+ }
+ TypeDeclaration typeDeclaration = declaringType.getBodyDeclaration(astRoot);
+ // the type declaration can be null when the source is completely hosed
+ return (typeDeclaration == null) ? null : this.getNestedTypeDeclaration(typeDeclaration);
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ return new ASTNodeTextRange(this.getBodyDeclaration(astRoot).getName());
+ }
+
+
+ // ********** internal **********
+
+ /**
+ * return the first top-level type in the specified AST with a matching name
+ */
+ protected AbstractTypeDeclaration getTopLevelTypeDeclaration(CompilationUnit astRoot) {
+ return this.getTypeDeclaration(types(astRoot));
+ }
+
+ protected AbstractTypeDeclaration getTypeDeclaration(List<AbstractTypeDeclaration> typeDeclarations) {
+ return this.getTypeDeclaration(typeDeclarations.toArray(new AbstractTypeDeclaration[typeDeclarations.size()]));
+ }
+
+ /**
+ * Return the nested type declaration with matching name and occurrence within the declaring type
+ */
+ protected abstract AbstractTypeDeclaration getNestedTypeDeclaration(TypeDeclaration declaringTypeDeclaration);
+
+ /**
+ * return the type declaration corresponding to the type from the specified
+ * set of type declarations (match name and occurrence).
+ * Only return type or enum declarations
+ */
+ protected AbstractTypeDeclaration getTypeDeclaration(AbstractTypeDeclaration[] typeDeclarations) {
+ String name = this.getName();
+ int occurrence = this.getOccurrence();
+ int count = 0;
+ for (AbstractTypeDeclaration typeDeclaration : typeDeclarations) {
+ if (typeDeclaration.getName().getFullyQualifiedName().equals(name)) {
+ count++;
+ if (count == occurrence) {
+ return (typeDeclaration.getNodeType() == this.getASTNodeType()) ? typeDeclaration : null;
+ }
+ }
+ }
+ // return null if the type is no longer in the source code;
+ // this can happen when the context model has not yet
+ // been synchronized with the resource model but is still
+ // asking for an ASTNode (e.g. during a selection event)
+ return null;
+ }
+
+ protected abstract int getASTNodeType();
+
+ /**
+ * we only instantiate a single top-level, non-annotation
+ * type per compilation unit (i.e. a class, enum, or interface)
+ */
+ // minimize scope of suppressed warnings
+ @SuppressWarnings("unchecked")
+ protected static List<AbstractTypeDeclaration> types(CompilationUnit astRoot) {
+ return astRoot.types();
+ }
+
+ protected static EnumDeclaration[] getEnums(TypeDeclaration declaringTypeDeclaration) {
+ List<BodyDeclaration> bd = bodyDeclarations(declaringTypeDeclaration);
+ int typeCount = 0;
+ for (Iterator<BodyDeclaration> it = bd.listIterator(); it.hasNext(); ) {
+ if (it.next().getNodeType() == ASTNode.ENUM_DECLARATION) {
+ typeCount++;
+ }
+ }
+ EnumDeclaration[] memberEnums = new EnumDeclaration[typeCount];
+ int next = 0;
+ for (Iterator<BodyDeclaration> it = bd.listIterator(); it.hasNext(); ) {
+ BodyDeclaration decl = it.next();
+ if (decl.getNodeType() == ASTNode.ENUM_DECLARATION) {
+ memberEnums[next++] = (EnumDeclaration) decl;
+ }
+ }
+ return memberEnums;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected static List<BodyDeclaration> bodyDeclarations(TypeDeclaration typeDeclaration) {
+ return typeDeclaration.bodyDeclarations();
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractNestedDeclarationAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractNestedDeclarationAnnotationAdapter.java
new file mode 100644
index 0000000000..1e12f713b0
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AbstractNestedDeclarationAnnotationAdapter.java
@@ -0,0 +1,403 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.MarkerAnnotation;
+import org.eclipse.jdt.core.dom.MemberValuePair;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+
+/**
+ * Pull together some of the behavior common to
+ * {@link NestedDeclarationAnnotationAdapter}
+ * and {@link NestedIndexedDeclarationAnnotationAdapter}
+ */
+public abstract class AbstractNestedDeclarationAnnotationAdapter
+ extends AbstractDeclarationAnnotationAdapter
+{
+ private final DeclarationAnnotationAdapter outerAnnotationAdapter;
+ private final String elementName;
+
+ // reduce NLS checks
+ protected static final String VALUE = "value"; //$NON-NLS-1$
+
+
+ // ********** constructors **********
+
+ /**
+ * The default element name is <code>value</code>.
+ */
+ protected AbstractNestedDeclarationAnnotationAdapter(DeclarationAnnotationAdapter outerAnnotationAdapter, String annotationName) {
+ this(outerAnnotationAdapter, VALUE, annotationName);
+ }
+
+ protected AbstractNestedDeclarationAnnotationAdapter(DeclarationAnnotationAdapter outerAnnotationAdapter, String elementName, String annotationName) {
+ super(annotationName);
+ this.outerAnnotationAdapter = outerAnnotationAdapter;
+ this.elementName = elementName;
+ }
+
+
+ // ********** DeclarationAnnotationAdapter implementation **********
+
+ public Annotation getAnnotation(ModifiedDeclaration declaration) {
+ Annotation outer = this.outerAnnotationAdapter.getAnnotation(declaration);
+ if (outer == null) {
+ return null;
+ }
+ Expression value = this.elementValue(outer);
+ if (value == null) {
+ return null;
+ }
+ Annotation inner = this.getAnnotation(value);
+ if (inner == null) {
+ return null;
+ }
+ // return the annotation only if it has a matching name(?)
+ return this.nameMatches(declaration, inner) ? inner : null;
+ }
+
+ public void removeAnnotation(ModifiedDeclaration declaration) {
+ Annotation outer = this.outerAnnotationAdapter.getAnnotation(declaration);
+ if (outer == null) {
+ return;
+ }
+ Expression value = this.elementValue(outer);
+ if (value == null) {
+ return;
+ }
+ // hack to allow short-circuit when the value is an array initializer
+ if (this.removeAnnotation(declaration, outer, value)) {
+ return;
+ }
+ Annotation inner = this.annotationValue(value);
+ if (inner == null) {
+ return;
+ }
+ // remove the annotation only if it has a matching name(?)
+ if (this.nameMatches(declaration, inner)) {
+ this.removeElementAndNormalize(declaration, outer);
+ }
+ }
+
+ public ASTNode getAstNode(ModifiedDeclaration declaration) {
+ // if the annotation is missing, return the outer annotation's node
+ Annotation annotation = this.getAnnotation(declaration);
+ return (annotation != null) ? annotation : this.outerAnnotationAdapter.getAstNode(declaration);
+ }
+
+ @Override
+ protected void addAnnotation(ModifiedDeclaration declaration, Annotation inner) {
+ Annotation outer = this.outerAnnotationAdapter.getAnnotation(declaration);
+ if (outer == null) {
+ this.buildNewOuterAnnotation(declaration, inner);
+ } else if (outer.isMarkerAnnotation()) {
+ this.modifyAnnotation(declaration, (MarkerAnnotation) outer, inner);
+ } else if (outer.isSingleMemberAnnotation()) {
+ this.modifyAnnotation(declaration, (SingleMemberAnnotation) outer, inner);
+ } else if (outer.isNormalAnnotation()) {
+ this.modifyAnnotation(declaration, (NormalAnnotation) outer, inner);
+ } else {
+ throw new IllegalStateException("unknown annotation type: " + outer); //$NON-NLS-1$
+ }
+ }
+
+
+ // ********** abstract methods **********
+
+ /**
+ * Return an annotation extracted from the specified expression,
+ * which is the value of the adapter's element.
+ */
+ protected abstract Annotation getAnnotation(Expression value);
+
+ /**
+ * Remove the annotation from the specified expression,
+ * which is the value of the adapter's element.
+ * Return whether the removal was successful.
+ */
+ protected abstract boolean removeAnnotation(ModifiedDeclaration declaration, Annotation outer, Expression value);
+
+ /**
+ * Set the value of the specified outer annotation to the
+ * specified inner annotation.
+ */
+ protected abstract void modifyAnnotationValue(SingleMemberAnnotation outer, Annotation inner);
+
+ /**
+ * Set the value of the specified member value pair to the
+ * specified inner annotation.
+ */
+ protected abstract void modifyMemberValuePair(MemberValuePair pair, Annotation inner);
+
+
+ // ********** public methods **********
+
+ public DeclarationAnnotationAdapter getOuterAnnotationAdapter() {
+ return this.outerAnnotationAdapter;
+ }
+
+ public String getElementName() {
+ return this.elementName;
+ }
+
+
+ // ********** internal methods **********
+
+ /**
+ * If the specified expression is an annotation, cast it to an annotation;
+ * otherwise return null.
+ */
+ protected Annotation annotationValue(Expression expression) {
+ switch (expression.getNodeType()) {
+ case ASTNode.NORMAL_ANNOTATION:
+ case ASTNode.SINGLE_MEMBER_ANNOTATION:
+ case ASTNode.MARKER_ANNOTATION:
+ return (Annotation) expression;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Remove the <em>first</em> annotation element with the specified name
+ * from the specified annotation, converting the annotation as appropriate.
+ */
+ protected void removeElementAndNormalize(ModifiedDeclaration declaration, Annotation outer) {
+ if (outer.isNormalAnnotation()) {
+ this.removeElementAndNormalize(declaration, (NormalAnnotation) outer);
+ } else if (outer.isSingleMemberAnnotation()) {
+ this.removeElementAndNormalize(declaration, (SingleMemberAnnotation) outer);
+ } else if (outer.isMarkerAnnotation()) {
+ this.removeElementAndNormalize(declaration, (MarkerAnnotation) outer);
+ } else {
+ throw new IllegalArgumentException("unknown annotation type: " + outer); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Remove the <em>first</em> annotation element with the adapter's element
+ * name from the specified annotation. Convert the annotation to
+ * a marker annotation or single member annotation if appropriate.
+ * <pre>
+ * &#64;Outer(name="Fred", foo=&#64;Inner) => &#64;Outer(name="Fred")
+ * &#64;Outer(foo=&#64;Inner) => &#64;Outer
+ * </pre>
+ */
+ protected void removeElementAndNormalize(ModifiedDeclaration declaration, NormalAnnotation outer) {
+ this.removeElement(outer);
+ this.normalizeAnnotation(declaration, outer);
+ }
+
+ /**
+ * Remove from the specified annotation the element with
+ * the adapter's element name.
+ */
+ protected void removeElement(NormalAnnotation annotation) {
+ for (Iterator<MemberValuePair> stream = this.values(annotation).iterator(); stream.hasNext(); ) {
+ MemberValuePair pair = stream.next();
+ if (pair.getName().getFullyQualifiedName().equals(this.elementName)) {
+ stream.remove();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Convert the specified normal annotation to a marker annotation or
+ * single member annotation if appropriate.
+ */
+ protected void normalizeAnnotation(ModifiedDeclaration declaration, NormalAnnotation outer) {
+ List<MemberValuePair> values = this.values(outer);
+ switch (values.size()) {
+ case 0:
+ // if the elements are all gone, convert the annotation to a marker annotation
+ this.outerAnnotationAdapter.newMarkerAnnotation(declaration);
+ break;
+ case 1:
+ MemberValuePair pair = values.get(0);
+ if (pair.getName().getFullyQualifiedName().equals(VALUE)) {
+ // if the last remaining element is 'value', convert the annotation to a single member annotation
+ Expression vv = pair.getValue();
+ vv = (Expression) ASTNode.copySubtree(vv.getAST(), vv);
+ this.outerAnnotationAdapter.newSingleMemberAnnotation(declaration).setValue(vv);
+ }
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ }
+
+ /**
+ * Convert the specified single member annotation to a marker annotation
+ * if the adapter's element name is <code>value</code>.
+ */
+ protected void removeElementAndNormalize(ModifiedDeclaration declaration, @SuppressWarnings("unused") SingleMemberAnnotation outer) {
+ if (this.elementName.equals(VALUE)) {
+ this.outerAnnotationAdapter.newMarkerAnnotation(declaration);
+ }
+ }
+
+ protected void removeElementAndNormalize(@SuppressWarnings("unused") ModifiedDeclaration declaration, @SuppressWarnings("unused") MarkerAnnotation outer) {
+ // NOP
+ }
+
+ /**
+ * Return the value of the *first* annotation element
+ * with the adapter's element name.
+ * Return null if the annotation has no such element.
+ * (An element name of "value" will return the value of a single
+ * member annotation.)
+ */
+ protected Expression elementValue(Annotation annotation) {
+ if (annotation.isNormalAnnotation()) {
+ return this.elementValue((NormalAnnotation) annotation);
+ }
+ if (annotation.isSingleMemberAnnotation()) {
+ return this.elementValue((SingleMemberAnnotation) annotation);
+ }
+ return null;
+ }
+
+ protected Expression elementValue(NormalAnnotation annotation) {
+ MemberValuePair pair = this.memberValuePair(annotation);
+ return (pair == null) ? null : pair.getValue();
+ }
+
+ /**
+ * If the adapter's element name is "value", return the value of the
+ * annotation, otherwise return null.
+ */
+ protected Expression elementValue(SingleMemberAnnotation annotation) {
+ return this.elementName.equals(VALUE) ? annotation.getValue() : null;
+ }
+
+ /**
+ * Return the *first* member value pair for the adapter's element name.
+ * Return null if the specified annotation has no such element.
+ */
+ protected MemberValuePair memberValuePair(NormalAnnotation annotation) {
+ for (MemberValuePair pair : this.values(annotation)) {
+ if (pair.getName().getFullyQualifiedName().equals(this.elementName)) {
+ return pair;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Build a new outer annotation and add the specified
+ * inner annotation to it:
+ * <pre>
+ * &#64;Outer(&#64;Inner)
+ * </pre>
+ * or
+ * <pre>
+ * &#64;Outer(foo=&#64;Inner)
+ * </pre>
+ */
+ protected void buildNewOuterAnnotation(ModifiedDeclaration declaration, Annotation inner) {
+ if (this.elementName.equals(VALUE)) {
+ this.outerAnnotationAdapter.newSingleMemberAnnotation(declaration).setValue(this.buildNewInnerExpression(inner));
+ } else {
+ List<MemberValuePair> values = this.values(this.outerAnnotationAdapter.newNormalAnnotation(declaration));
+ values.add(this.newMemberValuePair(this.buildNewInnerExpression(inner)));
+ }
+ }
+
+ /**
+ * Build an expression to be added to a new outer annotation
+ * for the specified inner annotation.
+ */
+ protected abstract Expression buildNewInnerExpression(Annotation inner);
+
+ /**
+ * Build a new member value pair with the specified name and value.
+ */
+ protected MemberValuePair newMemberValuePair(String name, Expression value) {
+ AST ast = value.getAST();
+ MemberValuePair pair = ast.newMemberValuePair();
+ pair.setName(ast.newSimpleName(name));
+ pair.setValue(value);
+ return pair;
+ }
+
+ /**
+ * Build a new member value pair with the adapter's element name
+ * and the specified inner annotation.
+ */
+ protected MemberValuePair newMemberValuePair(Expression value) {
+ return this.newMemberValuePair(this.elementName, value);
+ }
+
+ /**
+ * Add the specified inner annotation to the marker annotation.
+ */
+ protected void modifyAnnotation(ModifiedDeclaration declaration, @SuppressWarnings("unused") MarkerAnnotation outer, Annotation inner) {
+ this.buildNewOuterAnnotation(declaration, inner);
+ }
+
+ /**
+ * Add the specified inner annotation to the single member annotation.
+ */
+ protected void modifyAnnotation(ModifiedDeclaration declaration, SingleMemberAnnotation outer, Annotation inner) {
+ if (this.elementName.equals(VALUE)) {
+ this.modifyAnnotationValue(outer, inner);
+ } else {
+ this.modifyAnnotationNonValue(declaration, outer, inner);
+ }
+ }
+
+ /**
+ * Add the specified inner annotation to the single member annotation,
+ * converting it to a normal annotation:
+ * <pre>
+ * &#64;Outer("lorem ipsum") => &#64;Outer(value="lorem ipsum", foo=&#64;Inner)
+ * </pre>
+ */
+ protected void modifyAnnotationNonValue(ModifiedDeclaration declaration, SingleMemberAnnotation outer, Annotation inner) {
+ Expression vv = outer.getValue();
+ vv = (Expression) ASTNode.copySubtree(vv.getAST(), vv);
+ NormalAnnotation newOuter = this.outerAnnotationAdapter.newNormalAnnotation(declaration);
+ List<MemberValuePair> values = this.values(newOuter);
+ values.add(this.newMemberValuePair(VALUE, vv));
+ values.add(this.newMemberValuePair(this.buildNewInnerExpression(inner)));
+ }
+
+ /**
+ * Add the specified inner annotation to the normal annotation:
+ * <pre>
+ * &#64;Outer(bar="lorem ipsum") => &#64;Outer(bar="lorem ipsum", foo=&#64;Inner)
+ * </pre>
+ * or
+ * <pre>
+ * &#64;Outer(foo=&#64;Inner("lorem ipsum")) => &#64;Outer(foo=&#64;Inner)
+ * </pre>
+ */
+ protected void modifyAnnotation(@SuppressWarnings("unused") ModifiedDeclaration declaration, NormalAnnotation outer, Annotation inner) {
+ MemberValuePair pair = this.memberValuePair(outer);
+ if (pair == null) {
+ List<MemberValuePair> values = this.values(outer);
+ values.add(this.newMemberValuePair(inner));
+ } else {
+ this.modifyMemberValuePair(pair, inner);
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AnnotatedElementAnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AnnotatedElementAnnotationElementAdapter.java
new file mode 100644
index 0000000000..f3bdf046c6
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AnnotatedElementAnnotationElementAdapter.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotatedElement;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationElementAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationElementAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+ /**
+ * Adapt an annotated element and a declaration annotation element adapter.
+ */
+public class AnnotatedElementAnnotationElementAdapter<T>
+ implements AnnotationElementAdapter<T>
+{
+ private final AnnotatedElement annotatedElement;
+ private final DeclarationAnnotationElementAdapter<T> daea;
+
+
+ // ********** constructor **********
+
+ public AnnotatedElementAnnotationElementAdapter(AnnotatedElement annotatedElement, DeclarationAnnotationElementAdapter<T> daea) {
+ super();
+ this.annotatedElement = annotatedElement;
+ this.daea = daea;
+ }
+
+
+ // ********** AnnotationElementAdapter implementation **********
+
+ public T getValue() {
+ return this.daea.getValue(this.annotatedElement.getModifiedDeclaration());
+ }
+
+ public T getValue(CompilationUnit astRoot) {
+ return this.daea.getValue(this.annotatedElement.getModifiedDeclaration(astRoot));
+ }
+
+ public void setValue(T value) {
+ this.edit(this.buildSetValueEditor(value));
+ }
+
+ public Expression getExpression(CompilationUnit astRoot) {
+ return this.daea.getExpression(this.annotatedElement.getModifiedDeclaration(astRoot));
+ }
+
+ public ASTNode getAstNode(CompilationUnit astRoot) {
+ return this.daea.getAstNode(this.annotatedElement.getModifiedDeclaration(astRoot));
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.daea);
+ }
+
+
+ // ********** internal methods **********
+
+ protected void edit(AnnotatedElement.Editor editor) {
+ this.annotatedElement.edit(editor);
+ }
+
+ protected AnnotatedElement.Editor buildSetValueEditor(T value) {
+ return new SetValueEditor<T>(value, this.daea);
+ }
+
+
+ // ********** member classes **********
+
+ protected static class SetValueEditor<T> implements AnnotatedElement.Editor {
+ private final DeclarationAnnotationElementAdapter<T> daea;
+ private final T value;
+
+ SetValueEditor(T value, DeclarationAnnotationElementAdapter<T> daea) {
+ super();
+ this.value = value;
+ this.daea = daea;
+ }
+ public void edit(ModifiedDeclaration declaration) {
+ this.daea.setValue(this.value, declaration);
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AnnotationStringArrayExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AnnotationStringArrayExpressionConverter.java
new file mode 100644
index 0000000000..bd085ef4ff
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/AnnotationStringArrayExpressionConverter.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ArrayInitializer;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+
+/**
+ * Convert an array initializer or single expression to/from an array of
+ * strings (e.g. {"text0", "text1"}).
+ * E is the type of the expressions to be found either stand-alone or
+ * as elements in the array initializer.
+ */
+public class AnnotationStringArrayExpressionConverter
+ extends AbstractExpressionConverter<String[]>
+{
+ private final ExpressionConverter<String> elementConverter;
+ private final StringArrayExpressionConverter arrayConverter;
+
+
+ /**
+ * The default behavior is to remove the array initializer if it is empty.
+ */
+ public AnnotationStringArrayExpressionConverter(ExpressionConverter<String> elementConverter) {
+ this(elementConverter, true);
+ }
+
+ public AnnotationStringArrayExpressionConverter(ExpressionConverter<String> elementConverter, boolean removeArrayInitializerWhenEmpty) {
+ super();
+ this.elementConverter = elementConverter;
+ this.arrayConverter = new StringArrayExpressionConverter(elementConverter, removeArrayInitializerWhenEmpty);
+ }
+
+ /**
+ * if we only have a single string in the array return the single expression,
+ * without braces, instead of an array initializer
+ */
+ @Override
+ protected Expression convertObject(String[] strings, AST ast) {
+ return (strings.length == 1) ?
+ this.elementConverter.convert(strings[0], ast)
+ :
+ this.arrayConverter.convertObject(strings, ast);
+ }
+
+ @Override
+ protected String[] convertNull() {
+ return this.arrayConverter.convertNull();
+ }
+
+ /**
+ * check for a single expression with no surrounding braces, implying a
+ * single-entry array
+ */
+ @Override
+ protected String[] convertExpression(Expression expression) {
+ return (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) ?
+ this.arrayConverter.convertArrayInitializer((ArrayInitializer) expression)
+ :
+ new String[] {this.elementConverter.convert(expression)};
+ }
+
+
+ // ********** factory methods **********
+
+ /**
+ * Build an expression converter for an annotation element of type String[].
+ * @Foo(bar={"text0", "text1"})
+ * or
+ * @Foo(bar="text0")
+ */
+ public static AnnotationStringArrayExpressionConverter forStrings() {
+ return new AnnotationStringArrayExpressionConverter(StringExpressionConverter.instance());
+ }
+
+ /**
+ * Build an expression converter for an annotation element of type <enum>[].
+ * @Foo(bar={BAZ, BAT})
+ * or
+ * @Foo(bar=BAZ)
+ */
+ public static AnnotationStringArrayExpressionConverter forNames() {
+ return new AnnotationStringArrayExpressionConverter(NameStringExpressionConverter.instance());
+ }
+
+
+ /**
+ * Build an expression converter for an annotation element of type Class[].
+ * @Foo(bar={Baz.class, Bat.class})
+ * or
+ * @Foo(bar=Baz.class)
+ */
+ public static AnnotationStringArrayExpressionConverter forTypes() {
+ return new AnnotationStringArrayExpressionConverter(TypeStringExpressionConverter.instance());
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/BooleanExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/BooleanExpressionConverter.java
new file mode 100644
index 0000000000..f33a719986
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/BooleanExpressionConverter.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.BooleanLiteral;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+
+/**
+ * Convert a boolean literal to/from a Boolean
+ * (e.g. Boolean.TRUE).
+ */
+public final class BooleanExpressionConverter
+ extends AbstractExpressionConverter<Boolean>
+{
+ private static final ExpressionConverter<Boolean> INSTANCE = new BooleanExpressionConverter();
+
+ /**
+ * Return the singleton.
+ */
+ public static ExpressionConverter<Boolean> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private BooleanExpressionConverter() {
+ super();
+ }
+
+ @Override
+ protected BooleanLiteral convertObject(Boolean booleanObject, AST ast) {
+ return ast.newBooleanLiteral(booleanObject.booleanValue());
+ }
+
+ @Override
+ protected Boolean convertExpression(Expression expression) {
+ Object value = expression.resolveConstantExpressionValue();
+ return (value instanceof Boolean) ? ((Boolean) value) : null;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/CharacterStringExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/CharacterStringExpressionConverter.java
new file mode 100644
index 0000000000..cfb470581b
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/CharacterStringExpressionConverter.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.CharacterLiteral;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+
+/**
+ * Convert a character literal to/from a string representation of a character
+ * (e.g. "A").
+ */
+public final class CharacterStringExpressionConverter
+ extends AbstractExpressionConverter<String>
+{
+ private static final ExpressionConverter<String> INSTANCE = new CharacterStringExpressionConverter();
+
+ /**
+ * Return the singleton.
+ */
+ public static ExpressionConverter<String> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private CharacterStringExpressionConverter() {
+ super();
+ }
+
+ @Override
+ protected CharacterLiteral convertObject(String string, AST ast) {
+ CharacterLiteral characterLiteral = ast.newCharacterLiteral();
+ characterLiteral.setCharValue(string.charAt(0));
+ return characterLiteral;
+ }
+
+ @Override
+ protected String convertExpression(Expression expression) {
+ Object value = expression.resolveConstantExpressionValue();
+ return (value instanceof Character) ? ((Character) value).toString() : null;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/CombinationIndexedDeclarationAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/CombinationIndexedDeclarationAnnotationAdapter.java
new file mode 100644
index 0000000000..384324151c
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/CombinationIndexedDeclarationAnnotationAdapter.java
@@ -0,0 +1,500 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.List;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.MarkerAnnotation;
+import org.eclipse.jdt.core.dom.MemberValuePair;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.IndexedDeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Manipulate an annotation that either occurs stand-alone, e.g.
+ * <pre>
+ * &#64;Inner("zero")
+ * private int id;
+ * </pre>
+ *
+ * or is embedded in an element array within another annotation, e.g.
+ * <pre>
+ * &#64;Outer(foo={&#64;Inner("zero"), &#64;Inner("one"), &#64;Inner("two")})
+ * private int id;
+ *
+ * annotationName = "Inner"
+ * containerAnnotationName = "Outer"
+ * elementName = "foo"
+ * index = 0-2
+ * </pre>
+ *
+ * This is a useful pattern because a declaration cannot have more
+ * than one annotation of the same type, and allowing the stand-alone
+ * configuration reduces clutter.
+ * <br>
+ * NB: This configuration only makes sense for "top-level" annotations, as
+ * opposed to "nested" annotations. This is because annotation elements
+ * can only be declared with a type of a single annotation and annotations
+ * cannot be part of an inheritance hierarchy.
+ * For example, the following configurations cannot *both* be supported:
+ * <pre>
+ * &#64;Foo(bar=&#64;Outer(...))
+ * private int id;
+ *
+ * &#64;Foo(bar=&#64;Inner(...)) // not allowed
+ * private int id;
+ * </pre>
+ *
+ * NB: Behavior is undefined when both the stand-alone and the nested
+ * configurations annotate the same declaration, e.g.
+ * <pre>
+ * // undefined behavior
+ * &#64;Inner("zero")
+ * &#64;Outer(foo={&#64;Inner("zero"), &#64;Inner("one"), &#64;Inner("two")})
+ * private int id;
+ * </pre>
+ */
+public class CombinationIndexedDeclarationAnnotationAdapter
+ implements IndexedDeclarationAnnotationAdapter
+{
+
+ /**
+ * this adapter is used when the annotation is "stand-alone":
+ * <pre>
+ * &#64;Inner("zero")
+ * </pre>
+ * and is only used when the index is 0 or 1
+ */
+ private final SimpleDeclarationAnnotationAdapter standAloneAnnotationAdapter;
+
+ /**
+ * this adapter is used when the annotation is "nested":
+ * <pre>
+ * &#64;Outer(foo={&#64;Inner("zero"), &#64;Inner("one")})
+ * </pre>
+ */
+ private final NestedIndexedDeclarationAnnotationAdapter nestedAnnotationAdapter;
+
+ /**
+ * this adapter is for the "nested" annotation at the zero index;
+ * and is only used when the index is 1
+ */
+ private final NestedIndexedDeclarationAnnotationAdapter zeroNestedAnnotationAdapter;
+
+ // reduce NLS checks
+ protected static final String VALUE = "value"; //$NON-NLS-1$
+
+
+ // ********** constructors **********
+
+ /**
+ * default element name is "value"
+ * <pre>
+ * &#64;Inner("zero")
+ * &#64;Outer({&#64;Inner("zero"), &#64;Inner("one")})
+ * </pre>
+ */
+ public CombinationIndexedDeclarationAnnotationAdapter(String annotationName, String containerAnnotationName, int index) {
+ this(annotationName, containerAnnotationName, VALUE, index);
+ }
+
+ public CombinationIndexedDeclarationAnnotationAdapter(String annotationName, String containerAnnotationName, String elementName, int index) {
+ this(new SimpleDeclarationAnnotationAdapter(annotationName), new SimpleDeclarationAnnotationAdapter(containerAnnotationName), elementName, index, annotationName);
+ }
+
+ /**
+ * default element name is "value"
+ */
+ public CombinationIndexedDeclarationAnnotationAdapter(
+ SimpleDeclarationAnnotationAdapter standAloneAnnotationAdapter,
+ SimpleDeclarationAnnotationAdapter containerAnnotationAdapter,
+ int index,
+ String nestedAnnotationName
+ ) {
+ this(standAloneAnnotationAdapter, containerAnnotationAdapter, VALUE, index, nestedAnnotationName);
+ }
+
+ public CombinationIndexedDeclarationAnnotationAdapter(
+ SimpleDeclarationAnnotationAdapter standAloneAnnotationAdapter,
+ SimpleDeclarationAnnotationAdapter containerAnnotationAdapter,
+ String elementName,
+ int index,
+ String nestedAnnotationName
+ ) {
+ super();
+ this.standAloneAnnotationAdapter = standAloneAnnotationAdapter;
+ this.nestedAnnotationAdapter = new NestedIndexedDeclarationAnnotationAdapter(containerAnnotationAdapter, elementName, index, nestedAnnotationName);
+ this.zeroNestedAnnotationAdapter = new NestedIndexedDeclarationAnnotationAdapter(containerAnnotationAdapter, elementName, 0, nestedAnnotationName);
+ }
+
+
+ // ********** DeclarationAnnotationAdapter implementation **********
+
+ public Annotation getAnnotation(ModifiedDeclaration declaration) {
+ if (this.getIndex() == 0) {
+ // check for the stand-alone annotation
+ Annotation standAloneAnnotation = this.getStandAloneAnnotation(declaration);
+ if (standAloneAnnotation != null) {
+ return standAloneAnnotation;
+ }
+ }
+ return this.getNestedAnnotation(declaration);
+ }
+
+ /**
+ * <pre>
+ * [none] => &#64;Inner
+ * or
+ * &#64;Inner("lorem ipsum") => &#64;Inner
+ * or
+ * &#64;Inner(text="lorem ipsum") => &#64;Inner
+ * or
+ * &#64;Outer(foo={&#64;Inner, &#64;Inner}) => &#64;Outer(foo={&#64;Inner, &#64;Inner, &#64;Inner})
+ * or
+ * &#64;Outer(foo=&#64;Inner) => &#64;Outer(foo={&#64;Inner, &#64;Inner})
+ * or
+ * &#64;Inner => &#64;Outer(foo={&#64;Inner, &#64;Inner})
+ * etc.
+ * </pre>
+ */
+ public MarkerAnnotation newMarkerAnnotation(ModifiedDeclaration declaration) {
+ return (MarkerAnnotation) this.newAnnotation(MARKER_ANNOTATION_FACTORY, declaration);
+ }
+
+ public SingleMemberAnnotation newSingleMemberAnnotation(ModifiedDeclaration declaration) {
+ return (SingleMemberAnnotation) this.newAnnotation(SINGLE_MEMBER_ANNOTATION_FACTORY, declaration);
+ }
+
+ public NormalAnnotation newNormalAnnotation(ModifiedDeclaration declaration) {
+ return (NormalAnnotation) this.newAnnotation(NORMAL_ANNOTATION_FACTORY, declaration);
+ }
+
+ public void removeAnnotation(ModifiedDeclaration declaration) {
+ if (this.getIndex() == 0) {
+ // check for the stand-alone annotation
+ if (this.standAloneAnnotationIsPresent(declaration)) {
+ this.removeStandAloneAnnotation(declaration);
+ return;
+ }
+ }
+ this.removeNestedAnnotation(declaration);
+ if (this.nestedElementCanBeConvertedToStandAlone(declaration)) {
+ this.convertLastElementAnnotationToStandAloneAnnotation(declaration);
+ }
+ }
+
+ public ASTNode getAstNode(ModifiedDeclaration declaration) {
+ // if the annotation is missing, delegate to the nested annotation adapter
+ Annotation annotation = this.getAnnotation(declaration);
+ return (annotation != null) ? annotation : this.nestedAnnotationAdapter.getAstNode(declaration);
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.getAnnotationName());
+ }
+
+
+ // ********** IndexedDeclarationAnnotationAdapter implementation **********
+
+ public int getIndex() {
+ return this.nestedAnnotationAdapter.getIndex();
+ }
+
+ public void moveAnnotation(int newIndex, ModifiedDeclaration declaration) {
+ int oldIndex = this.getIndex();
+ if (newIndex == oldIndex) {
+ return;
+ }
+
+ Annotation standAloneAnnotation = this.getStandAloneAnnotation(declaration);
+ if (standAloneAnnotation == null) {
+ this.moveNestedAnnotation(newIndex, declaration);
+ if (this.nestedElementCanBeConvertedToStandAlone(declaration)) {
+ this.convertLastElementAnnotationToStandAloneAnnotation(declaration);
+ }
+ } else {
+ if ((oldIndex == 0) && (newIndex == 1)) {
+ // this is one of two situations where we transition from stand-alone to container
+ this.moveStandAloneAnnotationToContainerAnnotation(standAloneAnnotation, declaration);
+ this.moveNestedAnnotation(newIndex, declaration);
+ } else if (newIndex == 0) {
+ // we are moving a 'null' entry on top of the stand-alone, so remove it
+ this.removeStandAloneAnnotation(declaration);
+ } else {
+ throw new IllegalStateException("old index = " + oldIndex + "; new index = " + newIndex); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+
+
+ // ********** internal methods **********
+
+ /**
+ * build the appropriate new annotation,
+ * which may require moving the 0th annotation from "stand-alone" to "nested"
+ */
+ private Annotation newAnnotation(AnnotationFactory annotationFactory, ModifiedDeclaration declaration) {
+ if (this.getIndex() == 0) {
+ return this.newZeroAnnotation(annotationFactory, declaration);
+ }
+ if (this.zeroNestedAnnotationIsPresent(declaration)) {
+ // manipulate the container annotation - ignore the stand-alone annotation(?)
+ // @Outer(foo=@Inner("zero")) => @Outer(foo={@Inner("zero"), @Inner})
+ // or
+ // @Outer(foo={@Inner("zero"), @Inner("one")}) => @Outer(foo={@Inner("zero"), @Inner})
+ return annotationFactory.newAnnotation(this.nestedAnnotationAdapter, declaration);
+ }
+
+ // this is one of two situations where we transition from stand-alone to container
+ this.moveStandAloneAnnotationToContainerAnnotation(declaration);
+ // once the stand-alone annotation is moved to index=0, build the new annotation at index=1
+ return annotationFactory.newAnnotation(this.nestedAnnotationAdapter, declaration);
+ }
+
+ /**
+ * the index is 0 - build the appropriate new annotation,
+ * which may be either "stand-alone" or "nested"
+ */
+ private Annotation newZeroAnnotation(AnnotationFactory annotationFactory, ModifiedDeclaration declaration) {
+ if (this.standAloneAnnotationIsPresent(declaration)) {
+ // replace the stand-alone annotation - ignore the container annotation(?)
+ // @Inner(text="lorem ipsum") => @Inner
+ return annotationFactory.newAnnotation(this.standAloneAnnotationAdapter, declaration);
+ }
+ if (this.containerAnnotationIsPresent(declaration)) {
+ // manipulate the container annotation
+ // @Outer(foo=@Inner(text="lorem ipsum")) => @Outer(foo=@Inner)
+ return annotationFactory.newAnnotation(this.nestedAnnotationAdapter, declaration);
+ }
+ // neither annotation is present - add a new stand-alone annotation
+ return annotationFactory.newAnnotation(this.standAloneAnnotationAdapter, declaration);
+ }
+
+ /**
+ * move the stand-alone annotation to the container annotation at index=0
+ */
+ private void moveStandAloneAnnotationToContainerAnnotation(ModifiedDeclaration declaration) {
+ Annotation standAloneAnnotation = this.getStandAloneAnnotation(declaration);
+ if (standAloneAnnotation == null) {
+ throw new IllegalStateException("the stand-alone annotation is missing"); //$NON-NLS-1$
+ }
+ this.moveStandAloneAnnotationToContainerAnnotation(standAloneAnnotation, declaration);
+ }
+
+ /**
+ * move the specified, non-null, stand-alone annotation to
+ * the container annotation at index=0
+ */
+ private void moveStandAloneAnnotationToContainerAnnotation(Annotation standAloneAnnotation, ModifiedDeclaration declaration) {
+ if (standAloneAnnotation.isMarkerAnnotation()) {
+ this.zeroNestedAnnotationAdapter.newMarkerAnnotation(declaration);
+ } else if (standAloneAnnotation.isSingleMemberAnnotation()) {
+ Expression vv = ((SingleMemberAnnotation) standAloneAnnotation).getValue();
+ vv = (Expression) ASTNode.copySubtree(vv.getAST(), vv);
+ this.zeroNestedAnnotationAdapter.newSingleMemberAnnotation(declaration).setValue(vv);
+ } else if (standAloneAnnotation.isNormalAnnotation()) {
+ NormalAnnotation newNA = this.zeroNestedAnnotationAdapter.newNormalAnnotation(declaration);
+ List<MemberValuePair> values = this.values(newNA);
+ for (MemberValuePair pair : this.values((NormalAnnotation) standAloneAnnotation)) {
+ values.add((MemberValuePair) ASTNode.copySubtree(pair.getAST(), pair));
+ }
+ } else {
+ throw new IllegalStateException("unknown annotation type: " + standAloneAnnotation); //$NON-NLS-1$
+ }
+ this.removeStandAloneAnnotation(declaration);
+ }
+
+ /**
+ * return whether the "nested" annotation container has been reduced to
+ * a single element (and the array initializer is converted to just
+ * the single remaining element) and can be further converted to the
+ * "stand-alone" annotation:
+ * <pre>
+ * &#64;Outer(foo={&#64;Inner("zero"), &#64;Inner("one")}) =>
+ * &#64;Outer(foo=&#64;Inner("zero")) =>
+ * &#64;Inner("zero")
+ * </pre>
+ */
+ private boolean nestedElementCanBeConvertedToStandAlone(ModifiedDeclaration declaration) {
+ Annotation containerAnnotation = this.getContainerAnnotation(declaration);
+ if (containerAnnotation == null) {
+ return false;
+ }
+ if (containerAnnotation.isMarkerAnnotation()) {
+ return false;
+ }
+ if (containerAnnotation.isSingleMemberAnnotation()) {
+ if (this.getElementName().equals(VALUE)) {
+ return (((SingleMemberAnnotation) containerAnnotation).getValue().getNodeType() != ASTNode.ARRAY_INITIALIZER)
+ && (this.zeroNestedAnnotationAdapter.getAnnotation(declaration) != null);
+ }
+ return false;
+ }
+ if (containerAnnotation.isNormalAnnotation()) {
+ NormalAnnotation na = (NormalAnnotation) containerAnnotation;
+ if (na.values().size() == 0) {
+ return false; // there are no elements present
+ }
+ if (na.values().size() != 1) {
+ return false; // there are other elements present - leave them all alone
+ }
+ MemberValuePair pair = (MemberValuePair) na.values().get(0);
+ if (this.getElementName().equals(pair.getName().getFullyQualifiedName())) {
+ return (pair.getValue().getNodeType() != ASTNode.ARRAY_INITIALIZER)
+ && (this.zeroNestedAnnotationAdapter.getAnnotation(declaration) != null);
+ }
+ return false;
+ }
+ throw new IllegalStateException("unknown annotation type: " + containerAnnotation); //$NON-NLS-1$
+ }
+
+ /**
+ * move the annotation in the container annotation at index=0
+ * to the stand-alone annotation
+ */
+ private void convertLastElementAnnotationToStandAloneAnnotation(ModifiedDeclaration declaration) {
+ Annotation last = this.zeroNestedAnnotationAdapter.getAnnotation(declaration);
+ if (last == null) {
+ throw new IllegalStateException("the last nested annotation is missing"); //$NON-NLS-1$
+ } else if (last.isMarkerAnnotation()) {
+ this.newStandAloneMarkerAnnotation(declaration);
+ } else if (last.isSingleMemberAnnotation()) {
+ Expression vv = ((SingleMemberAnnotation) last).getValue();
+ vv = (Expression) ASTNode.copySubtree(vv.getAST(), vv);
+ this.newStandAloneSingleMemberAnnotation(declaration).setValue(vv);
+ } else if (last.isNormalAnnotation()) {
+ NormalAnnotation newNA = this.newStandAloneNormalAnnotation(declaration);
+ List<MemberValuePair> values = this.values(newNA);
+ for (MemberValuePair pair : this.values((NormalAnnotation) last)) {
+ values.add((MemberValuePair) ASTNode.copySubtree(pair.getAST(), pair));
+ }
+ } else {
+ throw new IllegalStateException("unknown annotation type: " + last); //$NON-NLS-1$
+ }
+ this.removeContainerAnnotation(declaration);
+ }
+
+ private boolean standAloneAnnotationIsPresent(ModifiedDeclaration declaration) {
+ return this.getStandAloneAnnotation(declaration) != null;
+ }
+
+ private Annotation getStandAloneAnnotation(ModifiedDeclaration declaration) {
+ return this.standAloneAnnotationAdapter.getAnnotation(declaration);
+ }
+
+ private MarkerAnnotation newStandAloneMarkerAnnotation(ModifiedDeclaration declaration) {
+ return this.standAloneAnnotationAdapter.newMarkerAnnotation(declaration);
+ }
+
+ private SingleMemberAnnotation newStandAloneSingleMemberAnnotation(ModifiedDeclaration declaration) {
+ return this.standAloneAnnotationAdapter.newSingleMemberAnnotation(declaration);
+ }
+
+ private NormalAnnotation newStandAloneNormalAnnotation(ModifiedDeclaration declaration) {
+ return this.standAloneAnnotationAdapter.newNormalAnnotation(declaration);
+ }
+
+ private void removeStandAloneAnnotation(ModifiedDeclaration declaration) {
+ this.standAloneAnnotationAdapter.removeAnnotation(declaration);
+ }
+
+ private Annotation getNestedAnnotation(ModifiedDeclaration declaration) {
+ return this.nestedAnnotationAdapter.getAnnotation(declaration);
+ }
+
+ private void moveNestedAnnotation(int newIndex, ModifiedDeclaration declaration) {
+ this.nestedAnnotationAdapter.moveAnnotation(newIndex, declaration);
+ }
+
+ private void removeNestedAnnotation(ModifiedDeclaration declaration) {
+ this.nestedAnnotationAdapter.removeAnnotation(declaration);
+ }
+
+ private boolean containerAnnotationIsPresent(ModifiedDeclaration declaration) {
+ return this.getContainerAnnotation(declaration) != null;
+ }
+
+ private Annotation getContainerAnnotation(ModifiedDeclaration declaration) {
+ return this.nestedAnnotationAdapter.getOuterAnnotationAdapter().getAnnotation(declaration);
+ }
+
+ private void removeContainerAnnotation(ModifiedDeclaration declaration) {
+ this.nestedAnnotationAdapter.getOuterAnnotationAdapter().removeAnnotation(declaration);
+ }
+
+ private boolean zeroNestedAnnotationIsPresent(ModifiedDeclaration declaration) {
+ return this.getZeroNestedAnnotation(declaration) != null;
+ }
+
+ private Annotation getZeroNestedAnnotation(ModifiedDeclaration declaration) {
+ return this.zeroNestedAnnotationAdapter.getAnnotation(declaration);
+ }
+
+ private String getAnnotationName() {
+ return this.nestedAnnotationAdapter.getAnnotationName();
+ }
+
+ private String getElementName() {
+ return this.nestedAnnotationAdapter.getElementName();
+ }
+
+ @SuppressWarnings("unchecked")
+ protected List<MemberValuePair> values(NormalAnnotation na) {
+ return na.values();
+ }
+
+
+ // ********** annotation factories **********
+
+ /**
+ * define interface that allows us to "re-use" the nasty code in
+ * #newAnnotation(AnnotationFactory, ModifiedDeclaration)
+ */
+ private interface AnnotationFactory {
+ Annotation newAnnotation(DeclarationAnnotationAdapter adapter, ModifiedDeclaration declaration);
+ }
+
+ private static final AnnotationFactory MARKER_ANNOTATION_FACTORY = new AnnotationFactory() {
+ public Annotation newAnnotation(DeclarationAnnotationAdapter adapter, ModifiedDeclaration declaration) {
+ return adapter.newMarkerAnnotation(declaration);
+ }
+ @Override
+ public String toString() {
+ return "MarkerAnnotationFactory"; //$NON-NLS-1$
+ }
+ };
+
+ private static final AnnotationFactory SINGLE_MEMBER_ANNOTATION_FACTORY = new AnnotationFactory() {
+ public Annotation newAnnotation(DeclarationAnnotationAdapter adapter, ModifiedDeclaration declaration) {
+ return adapter.newSingleMemberAnnotation(declaration);
+ }
+ @Override
+ public String toString() {
+ return "SingleMemberAnnotationFactory"; //$NON-NLS-1$
+ }
+ };
+
+ private static final AnnotationFactory NORMAL_ANNOTATION_FACTORY = new AnnotationFactory() {
+ public Annotation newAnnotation(DeclarationAnnotationAdapter adapter, ModifiedDeclaration declaration) {
+ return adapter.newNormalAnnotation(declaration);
+ }
+ @Override
+ public String toString() {
+ return "NormalAnnotationFactory"; //$NON-NLS-1$
+ }
+ };
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ConversionDeclarationAnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ConversionDeclarationAnnotationElementAdapter.java
new file mode 100644
index 0000000000..37d12076be
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ConversionDeclarationAnnotationElementAdapter.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationElementAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Wrap a declaration annotation element adapter that deals with AST
+ * expressions, converting them to/from various other objects.
+ *
+ * @param <T> the type of the object be passed to and returned by the adapter
+ */
+public class ConversionDeclarationAnnotationElementAdapter<T>
+ implements DeclarationAnnotationElementAdapter<T>
+{
+ /**
+ * The wrapped adapter that returns and takes AST expressions.
+ */
+ private final DeclarationAnnotationElementAdapter<Expression> adapter;
+
+ /**
+ * The converter that converts AST expressions to other objects
+ * (e.g. Strings).
+ */
+ private final ExpressionConverter<T> converter;
+
+
+ // ********** constructors **********
+
+ /**
+ * The default element name is <code>value</code>.
+ */
+ public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, ExpressionConverter<T> converter) {
+ this(new ExpressionDeclarationAnnotationElementAdapter<Expression>(annotationAdapter), converter);
+ }
+
+ public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, ExpressionConverter<T> converter) {
+ this(new ExpressionDeclarationAnnotationElementAdapter<Expression>(annotationAdapter, elementName), converter);
+ }
+
+ public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationElementAdapter<Expression> adapter, ExpressionConverter<T> converter) {
+ super();
+ this.adapter = adapter;
+ this.converter = converter;
+ }
+
+
+ // ********** DeclarationAnnotationElementAdapter implementation **********
+
+ public T getValue(ModifiedDeclaration declaration) {
+ Expression expression = this.adapter.getValue(declaration);
+ return this.converter.convert(expression);
+ }
+
+ public void setValue(T value, ModifiedDeclaration declaration) {
+ Expression expression;
+ try {
+ expression = this.converter.convert(value, declaration.getAst());
+ } catch (IllegalArgumentException ex) {
+ // if there is a problem converting the 'value' to an Expression we get this exception
+ return; // don't set the value if it is "illegal"
+ }
+ this.adapter.setValue(expression, declaration);
+ }
+
+ public Expression getExpression(ModifiedDeclaration declaration) {
+ return this.adapter.getExpression(declaration);
+ }
+
+ public ASTNode getAstNode(ModifiedDeclaration declaration) {
+ return this.adapter.getAstNode(declaration);
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.adapter);
+ }
+
+
+ // ********** factory static methods **********
+
+ /**
+ * The default element name is <code>value</code>;
+ * the default expression converter expects string constant expressions.
+ */
+ public static ConversionDeclarationAnnotationElementAdapter<String> forStrings(DeclarationAnnotationAdapter annotationAdapter) {
+ return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, StringExpressionConverter.instance());
+ }
+
+ /**
+ * The default expression converter expects string constant expressions.
+ */
+ public static ConversionDeclarationAnnotationElementAdapter<String> forStrings(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+ return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, StringExpressionConverter.instance());
+ }
+
+ /**
+ * The default element name is <code>value</code>;
+ * the default expression converter expects number constant expressions.
+ */
+ public static ConversionDeclarationAnnotationElementAdapter<Integer> forNumbers(DeclarationAnnotationAdapter annotationAdapter) {
+ return new ConversionDeclarationAnnotationElementAdapter<Integer>(annotationAdapter, NumberIntegerExpressionConverter.instance());
+ }
+
+ /**
+ * The default expression converter expects number constant expressions.
+ */
+ public static ConversionDeclarationAnnotationElementAdapter<Integer> forNumbers(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+ return new ConversionDeclarationAnnotationElementAdapter<Integer>(annotationAdapter, elementName, NumberIntegerExpressionConverter.instance());
+ }
+
+ /**
+ * The default element name is <code>value</code>;
+ * the default expression converter expects boolean constant expressions.
+ */
+ public static ConversionDeclarationAnnotationElementAdapter<Boolean> forBooleans(DeclarationAnnotationAdapter annotationAdapter) {
+ return new ConversionDeclarationAnnotationElementAdapter<Boolean>(annotationAdapter, BooleanExpressionConverter.instance());
+ }
+
+ /**
+ * The default expression converter expects boolean constant expressions.
+ */
+ public static ConversionDeclarationAnnotationElementAdapter<Boolean> forBooleans(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+ return new ConversionDeclarationAnnotationElementAdapter<Boolean>(annotationAdapter, elementName, BooleanExpressionConverter.instance());
+ }
+
+ /**
+ * The default element name is <code>value</code>;
+ * the default expression converter expects character constant expressions.
+ */
+ public static ConversionDeclarationAnnotationElementAdapter<String> forCharacters(DeclarationAnnotationAdapter annotationAdapter) {
+ return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, CharacterStringExpressionConverter.instance());
+ }
+
+ /**
+ * The default expression converter expects character constant expressions.
+ */
+ public static ConversionDeclarationAnnotationElementAdapter<String> forCharacters(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+ return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, CharacterStringExpressionConverter.instance());
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/DefaultAnnotationEditFormatter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/DefaultAnnotationEditFormatter.java
new file mode 100644
index 0000000000..97264a9d93
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/DefaultAnnotationEditFormatter.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * This implementation will clean up some of the nasty Eclipse annotation
+ * formatting (or lack thereof); e.g. arrays of annotations.
+ */
+public final class DefaultAnnotationEditFormatter
+ implements AnnotationEditFormatter
+{
+ private static final DefaultAnnotationEditFormatter INSTANCE = new DefaultAnnotationEditFormatter();
+
+ /**
+ * Return the singleton.
+ */
+ public static DefaultAnnotationEditFormatter instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private DefaultAnnotationEditFormatter() {
+ super();
+ }
+
+ /**
+ * TODO
+ */
+ public void format(IDocument doc, TextEdit editTree) throws MalformedTreeException, BadLocationException {
+ TextEdit[] edits = editTree.getChildren();
+ int len = edits.length;
+ if (len == 0) {
+ return;
+ }
+
+ MultiTextEdit extraEdits = new MultiTextEdit();
+ for (int i = 0; i < len; i++) {
+ TextEdit edit1 = edits[i];
+ if ( ! (edit1 instanceof InsertEdit)) {
+ continue; // if the edit is not an insert, skip to the next edit
+ }
+ InsertEdit insert1 = (InsertEdit) edit1;
+ int j = i + 1;
+ if (j < len) {
+ TextEdit edit2 = edits[j];
+ if (edit2 instanceof InsertEdit) {
+ InsertEdit insert2 = (InsertEdit) edit2;
+ String text1 = insert1.getText();
+ String text2 = insert2.getText();
+ int offset1 = insert1.getOffset();
+ int offset2 = insert2.getOffset();
+ if (this.stringIsAnnotation(text1) && text2.equals(" ")) { //$NON-NLS-1$
+ // an annotation was inserted before something on the same line;
+ // replace the trailing space with a newline and appropriate indent
+ extraEdits.addChild(new ReplaceEdit(offset2, 1, this.buildCR(doc, offset2)));
+ i++; // jump the index past 'edit2'
+ continue; // go to the next edit
+ }
+ int comma1Length = this.commaLength(text1);
+ if ((comma1Length != 0) && this.stringIsAnnotation(text2)) {
+ // an annotation was inserted in an array initializer on the
+ // same line as the previous array element;
+ // replace the preceding space with a newline and appropriate indent
+ extraEdits.addChild(new ReplaceEdit(offset1 + comma1Length, text1.length() - comma1Length, this.buildCR(doc, offset1)));
+ i++; // jump the index past 'edit2'
+ continue; // go to the next edit
+ }
+ }
+ }
+ this.formatArrayInitializer(doc, insert1, extraEdits);
+ }
+ extraEdits.apply(doc, TextEdit.NONE);
+ }
+
+ /**
+ * If the insert edit is inserting an annotation containing an array of annotations as
+ * its value then format them nicely.
+ */
+ private void formatArrayInitializer(IDocument doc, InsertEdit insertEdit, MultiTextEdit extraEdits) throws BadLocationException {
+ String s = insertEdit.getText();
+ if ( ! this.stringIsAnnotation(s)) {
+ return;
+ }
+ int len = s.length();
+ int pos = 1; // skip '@'
+ while (pos < len) {
+ char c = s.charAt(pos);
+ pos++; // bump to just past first '('
+ if (c == '(') {
+ break;
+ }
+ }
+ if (pos == len) {
+ return; // reached end of string
+ }
+ while (pos < len) {
+ char c = s.charAt(pos);
+ pos++; // bump to just past first '{'
+ if (c == '{') {
+ break;
+ }
+ if (c != ' ') {
+ return;
+ }
+ }
+ if (pos == len) {
+ return; // reached end of string
+ }
+ // now look for '@' not inside parentheses and put in
+ // line delimeter and indent string before each
+ int offset = insertEdit.getOffset();
+ String indent = null;
+ int parenDepth = 0;
+ while (pos < len) {
+ switch (s.charAt(pos)) {
+ case '(' :
+ parenDepth++;
+ break;
+ case ')' :
+ parenDepth--;
+ break;
+ case '@' :
+ if (parenDepth == 0) {
+ if (indent == null) {
+ indent = this.buildCR(doc, offset, "\t"); // TODO use tab preference? //$NON-NLS-1$
+ }
+ extraEdits.addChild(new InsertEdit(offset + pos, indent));
+ }
+ break;
+ case '}' :
+ if (parenDepth == 0) {
+ extraEdits.addChild(new InsertEdit(offset + pos, this.buildCR(doc, offset)));
+ }
+ break;
+ }
+ pos++;
+ }
+ }
+
+ /**
+ * Build a string containing a line delimeter and indenting characters
+ * matching the indent level of the line containing the character offset
+ * (i.e. the new line's indent matches the current line).
+ */
+ private String buildCR(IDocument doc, int offset) throws BadLocationException {
+ return this.buildCR(doc, offset, ""); //$NON-NLS-1$
+ }
+
+ private String buildCR(IDocument doc, int offset, String suffix) throws BadLocationException {
+ int line = doc.getLineOfOffset(offset);
+ StringBuilder sb = new StringBuilder();
+ sb.append(doc.getLineDelimiter(line)); // use same CR as current line
+
+ int o = doc.getLineOffset(line); // match the whitespace of the current line
+ char c = doc.getChar(o++);
+ while ((c == ' ') || (c == '\t')) {
+ sb.append(c);
+ c = doc.getChar(o++);
+ }
+ sb.append(suffix);
+ return sb.toString();
+ }
+
+ /**
+ * Return whether the specified string is an annotation.
+ */
+ private boolean stringIsAnnotation(String string) {
+ return (string.length() > 1) && string.charAt(0) == '@';
+ }
+
+ /**
+ * If the specified string is a single comma, possibly surrounded by
+ * spaces, return the length of the substring containing the
+ * initial spaces and the comma.
+ */
+ private int commaLength(String string) {
+ boolean comma = false;
+ int len = string.length();
+ int result = 0;
+ for (int i = 0; i < len; i++) {
+ switch (string.charAt(i)) {
+ case ' ' :
+ if ( ! comma) {
+ result++; // space preceding comma
+ }
+ break;
+ case ',' :
+ if (comma) {
+ return 0; // second comma!
+ }
+ comma = true;
+ result++;
+ break;
+ default:
+ return 0; // non-comma, non-space char
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ElementAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ElementAnnotationAdapter.java
new file mode 100644
index 0000000000..17f14a4b22
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ElementAnnotationAdapter.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jpt.common.core.utility.jdt.AnnotatedElement;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+
+/**
+ * Adapt an annotated element and a declaration annotation adapter.
+ */
+public class ElementAnnotationAdapter extends AbstractAnnotationAdapter {
+
+
+ // ********** constructor **********
+
+ public ElementAnnotationAdapter(AnnotatedElement annotatedElement, DeclarationAnnotationAdapter daa) {
+ super(annotatedElement, daa);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ElementIndexedAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ElementIndexedAnnotationAdapter.java
new file mode 100644
index 0000000000..f113161824
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ElementIndexedAnnotationAdapter.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jpt.common.core.utility.jdt.AnnotatedElement;
+import org.eclipse.jpt.common.core.utility.jdt.IndexedAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.IndexedDeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Adapt an annotated element and an indexed declaration annotation adapter.
+ */
+public class ElementIndexedAnnotationAdapter
+ extends AbstractAnnotationAdapter
+ implements IndexedAnnotationAdapter
+{
+ private final IndexedDeclarationAnnotationAdapter idaa;
+
+
+ // ********** constructor **********
+
+ public ElementIndexedAnnotationAdapter(AnnotatedElement annotatedElement, IndexedDeclarationAnnotationAdapter idaa) {
+ super(annotatedElement, idaa);
+ this.idaa = idaa;
+ }
+
+
+ // ********** IndexedAnnotationAdapter implementation **********
+
+ public int getIndex() {
+ return this.idaa.getIndex();
+ }
+
+ public void moveAnnotation(int newIndex) {
+ this.edit(this.buildMoveAnnotationEditor(newIndex));
+ }
+
+
+ // ********** factory methods **********
+
+ protected AnnotatedElement.Editor buildMoveAnnotationEditor(int newIndex) {
+ return new MoveAnnotationEditor(this.idaa, newIndex);
+ }
+
+
+ // ********** member classes **********
+
+ protected static class MoveAnnotationEditor implements AnnotatedElement.Editor {
+ private final IndexedDeclarationAnnotationAdapter idaa;
+ private int index;
+
+ MoveAnnotationEditor(IndexedDeclarationAnnotationAdapter idaa, int index) {
+ super();
+ this.idaa = idaa;
+ this.index = index;
+ }
+ public void edit(ModifiedDeclaration declaration) {
+ this.idaa.moveAnnotation(this.index, declaration);
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/EnumArrayDeclarationAnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/EnumArrayDeclarationAnnotationElementAdapter.java
new file mode 100644
index 0000000000..330e98303e
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/EnumArrayDeclarationAnnotationElementAdapter.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.List;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ArrayInitializer;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationElementAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Wrap a declaration annotation element adapter and simply
+ * add an import for the enums when necessary.
+ */
+public class EnumArrayDeclarationAnnotationElementAdapter
+ implements DeclarationAnnotationElementAdapter<String[]>
+{
+ /**
+ * The wrapped adapter that returns and takes name strings (enums).
+ */
+ private final ConversionDeclarationAnnotationElementAdapter<String[]> adapter;
+
+
+ // ********** constructors **********
+
+ /**
+ * The default element name is <code>value</code>.
+ * The default behavior is to remove the array initializer if it is empty.
+ */
+ public EnumArrayDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter) {
+ this(annotationAdapter, VALUE);
+ }
+
+ /**
+ * The default behavior is to remove the array initializer if it is empty.
+ */
+ public EnumArrayDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+ this(annotationAdapter, elementName, true);
+ }
+
+ public EnumArrayDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeArrayInitializerWhenEmpty) {
+ this(new ConversionDeclarationAnnotationElementAdapter<String[]>(annotationAdapter, elementName, buildExpressionConverter(removeArrayInitializerWhenEmpty)));
+ }
+
+ private static ExpressionConverter<String[]> buildExpressionConverter(boolean removeArrayInitializerWhenEmpty) {
+ return new AnnotationStringArrayExpressionConverter(NameStringExpressionConverter.instance(), removeArrayInitializerWhenEmpty);
+ }
+
+ protected EnumArrayDeclarationAnnotationElementAdapter(ConversionDeclarationAnnotationElementAdapter<String[]> adapter) {
+ super();
+ this.adapter = adapter;
+ }
+
+
+ // ********** DeclarationAnnotationElementAdapter implementation **********
+
+ public String[] getValue(ModifiedDeclaration declaration) {
+ // ignore the adapter's getValue() - we want the expression
+ return this.resolve(this.adapter.getExpression(declaration), declaration);
+ }
+
+ public void setValue(String[] value, ModifiedDeclaration declaration) {
+ this.adapter.setValue(this.convertToSourceCodeNames(value, declaration), declaration);
+ }
+
+ public Expression getExpression(ModifiedDeclaration declaration) {
+ return this.adapter.getExpression(declaration);
+ }
+
+ public ASTNode getAstNode(ModifiedDeclaration declaration) {
+ return this.adapter.getAstNode(declaration);
+ }
+
+
+ // ********** internal methods **********
+
+ /**
+ * resolve the enums, which can be
+ * null
+ * or
+ * {FOO, BAR, BAZ}
+ * or
+ * FOO
+ */
+ protected String[] resolve(Expression expression, ModifiedDeclaration declaration) {
+ if (expression == null) {
+ return StringTools.EMPTY_STRING_ARRAY;
+ } else if (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) {
+ return this.resolveArray((ArrayInitializer) expression, declaration);
+ } else {
+ return this.resolveSingleElement(expression, declaration);
+ }
+ }
+
+ protected String[] resolveArray(ArrayInitializer ai, @SuppressWarnings("unused") ModifiedDeclaration declaration) {
+ List<Expression> expressions = this.expressions(ai);
+ int len = expressions.size();
+ String[] enums = new String[len];
+ for (int i = len; i-- > 0; ) {
+ enums[i] = this.resolveEnum(expressions.get(i));
+ }
+ return enums;
+ }
+
+ protected String[] resolveSingleElement(Expression enumExpression, @SuppressWarnings("unused") ModifiedDeclaration declaration) {
+ return new String[] {this.resolveEnum(enumExpression)};
+ }
+
+ protected String resolveEnum(Expression expression) {
+ return ASTTools.resolveEnum(expression);
+ }
+
+ // minimize scope of suppressd warnings
+ @SuppressWarnings("unchecked")
+ private List<Expression> expressions(ArrayInitializer arrayInitializer) {
+ return arrayInitializer.expressions();
+ }
+
+ /**
+ * convert the fully-qualified enums to names that can be inserted in source code
+ * NB: imports may be added as a side-effect :-(
+ */
+ protected String[] convertToSourceCodeNames(String[] enums, ModifiedDeclaration declaration) {
+ if (enums == null) {
+ return null;
+ }
+ int len = enums.length;
+ String[] sourceCodeNames = new String[len];
+ for (int i = 0; i < len; i++) {
+ sourceCodeNames[i] = this.convertToSourceCodeName(enums[i], declaration);
+ }
+ return sourceCodeNames;
+ }
+
+ protected String convertToSourceCodeName(String enum_, ModifiedDeclaration declaration) {
+ return EnumDeclarationAnnotationElementAdapter.convertToSourceCodeName(enum_, declaration);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/EnumDeclarationAnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/EnumDeclarationAnnotationElementAdapter.java
new file mode 100644
index 0000000000..21cbe29aaa
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/EnumDeclarationAnnotationElementAdapter.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationElementAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+
+/**
+ * Wrap a declaration annotation element adapter and simply
+ * add an import for the enum when necessary.
+ */
+public class EnumDeclarationAnnotationElementAdapter
+ implements DeclarationAnnotationElementAdapter<String>
+{
+ /**
+ * The wrapped adapter that returns and takes name strings (enums).
+ */
+ private final ConversionDeclarationAnnotationElementAdapter<String> adapter;
+
+
+ // ********** constructors **********
+
+ /**
+ * The default element name is <code>value</code>.
+ */
+ public EnumDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter) {
+ this(annotationAdapter, VALUE);
+ }
+
+ public EnumDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+ this(new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, NameStringExpressionConverter.instance()));
+ }
+
+ protected EnumDeclarationAnnotationElementAdapter(ConversionDeclarationAnnotationElementAdapter<String> adapter) {
+ super();
+ this.adapter = adapter;
+ }
+
+
+ // ********** DeclarationAnnotationElementAdapter implementation **********
+
+ public String getValue(ModifiedDeclaration declaration) {
+ return this.resolve(this.adapter.getExpression(declaration));
+ }
+
+ public void setValue(String value, ModifiedDeclaration declaration) {
+ this.adapter.setValue(convertToSourceCodeName(value, declaration), declaration);
+ }
+
+ public Expression getExpression(ModifiedDeclaration declaration) {
+ return this.adapter.getExpression(declaration);
+ }
+
+ public ASTNode getAstNode(ModifiedDeclaration declaration) {
+ return this.adapter.getAstNode(declaration);
+ }
+
+
+ // ********** internal methods **********
+
+ /**
+ * resolve the enum
+ */
+ protected String resolve(Expression expression) {
+ return ASTTools.resolveEnum(expression);
+ }
+
+ /**
+ * convert the fully-qualified enum constant to a static import and the constant's short name, e.g.
+ * static import javax.persistence.FetchType.EAGER;
+ * return "EAGER"
+ * if that doesn't work, convert to a normal import and the constant's partially-qualified name, e.g.
+ * import javax.persistence.FetchType;
+ * return "FetchType.EAGER"
+ * if that doesn't work, simply return the constant's fully-qualified name, e.g.
+ * return "javax.persistence.FetchType.EAGER"
+ * NB: an import may be added as a side-effect :-(
+ */
+ protected static String convertToSourceCodeName(String enumConstantName, ModifiedDeclaration declaration) {
+ return (enumConstantName == null) ? null : convertToSourceCodeName_(enumConstantName, declaration);
+ }
+
+ /**
+ * pre-condition: enum constant name is non-null;
+ * convert it to its short version if we can add a static import etc.
+ */
+ protected static String convertToSourceCodeName_(String enumConstantName, ModifiedDeclaration declaration) {
+ if (declaration.addStaticImport(enumConstantName)) {
+ return convertToShortName(enumConstantName);
+ }
+ if (declaration.addImport(convertToTypeName(enumConstantName))) {
+ return convertToPartiallyQualifiedName(enumConstantName);
+ }
+ return enumConstantName;
+ }
+
+ protected static String convertToShortName(String name) {
+ return name.substring(name.lastIndexOf('.') + 1);
+ }
+
+ protected static String convertToTypeName(String name) {
+ return name.substring(0, name.lastIndexOf('.'));
+ }
+
+ protected static String convertToPartiallyQualifiedName(String name) {
+ return name.substring(name.lastIndexOf('.', name.lastIndexOf('.') - 1) + 1);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ExpressionDeclarationAnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ExpressionDeclarationAnnotationElementAdapter.java
new file mode 100644
index 0000000000..b5af2afadf
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ExpressionDeclarationAnnotationElementAdapter.java
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.MarkerAnnotation;
+import org.eclipse.jdt.core.dom.MemberValuePair;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationElementAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Most obvious implementation of the interface.
+ * Assume the element's value is an Expression.
+ */
+public class ExpressionDeclarationAnnotationElementAdapter<E extends Expression>
+ implements DeclarationAnnotationElementAdapter<E>
+{
+ /**
+ * Adapter used to manipulate the element's annotation.
+ */
+ private final DeclarationAnnotationAdapter annotationAdapter;
+
+ /**
+ * The name of the relevant annotation element.
+ */
+ private final String elementName;
+
+
+ // ********** constructors **********
+
+ /**
+ * The default element name is <code>value</code>.
+ */
+ public ExpressionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter) {
+ this(annotationAdapter, VALUE);
+ }
+
+ public ExpressionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+ this.annotationAdapter = annotationAdapter;
+ this.elementName = elementName;
+ }
+
+
+ // ********** DeclarationAnnotationElementAdapter implementation **********
+
+ public E getValue(ModifiedDeclaration declaration) {
+ // return the expression unmodified
+ return this.getExpression(declaration);
+ }
+
+ public void setValue(E value, ModifiedDeclaration declaration) {
+ this.setValue(value, this.annotationAdapter.getAnnotation(declaration), declaration);
+ }
+
+ public E getExpression(ModifiedDeclaration declaration) {
+ return this.expression(this.annotationAdapter.getAnnotation(declaration));
+ }
+
+ public ASTNode getAstNode(ModifiedDeclaration declaration) {
+ Expression exp = this.getExpression(declaration);
+ return (exp != null) ? exp : this.annotationAdapter.getAstNode(declaration);
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.elementName);
+ }
+
+
+ // ********** expression **********
+
+ /**
+ * Return the expression value of the *first* annotation element
+ * with the adapter's element name.
+ * Return null if the annotation has no such element.
+ * (An element name of "value" will return the value of a single
+ * member annotation.)
+ */
+ protected E expression(Annotation annotation) {
+ if (annotation == null) {
+ return this.expressionNoAnnotation();
+ }
+ if (annotation.isMarkerAnnotation()) {
+ return this.expressionMarkerAnnotation((MarkerAnnotation) annotation);
+ }
+ if (annotation.isSingleMemberAnnotation()) {
+ return this.expressionSingleMemberAnnotation((SingleMemberAnnotation) annotation);
+ }
+ if (annotation.isNormalAnnotation()) {
+ return this.expressionNormalAnnotation((NormalAnnotation) annotation);
+ }
+ throw new IllegalArgumentException("unknown annotation type: " + annotation); //$NON-NLS-1$
+ }
+
+ protected E expressionNoAnnotation() {
+ return null;
+ }
+
+ /**
+ * Return the expression value of the *first* annotation element
+ * with the adapter's element name.
+ * Return null if the annotation has no such element.
+ */
+ protected E expressionMarkerAnnotation(@SuppressWarnings("unused") MarkerAnnotation annotation) {
+ return null;
+ }
+
+ /**
+ * Return the expression value of the *first* annotation element
+ * with the adapter's element name.
+ * Return null if the annotation has no such element.
+ */
+ protected E expressionSingleMemberAnnotation(SingleMemberAnnotation annotation) {
+ return this.downcast(this.elementName.equals(VALUE) ? annotation.getValue() : null);
+ }
+
+ @SuppressWarnings("unchecked")
+ private E downcast(Expression e) {
+ return (E) e;
+ }
+
+ /**
+ * Return the expression value of the *first* annotation element
+ * with the adapter's element name.
+ * Return null if the annotation has no such element.
+ */
+ protected E expressionNormalAnnotation(NormalAnnotation annotation) {
+ MemberValuePair pair = this.memberValuePair(annotation);
+ return this.downcast((pair == null) ? null : pair.getValue());
+ }
+
+
+ // ********** set value **********
+
+ /**
+ * set non-null, non-empty value
+ */
+ protected void setValue(Expression value, Annotation annotation, ModifiedDeclaration declaration) {
+ if (value == null) {
+ this.removeElement(annotation, declaration);
+ }
+ else if (annotation == null) {
+ this.setValueNoAnnotation(value, declaration);
+ }
+ else if (annotation.isMarkerAnnotation()) {
+ this.setValueMarkerAnnotation(value, (MarkerAnnotation) annotation, declaration);
+ }
+ else if (annotation.isSingleMemberAnnotation()) {
+ this.setValueSingleMemberAnnotation(value, (SingleMemberAnnotation) annotation, declaration);
+ }
+ else if (annotation.isNormalAnnotation()) {
+ this.setValueNormalAnnotation(value, (NormalAnnotation) annotation, declaration);
+ }
+ else {
+ throw new IllegalArgumentException("unknown annotation type: " + annotation); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * add non-null, non-empty value
+ */
+ protected void setValueNoAnnotation(Expression value, ModifiedDeclaration declaration) {
+ if (this.elementName.equals(VALUE)) {
+ // @Foo("xxx")
+ this.annotationAdapter.newSingleMemberAnnotation(declaration).setValue(value);
+ } else {
+ // @Foo(bar="xxx")
+ this.addValue(value, this.annotationAdapter.newNormalAnnotation(declaration));
+ }
+ }
+
+ protected void addValue(Expression value, NormalAnnotation annotation) {
+ this.addValue(value, annotation, this.elementName);
+ }
+
+ protected void addValue(Expression value, NormalAnnotation annotation, String annotationElementName) {
+ AST ast = annotation.getAST();
+ MemberValuePair pair = ast.newMemberValuePair();
+ pair.setName(ast.newSimpleName(annotationElementName));
+ pair.setValue(value);
+ List<MemberValuePair> values = this.values(annotation);
+ values.add(pair);
+ }
+
+ protected void setValueMarkerAnnotation(Expression value, @SuppressWarnings("unused") MarkerAnnotation annotation, ModifiedDeclaration declaration) {
+ // @Foo => @Foo("xxx")
+ // or
+ // @Foo => @Foo(bar="xxx")
+ this.setValueNoAnnotation(value, declaration);
+ }
+
+ protected void setValueSingleMemberAnnotation(Expression value, SingleMemberAnnotation annotation, ModifiedDeclaration declaration) {
+ if (this.elementName.equals(VALUE)) {
+ // @Foo("yyy") => @Foo("xxx")
+ annotation.setValue(value);
+ } else {
+ // @Foo("yyy") => @Foo(value="yyy", bar="xxx")
+ Expression vv = annotation.getValue();
+ vv = (Expression) ASTNode.copySubtree(vv.getAST(), vv);
+ NormalAnnotation normalAnnotation = this.annotationAdapter.newNormalAnnotation(declaration);
+ this.addValue(vv, normalAnnotation, VALUE);
+ this.addValue(value, normalAnnotation);
+ }
+ }
+
+ protected void setValueNormalAnnotation(Expression value, NormalAnnotation annotation, @SuppressWarnings("unused") ModifiedDeclaration declaration) {
+ MemberValuePair pair = this.memberValuePair(annotation);
+ if (pair == null) {
+ this.addValue(value, annotation);
+ } else {
+ pair.setValue(value);
+ }
+ }
+
+
+ // ********** remove element **********
+
+ protected void removeElement(Annotation annotation, ModifiedDeclaration declaration) {
+ if (annotation == null) {
+ this.removeElementNoAnnotation(declaration);
+ }
+ else if (annotation.isMarkerAnnotation()) {
+ this.removeElementMarkerAnnotation((MarkerAnnotation) annotation, declaration);
+ }
+ else if (annotation.isSingleMemberAnnotation()) {
+ this.removeElementSingleMemberAnnotation((SingleMemberAnnotation) annotation, declaration);
+ }
+ else if (annotation.isNormalAnnotation()) {
+ this.removeElementNormalAnnotation((NormalAnnotation) annotation, declaration);
+ }
+ else {
+ throw new IllegalArgumentException("unknown annotation type: " + annotation); //$NON-NLS-1$
+ }
+ }
+
+ protected void removeElementNoAnnotation(@SuppressWarnings("unused") ModifiedDeclaration declaration) {
+ // the element is already gone (?)
+ }
+
+ protected void removeElementMarkerAnnotation(@SuppressWarnings("unused") MarkerAnnotation annotation, @SuppressWarnings("unused") ModifiedDeclaration declaration) {
+ // the element is already gone (?)
+ }
+
+ protected void removeElementSingleMemberAnnotation(@SuppressWarnings("unused") SingleMemberAnnotation annotation, ModifiedDeclaration declaration) {
+ if (this.elementName.equals(VALUE)) {
+ // @Foo("xxx") => @Foo
+ this.annotationAdapter.newMarkerAnnotation(declaration);
+ } else {
+ // the [non-'value'] element is already gone (?)
+ }
+ }
+
+ protected void removeElementNormalAnnotation(NormalAnnotation annotation, ModifiedDeclaration declaration) {
+ List<MemberValuePair> values = this.values(annotation);
+ if ((values.size() == 1) && values.get(0).getName().getFullyQualifiedName().equals(this.elementName)) {
+ // @Foo(bar="xxx") => @Foo
+ this.annotationAdapter.newMarkerAnnotation(declaration);
+ } else {
+ this.removeElement(annotation);
+ if (values.size() == 1) {
+ MemberValuePair pair = values.get(0);
+ if (pair.getName().getFullyQualifiedName().equals(VALUE)) {
+ // @Foo(bar="xxx", value="yyy") => @Foo("yyy")
+ Expression vv = pair.getValue();
+ vv = (Expression) ASTNode.copySubtree(vv.getAST(), vv);
+ this.annotationAdapter.newSingleMemberAnnotation(declaration).setValue(vv);
+ } else {
+ // @Foo(bar="xxx", baz="yyy") => @Foo(baz="yyy")
+ }
+ } else {
+ // @Foo(bar="xxx", baz="yyy", joo="xxx") => @Foo(baz="yyy", joo="xxx")
+ }
+ }
+ }
+
+ /**
+ * Remove the *first* member value pair from the specified annotation element
+ * with the adapter's element name.
+ */
+ protected void removeElement(NormalAnnotation annotation) {
+ for (Iterator<MemberValuePair> stream = this.values(annotation).iterator(); stream.hasNext(); ) {
+ MemberValuePair pair = stream.next();
+ if (pair.getName().getFullyQualifiedName().equals(this.elementName)) {
+ stream.remove();
+ }
+ }
+ }
+
+
+ // ********** convenience methods **********
+
+ /**
+ * Return the *first* member value pair for the specified annotation element
+ * with the adapter's element name.
+ * Return null if the annotation has no such element.
+ */
+ protected MemberValuePair memberValuePair(NormalAnnotation annotation) {
+ for (MemberValuePair pair : this.values(annotation)) {
+ if (pair.getName().getFullyQualifiedName().equals(this.elementName)) {
+ return pair;
+ }
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected List<MemberValuePair> values(NormalAnnotation na) {
+ return na.values();
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/GenericVisitor.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/GenericVisitor.java
new file mode 100644
index 0000000000..92160afdf5
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/GenericVisitor.java
@@ -0,0 +1,791 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
+import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
+import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
+import org.eclipse.jdt.core.dom.ArrayAccess;
+import org.eclipse.jdt.core.dom.ArrayCreation;
+import org.eclipse.jdt.core.dom.ArrayInitializer;
+import org.eclipse.jdt.core.dom.ArrayType;
+import org.eclipse.jdt.core.dom.AssertStatement;
+import org.eclipse.jdt.core.dom.Assignment;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.BlockComment;
+import org.eclipse.jdt.core.dom.BooleanLiteral;
+import org.eclipse.jdt.core.dom.BreakStatement;
+import org.eclipse.jdt.core.dom.CastExpression;
+import org.eclipse.jdt.core.dom.CatchClause;
+import org.eclipse.jdt.core.dom.CharacterLiteral;
+import org.eclipse.jdt.core.dom.ClassInstanceCreation;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.ConditionalExpression;
+import org.eclipse.jdt.core.dom.ConstructorInvocation;
+import org.eclipse.jdt.core.dom.ContinueStatement;
+import org.eclipse.jdt.core.dom.DoStatement;
+import org.eclipse.jdt.core.dom.EmptyStatement;
+import org.eclipse.jdt.core.dom.EnhancedForStatement;
+import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
+import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.ExpressionStatement;
+import org.eclipse.jdt.core.dom.FieldAccess;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.ForStatement;
+import org.eclipse.jdt.core.dom.IfStatement;
+import org.eclipse.jdt.core.dom.ImportDeclaration;
+import org.eclipse.jdt.core.dom.InfixExpression;
+import org.eclipse.jdt.core.dom.Initializer;
+import org.eclipse.jdt.core.dom.InstanceofExpression;
+import org.eclipse.jdt.core.dom.Javadoc;
+import org.eclipse.jdt.core.dom.LabeledStatement;
+import org.eclipse.jdt.core.dom.LineComment;
+import org.eclipse.jdt.core.dom.MarkerAnnotation;
+import org.eclipse.jdt.core.dom.MemberRef;
+import org.eclipse.jdt.core.dom.MemberValuePair;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.MethodInvocation;
+import org.eclipse.jdt.core.dom.MethodRef;
+import org.eclipse.jdt.core.dom.MethodRefParameter;
+import org.eclipse.jdt.core.dom.Modifier;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.NullLiteral;
+import org.eclipse.jdt.core.dom.NumberLiteral;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.dom.ParameterizedType;
+import org.eclipse.jdt.core.dom.ParenthesizedExpression;
+import org.eclipse.jdt.core.dom.PostfixExpression;
+import org.eclipse.jdt.core.dom.PrefixExpression;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.QualifiedName;
+import org.eclipse.jdt.core.dom.QualifiedType;
+import org.eclipse.jdt.core.dom.ReturnStatement;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.dom.SimpleType;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.StringLiteral;
+import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
+import org.eclipse.jdt.core.dom.SuperFieldAccess;
+import org.eclipse.jdt.core.dom.SuperMethodInvocation;
+import org.eclipse.jdt.core.dom.SwitchCase;
+import org.eclipse.jdt.core.dom.SwitchStatement;
+import org.eclipse.jdt.core.dom.SynchronizedStatement;
+import org.eclipse.jdt.core.dom.TagElement;
+import org.eclipse.jdt.core.dom.TextElement;
+import org.eclipse.jdt.core.dom.ThisExpression;
+import org.eclipse.jdt.core.dom.ThrowStatement;
+import org.eclipse.jdt.core.dom.TryStatement;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
+import org.eclipse.jdt.core.dom.TypeLiteral;
+import org.eclipse.jdt.core.dom.TypeParameter;
+import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
+import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
+import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
+import org.eclipse.jdt.core.dom.WhileStatement;
+import org.eclipse.jdt.core.dom.WildcardType;
+
+/**
+ * copied from org.eclipse.jdt.internal.corext.dom.GenericVisitor
+ */
+public class GenericVisitor extends ASTVisitor {
+
+ public GenericVisitor() {
+ super();
+ }
+
+ public GenericVisitor(boolean visitJavadocTags) {
+ super(visitJavadocTags);
+ }
+
+ // ********** hooks for subclasses **********
+
+ protected boolean visit_(@SuppressWarnings("unused") ASTNode node) {
+ return true;
+ }
+
+ protected void endVisit_(@SuppressWarnings("unused") ASTNode node) {
+ // do nothing
+ }
+
+ // ********** overrides **********
+
+ @Override
+ public boolean visit(AnonymousClassDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ArrayAccess node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ArrayCreation node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ArrayInitializer node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ArrayType node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(AssertStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(Assignment node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(Block node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(BooleanLiteral node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(BreakStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(CastExpression node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(CatchClause node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(CharacterLiteral node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ClassInstanceCreation node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(CompilationUnit node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ConditionalExpression node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ConstructorInvocation node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ContinueStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(DoStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(EmptyStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ExpressionStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(FieldAccess node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(FieldDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ForStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(IfStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ImportDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(InfixExpression node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(InstanceofExpression node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(Initializer node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(Javadoc node) {
+ return (super.visit(node)) ? visit_(node) : false;
+ }
+ @Override
+ public boolean visit(LabeledStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(MethodDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(MethodInvocation node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(NullLiteral node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(NumberLiteral node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(PackageDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ParenthesizedExpression node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(PostfixExpression node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(PrefixExpression node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(PrimitiveType node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(QualifiedName node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ReturnStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SimpleName node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SimpleType node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(StringLiteral node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SuperConstructorInvocation node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SuperFieldAccess node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SuperMethodInvocation node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SwitchCase node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SwitchStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SynchronizedStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ThisExpression node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ThrowStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(TryStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(TypeDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(TypeDeclarationStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(TypeLiteral node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SingleVariableDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(VariableDeclarationExpression node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(VariableDeclarationStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(VariableDeclarationFragment node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(WhileStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(AnnotationTypeDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(AnnotationTypeMemberDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(BlockComment node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(EnhancedForStatement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(EnumConstantDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(EnumDeclaration node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(LineComment node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(MarkerAnnotation node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(MemberRef node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(MemberValuePair node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(MethodRef node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(MethodRefParameter node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(Modifier node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(NormalAnnotation node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(ParameterizedType node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(QualifiedType node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(SingleMemberAnnotation node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(TagElement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(TextElement node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(TypeParameter node) {
+ return visit_(node);
+ }
+ @Override
+ public boolean visit(WildcardType node) {
+ return visit_(node);
+ }
+
+ @Override
+ public void endVisit(AnonymousClassDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ArrayAccess node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ArrayCreation node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ArrayInitializer node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ArrayType node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(AssertStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(Assignment node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(Block node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(BooleanLiteral node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(BreakStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(CastExpression node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(CatchClause node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(CharacterLiteral node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ClassInstanceCreation node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(CompilationUnit node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ConditionalExpression node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ConstructorInvocation node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ContinueStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(DoStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(EmptyStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ExpressionStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(FieldAccess node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(FieldDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ForStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(IfStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ImportDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(InfixExpression node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(InstanceofExpression node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(Initializer node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(Javadoc node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(LabeledStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(MethodDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(MethodInvocation node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(NullLiteral node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(NumberLiteral node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(PackageDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ParenthesizedExpression node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(PostfixExpression node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(PrefixExpression node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(PrimitiveType node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(QualifiedName node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ReturnStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SimpleName node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SimpleType node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(StringLiteral node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SuperConstructorInvocation node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SuperFieldAccess node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SuperMethodInvocation node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SwitchCase node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SwitchStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SynchronizedStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ThisExpression node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ThrowStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(TryStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(TypeDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(TypeDeclarationStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(TypeLiteral node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SingleVariableDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(VariableDeclarationExpression node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(VariableDeclarationStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(VariableDeclarationFragment node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(WhileStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(AnnotationTypeDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(AnnotationTypeMemberDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(BlockComment node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(EnhancedForStatement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(EnumConstantDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(EnumDeclaration node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(LineComment node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(MarkerAnnotation node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(MemberRef node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(MemberValuePair node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(MethodRef node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(MethodRefParameter node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(Modifier node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(NormalAnnotation node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(ParameterizedType node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(QualifiedType node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(SingleMemberAnnotation node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(TagElement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(TextElement node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(TypeParameter node) {
+ endVisit_(node);
+ }
+ @Override
+ public void endVisit(WildcardType node) {
+ endVisit_(node);
+ }
+
+}
+
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTAnnotatedElement.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTAnnotatedElement.java
new file mode 100644
index 0000000000..f19653b191
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTAnnotatedElement.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.LocationKind;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotatedElement;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.Command;
+import org.eclipse.jpt.utility.CommandExecutor;
+import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * Adapt and extend a JDT member with simplified annotation handling.
+ */
+public abstract class JDTAnnotatedElement
+ implements AnnotatedElement
+{
+
+ /** the annotated element's name (duh) */
+ private final String name;
+
+ /**
+ * the compilation unit (file) containing the annotated element;
+ * used for building an AST when we modify the annotated element
+ */
+ private final ICompilationUnit compilationUnit;
+
+ /**
+ * this allows clients to provide a way to modify the compilation unit
+ * (file) when it is open in an editor and should be modified on the UI
+ * thread
+ */
+ private final CommandExecutor modifySharedDocumentCommandExecutor;
+
+ /** this will format the annotated element's annotations a bit */
+ private final AnnotationEditFormatter annotationEditFormatter;
+
+
+ // ********** constructors **********
+
+ protected JDTAnnotatedElement(
+ String name,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(name, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ protected JDTAnnotatedElement(
+ String name,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super();
+ this.name = name;
+ this.compilationUnit = compilationUnit;
+ this.modifySharedDocumentCommandExecutor = modifySharedDocumentCommandExecutor;
+ this.annotationEditFormatter = annotationEditFormatter;
+ }
+
+
+ // ********** AnnotatedElement implementation **********
+
+ public String getName() {
+ return this.name;
+ }
+
+ public abstract ModifiedDeclaration getModifiedDeclaration(CompilationUnit astRoot);
+
+ public ModifiedDeclaration getModifiedDeclaration() {
+ return this.getModifiedDeclaration(this.buildASTRoot());
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.name);
+ }
+
+
+ // ********** editing **********
+
+ /**
+ * Edit the member with the specified editor.
+ * The editor will be invoked once the member's compilation unit
+ * is in an editable state.
+ */
+ public void edit(Editor editor) {
+ try {
+ this.edit_(editor);
+ } catch (JavaModelException ex) {
+ throw new RuntimeException(ex);
+ } catch (BadLocationException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * NB: Be careful changing this method.
+ * Things to look out for:
+ * - when editing via the JavaEditor there is no need to create a working copy
+ * - when editing without an editor or via a simple text editor, a "working copy" must be created.
+ * (at least as far as I can tell ~kfm)
+ * - sharedDocument is only ever false in tests (headless mode). In the UI, even if the file
+ * is not open in an editor, sharedDocument is still true (buffer is not null)
+ * - if a working copy is created, then we must discard it
+ */
+ protected void edit_(Editor editor) throws JavaModelException, BadLocationException {
+ boolean createWorkingCopy = ! this.compilationUnit.isWorkingCopy();
+ if (createWorkingCopy) {
+ this.compilationUnit.becomeWorkingCopy(null);
+ }
+
+ ITextFileBuffer buffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(this.compilationUnit.getResource().getFullPath(), LocationKind.NORMALIZE);
+ boolean sharedDocument = (buffer != null); // documents are typically shared when they are already open in an editor
+ IDocument doc = sharedDocument ?
+ buffer.getDocument() :
+ new Document(this.compilationUnit.getBuffer().getContents());
+
+ try {
+ CompilationUnit astRoot = this.buildASTRoot();
+ astRoot.recordModifications();
+
+ editor.edit(this.getModifiedDeclaration(astRoot));
+
+ TextEdit edits = astRoot.rewrite(doc, this.compilationUnit.getJavaProject().getOptions(true));
+ if (sharedDocument) {
+ this.modifySharedDocumentCommandExecutor.execute(new ModifySharedDocumentCommand(edits, doc));
+ } else {
+ this.applyEdits(edits, doc);
+ }
+ }
+ finally {
+ if (createWorkingCopy) {
+ //discardWorkingCopy must be called every time becomeWorkingCopy is called.
+ this.compilationUnit.getBuffer().setContents(doc.get());
+ this.compilationUnit.commitWorkingCopy(true, null); // true="force"
+ this.compilationUnit.discardWorkingCopy();
+ }
+ }
+ }
+
+ /**
+ * apply the specified edits to the specified document,
+ * reformatting the document if necessary
+ */
+ protected void applyEdits(TextEdit edits, IDocument doc) throws MalformedTreeException, BadLocationException {
+ edits.apply(doc, TextEdit.UPDATE_REGIONS);
+ this.annotationEditFormatter.format(doc, edits);
+ }
+
+ protected CompilationUnit buildASTRoot() {
+ return ASTTools.buildASTRoot(this.compilationUnit);
+ }
+
+
+ // ********** modify shared document command class **********
+
+ /**
+ * simple command that calls back to the member to apply the edits
+ * in the same way as if the document were not shared
+ */
+ protected class ModifySharedDocumentCommand implements Command {
+ private final TextEdit edits;
+ private final IDocument doc;
+
+ protected ModifySharedDocumentCommand(TextEdit edits, IDocument doc) {
+ super();
+ this.edits = edits;
+ this.doc = doc;
+ }
+
+ public void execute() {
+ try {
+ JDTAnnotatedElement.this.applyEdits(this.edits, this.doc);
+ } catch (MalformedTreeException ex) {
+ throw new RuntimeException(ex);
+ } catch (BadLocationException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTEnum.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTEnum.java
new file mode 100644
index 0000000000..7fdff3c5c6
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTEnum.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.List;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
+import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.jpt.common.core.utility.jdt.Enum;
+import org.eclipse.jpt.common.core.utility.jdt.Type;
+import org.eclipse.jpt.utility.CommandExecutor;
+
+/**
+ * Adapt and extend a JDT enum.
+ */
+public class JDTEnum
+ extends AbstractJDTType
+ implements Enum
+{
+
+ /**
+ * constructor for the compilation unit's primary type, an enum
+ */
+ public JDTEnum(
+ EnumDeclaration enumDeclaration,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(enumDeclaration, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ /**
+ * constructor for the compilation unit's primary type, an enum
+ */
+ public JDTEnum(
+ EnumDeclaration enumDeclaration,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super(null, enumDeclaration, 1, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ /**
+ * constructor for nested enums
+ */
+ public JDTEnum(
+ Type declaringType,
+ EnumDeclaration enumDeclaration,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(declaringType, enumDeclaration, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ /**
+ * constructor for nested enums
+ */
+ public JDTEnum(
+ Type declaringType,
+ EnumDeclaration enumDeclaration,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super(declaringType, enumDeclaration, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ /**
+ * constructor for testing
+ */
+ public JDTEnum(Type declaringType, String name, int occurrence, ICompilationUnit compilationUnit) {
+ super(declaringType, name, occurrence, compilationUnit);
+ }
+
+ @Override
+ public EnumDeclaration getBodyDeclaration(CompilationUnit astRoot) {
+ return (EnumDeclaration) super.getBodyDeclaration(astRoot);
+ }
+
+ public boolean isPersistable(CompilationUnit astRoot) {
+ return true;
+ }
+
+ public EnumConstantDeclaration[] getEnumConstants(CompilationUnit astRoot) {
+ List<EnumConstantDeclaration> enumConstants = enumConstants(getBodyDeclaration(astRoot));
+ return enumConstants.toArray(new EnumConstantDeclaration[enumConstants.size()]);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static List<EnumConstantDeclaration> enumConstants(EnumDeclaration ed) {
+ return ed.enumConstants();
+ }
+
+
+ // ********** internal **********
+
+ @Override
+ protected EnumDeclaration getTopLevelTypeDeclaration(CompilationUnit astRoot) {
+ return (EnumDeclaration) super.getTopLevelTypeDeclaration(astRoot);
+ }
+
+ @Override
+ protected EnumDeclaration getTypeDeclaration(List<AbstractTypeDeclaration> typeDeclarations) {
+ return (EnumDeclaration) super.getTypeDeclaration(typeDeclarations);
+ }
+
+ @Override
+ protected EnumDeclaration getNestedTypeDeclaration(TypeDeclaration declaringTypeDeclaration) {
+ return this.getTypeDeclaration(getEnums(declaringTypeDeclaration));
+ }
+
+ @Override
+ protected EnumDeclaration getTypeDeclaration(AbstractTypeDeclaration[] typeDeclarations) {
+ return (EnumDeclaration) super.getTypeDeclaration(typeDeclarations);
+ }
+
+ @Override
+ protected int getASTNodeType() {
+ return ASTNode.ENUM_DECLARATION;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTEnumConstant.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTEnumConstant.java
new file mode 100644
index 0000000000..572721885a
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTEnumConstant.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.List;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
+import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.jpt.common.core.utility.jdt.Enum;
+import org.eclipse.jpt.common.core.utility.jdt.EnumConstant;
+import org.eclipse.jpt.utility.CommandExecutor;
+
+/**
+ * Adapt and extend a JDT enum constant.
+ */
+public class JDTEnumConstant
+ extends JDTMember
+ implements EnumConstant
+{
+
+ // ********** constructors **********
+
+ public JDTEnumConstant(
+ Enum declaringEnum,
+ String name,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(declaringEnum, name, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ public JDTEnumConstant(
+ Enum declaringEnum,
+ String name,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super(declaringEnum, name, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ /**
+ * constructor for testing
+ */
+ public JDTEnumConstant(Enum declaringEnum, String name, int occurrence, ICompilationUnit compilationUnit) {
+ this(declaringEnum, name, occurrence, compilationUnit, CommandExecutor.Default.instance(), DefaultAnnotationEditFormatter.instance());
+ }
+
+ @Override
+ protected Enum getDeclaringType() {
+ return (Enum) super.getDeclaringType();
+ }
+
+ // ********** AnnotatedElement/EnumConstant implementation **********
+
+ public IVariableBinding getBinding(CompilationUnit astRoot) {
+ return this.getBodyDeclaration(astRoot).resolveVariable();
+ }
+
+ @Override
+ public EnumConstantDeclaration getBodyDeclaration(CompilationUnit astRoot) {
+ return this.getSelectedDeclaration(astRoot);
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ return new ASTNodeTextRange(this.getBodyDeclaration(astRoot).getName());
+ }
+
+ //As far as I can tell, enum constants are always "persistable",
+ //there are no modifiers you can add to an enum constant
+ public boolean isPersistable(CompilationUnit astRoot) {
+ return true;
+ }
+
+
+ // ********** internal **********
+
+ protected EnumConstantDeclaration getSelectedDeclaration(CompilationUnit astRoot) {
+ String name = this.getName();
+ int occurrence = this.getOccurrence();
+ int count = 0;
+ for (EnumConstantDeclaration enumConstantDeclaration : this.getDeclaringTypeEnumConstantDeclarations(astRoot)) {
+ if (enumConstantDeclaration.getName().getFullyQualifiedName().equals(name)) {
+ count++;
+ if (count == occurrence) {
+ return enumConstantDeclaration;
+ }
+ }
+ }
+ // return null if the field is no longer in the source code;
+ // this can happen when the context model has not yet
+ // been synchronized with the resource model but is still
+ // asking for an ASTNode (e.g. during a selection event)
+ return null;
+ }
+
+ protected EnumConstantDeclaration[] getDeclaringTypeEnumConstantDeclarations(CompilationUnit astRoot) {
+ List<EnumConstantDeclaration> enumConstants = enumConstants(this.getDeclaringTypeDeclaration(astRoot));
+ return enumConstants.toArray(new EnumConstantDeclaration[enumConstants.size()]);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static List<EnumConstantDeclaration> enumConstants(EnumDeclaration ed) {
+ return ed.enumConstants();
+ }
+
+ protected EnumDeclaration getDeclaringTypeDeclaration(CompilationUnit astRoot) {
+ return this.getDeclaringType().getBodyDeclaration(astRoot);
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTFieldAttribute.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTFieldAttribute.java
new file mode 100644
index 0000000000..befa70dda2
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTFieldAttribute.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.List;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.jpt.common.core.utility.jdt.FieldAttribute;
+import org.eclipse.jpt.common.core.utility.jdt.Type;
+import org.eclipse.jpt.utility.CommandExecutor;
+
+/**
+ * Adapt and extend a JDT field.
+ * Attribute based on a Java field, e.g.
+ * private int foo;
+ */
+public class JDTFieldAttribute
+ extends JDTMember
+ implements FieldAttribute
+{
+
+ // ********** constructors **********
+
+ public JDTFieldAttribute(
+ Type declaringType,
+ String name,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(declaringType, name, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ public JDTFieldAttribute(
+ Type declaringType,
+ String name,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super(declaringType, name, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ /**
+ * constructor for testing
+ */
+ public JDTFieldAttribute(Type declaringType, String name, int occurrence, ICompilationUnit compilationUnit) {
+ this(declaringType, name, occurrence, compilationUnit, CommandExecutor.Default.instance(), DefaultAnnotationEditFormatter.instance());
+ }
+
+
+ // ********** Member/Attribute/FieldAttribute implementation **********
+
+ @Override
+ protected Type getDeclaringType() {
+ return (Type) super.getDeclaringType();
+ }
+
+ public IVariableBinding getBinding(CompilationUnit astRoot) {
+ return this.getFragment(astRoot).resolveBinding();
+ }
+
+ @Override
+ public FieldDeclaration getBodyDeclaration(CompilationUnit astRoot) {
+ return this.getSelectedDeclaration(astRoot, FIELD_DECLARATION_SELECTOR);
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ return new ASTNodeTextRange(this.getFragment(astRoot).getName());
+ }
+
+ public String getAttributeName() {
+ return this.getName();
+ }
+
+ public ITypeBinding getTypeBinding(CompilationUnit astRoot) {
+ return this.getBodyDeclaration(astRoot).getType().resolveBinding();
+ }
+
+ public boolean isField() {
+ return true;
+ }
+
+ public boolean isPersistable(CompilationUnit astRoot) {
+ IVariableBinding binding = this.getBinding(astRoot);
+ return (binding == null) ? false : JPTTools.fieldIsPersistable(new JPTToolsAdapter(binding));
+ }
+
+
+ // ********** internal **********
+
+ protected TypeDeclaration getDeclaringTypeDeclaration(CompilationUnit astRoot) {
+ // assume the declaring type is not an enum or annotation
+ // since they do not have field or method declarations
+ return this.getDeclaringType().getBodyDeclaration(astRoot);
+ }
+
+ protected VariableDeclarationFragment getFragment(CompilationUnit astRoot) {
+ return this.getSelectedDeclaration(astRoot, VARIABLE_DECLARATION_FRAGMENT_SELECTOR);
+ }
+
+ /**
+ * return either a FieldDeclaration or a VariableDeclarationFragment,
+ * depending on the specified selector;
+ *
+ * handle multiple fields declared in a single statement:
+ * private int foo, bar;
+ */
+ protected <T extends ASTNode> T getSelectedDeclaration(CompilationUnit astRoot, Selector<T> selector) {
+ String name = this.getName();
+ int occurrence = this.getOccurrence();
+ int count = 0;
+ for (FieldDeclaration fieldDeclaration : this.getDeclaringTypeFieldDeclarations(astRoot)) {
+ for (VariableDeclarationFragment fragment : fragments(fieldDeclaration)) {
+ if (fragment.getName().getFullyQualifiedName().equals(name)) {
+ count++;
+ if (count == occurrence) {
+ return selector.select(fieldDeclaration, fragment);
+ }
+ }
+ }
+ }
+ // return null if the field is no longer in the source code;
+ // this can happen when the context model has not yet
+ // been synchronized with the resource model but is still
+ // asking for an ASTNode (e.g. during a selection event)
+ return null;
+ }
+
+ protected FieldDeclaration[] getDeclaringTypeFieldDeclarations(CompilationUnit astRoot) {
+ return this.getDeclaringTypeDeclaration(astRoot).getFields();
+ }
+
+ // minimize scope of suppressed warnings
+ @SuppressWarnings("unchecked")
+ protected static List<VariableDeclarationFragment> fragments(FieldDeclaration fd) {
+ return fd.fragments();
+ }
+
+
+ // ********** Selector **********
+
+ // I'm not quite sure this interface is worth the resulting obfuscation,
+ // but, then, I kept changing both methods, so... ~bjv
+ protected interface Selector<T extends ASTNode> {
+ T select(FieldDeclaration fieldDeclaration, VariableDeclarationFragment variableDeclarationFragment);
+ String getDescription();
+ }
+
+ protected static final Selector<FieldDeclaration> FIELD_DECLARATION_SELECTOR =
+ new Selector<FieldDeclaration>() {
+ public FieldDeclaration select(FieldDeclaration fieldDeclaration, VariableDeclarationFragment variableDeclarationFragment) {
+ return fieldDeclaration;
+ }
+ public String getDescription() {
+ return "field declaration"; //$NON-NLS-1$
+ }
+ @Override
+ public String toString() {
+ return "FIELD_DECLARATION_SELECTOR"; //$NON-NLS-1$
+ }
+ };
+
+ protected static final Selector<VariableDeclarationFragment> VARIABLE_DECLARATION_FRAGMENT_SELECTOR =
+ new Selector<VariableDeclarationFragment>() {
+ public VariableDeclarationFragment select(FieldDeclaration fieldDeclaration, VariableDeclarationFragment variableDeclarationFragment) {
+ return variableDeclarationFragment;
+ }
+ public String getDescription() {
+ return "variable declaration fragment"; //$NON-NLS-1$
+ }
+ @Override
+ public String toString() {
+ return "VARIABLE_DECLARATION_FRAGMENT_SELECTOR"; //$NON-NLS-1$
+ }
+ };
+
+
+ // ********** JPTTools adapter **********
+
+ /**
+ * JPTTools needs an adapter so it can work with either an IField
+ * or an IVariableBinding etc.
+ */
+ protected static class JPTToolsAdapter implements JPTTools.FieldAdapter {
+ private final IVariableBinding fieldBinding;
+
+ protected JPTToolsAdapter(IVariableBinding fieldBinding) {
+ super();
+ if (fieldBinding == null) {
+ throw new NullPointerException();
+ }
+ this.fieldBinding = fieldBinding;
+ }
+
+ public int getModifiers() {
+ return this.fieldBinding.getModifiers();
+ }
+
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTMember.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTMember.java
new file mode 100644
index 0000000000..dfdec73a99
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTMember.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.BodyDeclaration;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.jdt.AbstractType;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.jpt.common.core.utility.jdt.Member;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.CommandExecutor;
+
+/**
+ * Adapt and extend a JDT member with simplified annotation handling.
+ */
+public abstract class JDTMember extends JDTAnnotatedElement
+ implements Member
+{
+
+ /** this will be null for the primary type */
+ private final AbstractType declaringType;
+
+ /**
+ * members can occur more than once in non-compiling source;
+ * count starts at 1; the primary type will have occurrence 1
+ */
+ private final int occurrence;
+
+
+ // ********** constructors **********
+
+ protected JDTMember(
+ AbstractType declaringType,
+ String name,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(declaringType, name, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ protected JDTMember(
+ AbstractType declaringType,
+ String name,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super(name, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ this.declaringType = declaringType;
+ this.occurrence = occurrence;
+ }
+
+ //covariant override
+ public abstract BodyDeclaration getBodyDeclaration(CompilationUnit astRoot);
+
+
+ // ********** Member implementation **********
+
+ @Override
+ public ModifiedDeclaration getModifiedDeclaration(CompilationUnit astRoot) {
+ return new JDTModifiedDeclaration(this.getBodyDeclaration(astRoot));
+ }
+
+ public boolean matches(String memberName, int occur) {
+ return memberName.equals(this.getName()) && (occur == this.occurrence);
+ }
+
+
+ // ********** internal **********
+
+ protected int getOccurrence() {
+ return this.occurrence;
+ }
+
+ /**
+ * this will return null for a top-level type
+ */
+ protected AbstractType getDeclaringType() {
+ return this.declaringType;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTMethodAttribute.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTMethodAttribute.java
new file mode 100644
index 0000000000..f4685e2fb1
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTMethodAttribute.java
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.Arrays;
+import java.util.List;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.jpt.common.core.utility.jdt.MethodAttribute;
+import org.eclipse.jpt.common.core.utility.jdt.Type;
+import org.eclipse.jpt.utility.CommandExecutor;
+import org.eclipse.jpt.utility.JavaType;
+import org.eclipse.jpt.utility.MethodSignature;
+import org.eclipse.jpt.utility.internal.NameTools;
+import org.eclipse.jpt.utility.internal.SimpleMethodSignature;
+
+/**
+ * Adapt and extend a JDT method.
+ * Attribute based on a Java property, e.g.
+ * private int getFoo() {
+ * return foo;
+ * }
+ * private void setFoo(int foo) {
+ * this.foo = foo;
+ * }
+ */
+public class JDTMethodAttribute
+ extends JDTMember
+ implements MethodAttribute
+{
+ /** we need the parameter types to build the method signature */
+ private final JavaType[] parameterTypes;
+
+
+ // ********** constructors **********
+
+ public static JDTMethodAttribute newInstance(
+ Type declaringType,
+ MethodSignature signature,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ return newInstance(declaringType, signature, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ public static JDTMethodAttribute newInstance(
+ Type declaringType,
+ MethodSignature signature,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ return new JDTMethodAttribute(declaringType, signature, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ private JDTMethodAttribute(
+ Type declaringType,
+ MethodSignature methodSignature,
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super(declaringType, methodSignature.getName(), occurrence, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ this.parameterTypes = methodSignature.getParameterTypes();
+ }
+
+ /**
+ * constructor for testing
+ */
+ public JDTMethodAttribute(Type declaringType, String name, String[] parameterTypeNames, int occurrence, ICompilationUnit compilationUnit) {
+ this(declaringType, new SimpleMethodSignature(name, parameterTypeNames), occurrence, compilationUnit, CommandExecutor.Default.instance(), DefaultAnnotationEditFormatter.instance());
+ }
+
+
+ // ********** Member/Attribute/MethodAttribute implementation **********
+
+ @Override
+ protected Type getDeclaringType() {
+ return (Type) super.getDeclaringType();
+ }
+
+ public boolean isField() {
+ return false;
+ }
+
+ public IMethodBinding getBinding(CompilationUnit astRoot) {
+ return this.getBodyDeclaration(astRoot).resolveBinding();
+ }
+
+ @Override
+ public MethodDeclaration getBodyDeclaration(CompilationUnit astRoot) {
+ int count = 0;
+ for (MethodDeclaration methodDeclaration : this.getDeclaringTypeMethodDeclarations(astRoot)) {
+ if (this.matches(methodDeclaration)) {
+ count++;
+ if (count == this.getOccurrence()) {
+ return methodDeclaration;
+ }
+ }
+ }
+ // return null if the method is no longer in the source code;
+ // this can happen when the context model has not yet
+ // been synchronized with the resource model but is still
+ // asking for an ASTNode (e.g. during a selection event)
+ return null;
+ }
+
+ public boolean matches(MethodSignature signature, int occurrence) {
+ return this.matches(signature) && (occurrence == this.getOccurrence());
+ }
+
+ protected boolean matches(MethodSignature signature) {
+ return signature.getName().equals(this.getName())
+ && Arrays.equals(this.parameterTypes, signature.getParameterTypes());
+ }
+
+ protected boolean matches(MethodDeclaration methodDeclaration) {
+ return this.matches(ASTTools.buildMethodSignature(methodDeclaration));
+ }
+
+ // minimize scope of suppressed warnings
+ @SuppressWarnings("unchecked")
+ protected static List<SingleVariableDeclaration> parameters(MethodDeclaration methodDeclaration) {
+ return methodDeclaration.parameters();
+ }
+
+ @Override
+ public boolean matches(String memberName, int occurrence) {
+ throw new UnsupportedOperationException("Use #matches(MethodSignature, int)."); //$NON-NLS-1$
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ return new ASTNodeTextRange(this.getBodyDeclaration(astRoot).getName());
+ }
+
+ /**
+ * return "foo" for a method named "getFoo", "isFoo", "setFoo"
+ */
+ public String getAttributeName() {
+ return NameTools.convertGetterSetterMethodNameToPropertyName(this.getName());
+ }
+
+ public ITypeBinding getTypeBinding(CompilationUnit astRoot) {
+ IMethodBinding methodBinding = getBodyDeclaration(astRoot).resolveBinding();
+ return (methodBinding == null) ? null : methodBinding.getReturnType();
+ }
+
+ public boolean isPersistable(CompilationUnit astRoot) {
+ IMethodBinding binding = this.getBinding(astRoot);
+ return (binding == null) ? false : JPTTools.methodIsPersistablePropertyGetter(new JPTToolsAdapter(binding));
+ }
+
+
+ // ********** internal **********
+
+ protected TypeDeclaration getDeclaringTypeDeclaration(CompilationUnit astRoot) {
+ // assume the declaring type is not an enum or annotation
+ // since they do not have field or method declarations
+ return this.getDeclaringType().getBodyDeclaration(astRoot);
+ }
+
+ protected MethodDeclaration[] getDeclaringTypeMethodDeclarations(CompilationUnit astRoot) {
+ return this.getDeclaringTypeDeclaration(astRoot).getMethods();
+ }
+
+
+ // ********** JPTTools adapter **********
+
+ /**
+ * JPTTools needs an adapter so it can work with either an IMethod
+ * or an IMethodBinding etc.
+ */
+ protected static class SimpleJPTToolsAdapter
+ implements JPTTools.SimpleMethodAdapter
+ {
+ protected final IMethodBinding methodBinding;
+
+ protected SimpleJPTToolsAdapter(IMethodBinding methodBinding) {
+ super();
+ if (methodBinding == null) {
+ throw new NullPointerException();
+ }
+ this.methodBinding = methodBinding;
+ }
+
+ public int getModifiers() {
+ return this.methodBinding.getModifiers();
+ }
+
+ public String getReturnTypeErasureName() {
+ ITypeBinding returnType = this.methodBinding.getReturnType();
+ return (returnType == null) ? null : returnType.getTypeDeclaration().getErasure().getQualifiedName();
+ }
+
+ public boolean isConstructor() {
+ return this.methodBinding.isConstructor();
+ }
+
+ }
+
+ protected static class JPTToolsAdapter
+ extends SimpleJPTToolsAdapter
+ implements JPTTools.MethodAdapter
+ {
+ protected JPTToolsAdapter(IMethodBinding methodBinding) {
+ super(methodBinding);
+ }
+
+ public String getName() {
+ return this.methodBinding.getName();
+ }
+
+ public int getParametersLength() {
+ return this.methodBinding.getParameterTypes().length;
+ }
+
+ public JPTTools.SimpleMethodAdapter getSibling(String name) {
+ ITypeBinding typeBinding = this.methodBinding.getDeclaringClass();
+ if (typeBinding == null) {
+ return null;
+ }
+ for (IMethodBinding sibling : typeBinding.getDeclaredMethods()) {
+ if ((sibling.getParameterTypes().length == 0)
+ && sibling.getName().equals(name)) {
+ return new SimpleJPTToolsAdapter(sibling);
+ }
+ }
+ return null;
+ }
+
+ public JPTTools.SimpleMethodAdapter getSibling(String name, String parameterTypeErasureName) {
+ ITypeBinding typeBinding = this.methodBinding.getDeclaringClass();
+ if (typeBinding == null) {
+ return null;
+ }
+ for (IMethodBinding sibling : typeBinding.getDeclaredMethods()) {
+ ITypeBinding[] siblingParmTypes = sibling.getParameterTypes();
+ if ((siblingParmTypes.length == 1)
+ && sibling.getName().equals(name)
+ && siblingParmTypes[0].getTypeDeclaration().getErasure().getQualifiedName().equals(parameterTypeErasureName)) {
+ return new SimpleJPTToolsAdapter(sibling);
+ }
+ }
+ return null;
+ }
+
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTModifiedDeclaration.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTModifiedDeclaration.java
new file mode 100644
index 0000000000..5a1c8e3720
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTModifiedDeclaration.java
@@ -0,0 +1,584 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.BodyDeclaration;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IExtendedModifier;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.ImportDeclaration;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
+import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
+import org.eclipse.jpt.utility.internal.iterators.SubIteratorWrapper;
+
+/**
+ * Wrap any of the AST nodes that have modifiers (specifically, annotations);
+ * i.e. BodyDeclaration, SingleVariableDeclaration, VariableDeclarationExpression,
+ * and VariableDeclarationStatement.
+ */
+public class JDTModifiedDeclaration
+ implements ModifiedDeclaration
+{
+ private final Adapter adapter;
+
+
+ // ********** constructors **********
+
+ public JDTModifiedDeclaration(Adapter adapter) {
+ super();
+ this.adapter = adapter;
+ }
+
+ public JDTModifiedDeclaration(BodyDeclaration declaration) {
+ this(new BodyDeclarationAdapter(declaration));
+ }
+
+ public JDTModifiedDeclaration(PackageDeclaration declaration) {
+ this(new PackageDeclarationAdapter(declaration));
+ }
+
+ public JDTModifiedDeclaration(SingleVariableDeclaration declaration) {
+ this(new SingleVariableDeclarationAdapter(declaration));
+ }
+
+ public JDTModifiedDeclaration(VariableDeclarationExpression declaration) {
+ this(new VariableDeclarationExpressionAdapter(declaration));
+ }
+
+ public JDTModifiedDeclaration(VariableDeclarationStatement declaration) {
+ this(new VariableDeclarationStatementAdapter(declaration));
+ }
+
+
+ // ********** annotations **********
+
+ public Annotation getAnnotationNamed(String annotationName) {
+ for (Iterator<Annotation> stream = this.annotations(); stream.hasNext(); ) {
+ Annotation annotation = stream.next();
+ if (this.annotationIsNamed(annotation, annotationName)) {
+ return annotation;
+ }
+ }
+ return null;
+ }
+
+ public void removeAnnotationNamed(String annotationName) {
+ for (Iterator<IExtendedModifier> stream = this.getModifiers().iterator(); stream.hasNext(); ) {
+ IExtendedModifier modifier = stream.next();
+ if (modifier.isAnnotation()) {
+ if (this.annotationIsNamed((Annotation) modifier, annotationName)) {
+ stream.remove();
+ break;
+ }
+ }
+ }
+ }
+
+ public void replaceAnnotationNamed(String oldAnnotationName, Annotation newAnnotation) {
+ List<IExtendedModifier> modifiers = this.getModifiers();
+ for (ListIterator<IExtendedModifier> stream = modifiers.listIterator(); stream.hasNext(); ) {
+ IExtendedModifier modifier = stream.next();
+ if (modifier.isAnnotation()) {
+ if (this.annotationIsNamed((Annotation) modifier, oldAnnotationName)) {
+ stream.set(newAnnotation);
+ return;
+ }
+ }
+ }
+ this.addAnnotation(newAnnotation);
+ }
+
+ /**
+ * Add the specified annotation to the declaration.
+ * By convention annotations precede the "standard" (JLS2) modifiers;
+ * though, technically, they can be interspersed.
+ */
+ protected void addAnnotation(Annotation annotation) {
+ List<IExtendedModifier> modifiers = this.getModifiers();
+ for (ListIterator<IExtendedModifier> stream = modifiers.listIterator(); stream.hasNext(); ) {
+ if (stream.next().isModifier()) {
+ stream.previous(); // put the annotation *before* the first "standard" (JLS2) modifier
+ stream.add(annotation);
+ return;
+ }
+ }
+ modifiers.add(annotation); // just tack it on to the end
+ }
+
+ /**
+ * Return the declaration's annotations.
+ */
+ protected Iterator<Annotation> annotations() {
+ return new SubIteratorWrapper<IExtendedModifier, Annotation>(this.annotations_());
+ }
+
+ protected Iterator<IExtendedModifier> annotations_() {
+ return new FilteringIterator<IExtendedModifier>(this.getModifiers().iterator()) {
+ @Override
+ protected boolean accept(IExtendedModifier next) {
+ return next.isAnnotation();
+ }
+ };
+ }
+
+
+ // ********** add import **********
+
+ public boolean addImport(String className) {
+ if (className.indexOf('.') == -1) {
+ return true; // the class is in the default package - no need for import
+ }
+ return this.addImport(className, false);
+ }
+
+ public boolean addStaticImport(String enumConstantName) {
+ int index1 = enumConstantName.indexOf('.');
+ if (index1 == -1) {
+ throw new IllegalArgumentException(enumConstantName); // shouldn't happen?
+ }
+ int index2 = enumConstantName.indexOf('.', index1 + 1);
+ if (index2 == -1) {
+ return true; // the enum is in the default package - no need for import
+ }
+ return this.addImport(enumConstantName, true);
+ }
+
+ public boolean addImport(String importName, boolean staticImport) {
+ Boolean include = this.importsInclude(importName, staticImport);
+ if (include != null) {
+ return include.booleanValue();
+ }
+
+ ImportDeclaration importDeclaration = this.getAst().newImportDeclaration();
+ importDeclaration.setName(this.getAst().newName(importName));
+ importDeclaration.setStatic(staticImport);
+ this.getImports().add(importDeclaration);
+ return true;
+ }
+
+ /**
+ * Just a bit hacky:
+ * Return Boolean.TRUE if the import is already present.
+ * Return Boolean.FALSE if a colliding import is already present.
+ * Return null if a new import may be added.
+ * This hackery allows us to loop through the imports only once
+ * (and compose our methods).
+ * Pre-condition: 'importName' is not in the "default" package (i.e. it *is* qualified)
+ */
+ protected Boolean importsInclude(String importName, boolean staticImport) {
+ int period = importName.lastIndexOf('.'); // should not be -1
+ String importNameQualifier = importName.substring(0, period);
+ String shortImportName = importName.substring(period + 1);
+ return this.importsInclude(importName, importNameQualifier, shortImportName, staticImport);
+ }
+
+ /**
+ * pre-calculate the qualifier and short name
+ */
+ protected Boolean importsInclude(String importName, String importNameQualifier, String shortImportName, boolean staticImport) {
+ for (ImportDeclaration importDeclaration : this.getImports()) {
+ if (importDeclaration.isStatic() == staticImport) {
+ Boolean match = this.importMatches(importDeclaration, importName, importNameQualifier, shortImportName);
+ if (match != null) {
+ return match;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * we should be able to rely on the JDT model here, since we are looking
+ * at objects that should not be changing underneath us...
+ */
+ protected Boolean importMatches(ImportDeclaration importDeclaration, String importName, String importNameQualifier, String shortImportName) {
+ // examples:
+ // 'importName' is "java.util.Date"
+ // or
+ // 'importName' is "java.lang.annotation.ElementType.TYPE"
+ String idn = importDeclaration.getName().getFullyQualifiedName();
+ if (importName.equals(idn)) {
+ // import java.util.Date; => "Date" will resolve to "java.util.Date"
+ // import static java.lang.annotation.ElementType.TYPE; => "TYPE" will resolve to "java.lang.annotation.ElementType.TYPE"
+ return Boolean.TRUE;
+ }
+
+ String shortIDN = idn.substring(idn.lastIndexOf('.') + 1);
+ if (shortImportName.equals(shortIDN)) {
+ // import java.sql.Date; => ambiguous resolution of "Date"
+ // import static org.foo.Bar.TYPE; => ambiguous resolution of "TYPE"
+ return Boolean.FALSE;
+ }
+
+ if (importDeclaration.isOnDemand()) {
+ if (importNameQualifier.equals(idn)) {
+ // import java.util.*; => "Date" will resolve to "java.util.Date"
+ // import static java.lang.annotation.ElementType.*; => "TYPE" will resolve to "java.lang.annotation.ElementType.TYPE"
+ return Boolean.TRUE;
+ }
+ if (importDeclaration.isStatic()) {
+ if (this.enumResolves(idn, shortImportName)) {
+ // import static org.foo.Bar.*; => ambiguous resolution of "TYPE"
+ return Boolean.FALSE;
+ }
+ } else {
+ if (this.typeResolves(idn + '.' + shortImportName)) {
+ // import java.sql.*; => ambiguous resolution of "Date"
+ return Boolean.FALSE;
+ }
+ }
+ }
+ // no matches - OK to add explicit import
+ return null;
+ }
+
+ protected boolean enumResolves(String enumTypeName, String enumConstantName) {
+ try {
+ return this.enumResolves_(enumTypeName, enumConstantName);
+ } catch (JavaModelException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ protected boolean enumResolves_(String enumTypeName, String enumConstantName) throws JavaModelException {
+ IType jdtType = this.findType_(enumTypeName);
+ if (jdtType == null) {
+ return false;
+ }
+ if ( ! jdtType.isEnum()) {
+ return false;
+ }
+ for (IField jdtField : jdtType.getFields()) {
+ if (jdtField.isEnumConstant() && jdtField.getElementName().equals(enumConstantName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected boolean typeResolves(String name) {
+ return this.findType(name) != null;
+ }
+
+ protected IType findType(String name) {
+ try {
+ return this.findType_(name);
+ } catch (JavaModelException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ protected IType findType_(String name) throws JavaModelException {
+ return this.getCompilationUnit().getJavaElement().getJavaProject().findType(name);
+ }
+
+ protected List<ImportDeclaration> getImports() {
+ return this.imports(this.getCompilationUnit());
+ }
+
+ // minimize scope of suppressed warnings
+ @SuppressWarnings("unchecked")
+ protected List<ImportDeclaration> imports(CompilationUnit astRoot) {
+ return astRoot.imports();
+ }
+
+
+ // ********** annotation name resolution **********
+
+ public boolean annotationIsNamed(Annotation annotation, String name) {
+ return this.getQualifiedName(annotation).equals(name);
+ }
+
+ /**
+ * Simply return the annotation's unqualified name if we can't "resolve" it.
+ */
+ protected String getQualifiedName(Annotation annotation) {
+ ITypeBinding typeBinding = annotation.resolveTypeBinding();
+ if (typeBinding != null) {
+ String resolvedName = typeBinding.getQualifiedName();
+ if (resolvedName != null) {
+ return resolvedName;
+ }
+ }
+ // hack(?): check for a matching import because when moving a stand-alone
+ // annotation to its container in CombinationIndexedDeclarationAnnotationAdapter
+ // the container's import is added but then it won't "resolve" upon
+ // subsequent lookups (because the parser hasn't had time to run?)... :-(
+ return this.convertToFullClassName(annotation.getTypeName().getFullyQualifiedName());
+ }
+
+ /**
+ * If necessary, use the declaration's imports to calculate a guess as to
+ * the specified name's fully-qualified form.
+ * Simply return the unqualified name if we can't "resolve" it.
+ */
+ protected String convertToFullClassName(String name) {
+ // check for fully-qualified name
+ return (name.lastIndexOf('.') != -1) ? name : this.resolveAgainstImports(name, false);
+ }
+
+ /**
+ * If necessary, use the declaration's imports to calculate a guess as to
+ * the specified name's fully-qualified form.
+ * Simply return the unqualified name if we can't "resolve" it.
+ */
+ protected String convertToFullEnumConstantName(String name) {
+ int index1 = name.indexOf('.');
+ if (index1 == -1) {
+ // short name, e.g. "TYPE"
+ // true = look for static import of enum constant
+ return this.resolveAgainstImports(name, true);
+ }
+
+ int index2 = name.indexOf('.', index1 + 1);
+ if (index2 == -1) {
+ // partially-qualified name, e.g. "ElementType.TYPE"
+ // false = look regular import of enum class, not static import of enum constant
+ return this.resolveAgainstImports(name, false);
+ }
+
+ // fully-qualified name, e.g. "java.lang.annotation.ElementType.TYPE"
+ return name;
+ }
+
+ /**
+ * Attempt to resolve the specified "short" name against the declaration's
+ * imports. Return the name unchanged if we can't resolve it (perhaps it is
+ * in the "default" package).
+ */
+ protected String resolveAgainstImports(String shortName, boolean static_) {
+ for (ImportDeclaration importDeclaration : this.getImports()) {
+ if (importDeclaration.isStatic() == static_) {
+ String resolvedName = this.resolveAgainstImport(importDeclaration, shortName);
+ if (resolvedName != null) {
+ return resolvedName;
+ }
+ }
+ }
+ return shortName; // "default" package or unknown
+ }
+
+ /**
+ * Attempt to resolve the specified "short" name against the specified
+ * import. Return the resolved name if the import resolves it; otherwise
+ * return null.
+ */
+ protected String resolveAgainstImport(ImportDeclaration importDeclaration, String shortName) {
+ String idn = importDeclaration.getName().getFullyQualifiedName();
+ if (importDeclaration.isOnDemand()) {
+ String candidate = idn + '.' + shortName;
+ if (importDeclaration.isStatic()) {
+ if (this.enumResolves(idn, shortName)) {
+ return candidate;
+ }
+ } else {
+ if (this.typeResolves(candidate)) {
+ return candidate;
+ }
+ }
+ // no match
+ return null;
+ }
+
+ // explicit import - see whether its end matches 'shortName'
+ int period = idn.length() - shortName.length() - 1;
+ if (period < 1) {
+ // something must precede period
+ return null;
+ }
+ if ((idn.charAt(period) == '.') && idn.endsWith(shortName)) {
+ return idn; // probable exact match
+ }
+ return null;
+ }
+
+
+ // ********** miscellaneous methods **********
+
+ public ASTNode getDeclaration() {
+ return this.adapter.getDeclaration();
+ }
+
+ /**
+ * Return the declaration's list of modifiers.
+ * Element type: org.eclipse.jdt.core.dom.IExtendedModifier
+ */
+ protected List<IExtendedModifier> getModifiers() {
+ return this.adapter.getModifiers();
+ }
+
+ public AST getAst() {
+ return this.getDeclaration().getAST();
+ }
+
+ protected CompilationUnit getCompilationUnit() {
+ return (CompilationUnit) this.getDeclaration().getRoot();
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.adapter.toString());
+ }
+
+
+ // ********** declaration adapter interface and implementations **********
+
+ /**
+ * Define common protocol among the various "declarations".
+ */
+ public interface Adapter {
+
+ /**
+ * Return the adapted "declaration".
+ */
+ ASTNode getDeclaration();
+
+ /**
+ * Return the "declaration"'s list of modifiers.
+ * Element type: org.eclipse.jdt.core.dom.IExtendedModifier
+ */
+ List<IExtendedModifier> getModifiers();
+
+ }
+
+ public static class BodyDeclarationAdapter implements Adapter {
+ private final BodyDeclaration declaration;
+ public BodyDeclarationAdapter(BodyDeclaration declaration) {
+ super();
+ this.declaration = declaration;
+ }
+ public ASTNode getDeclaration() {
+ return this.declaration;
+ }
+ @SuppressWarnings("unchecked")
+ public List<IExtendedModifier> getModifiers() {
+ return this.declaration.modifiers();
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.declaration.toString());
+ }
+ }
+
+ public static class PackageDeclarationAdapter implements Adapter {
+ private final PackageDeclaration declaration;
+ public PackageDeclarationAdapter(PackageDeclaration declaration) {
+ super();
+ this.declaration = declaration;
+ }
+ public ASTNode getDeclaration() {
+ return this.declaration;
+ }
+ @SuppressWarnings("unchecked")
+ public List<IExtendedModifier> getModifiers() {
+ return this.declaration.annotations();
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.declaration.toString());
+ }
+ }
+
+ /*public static class ASTNodeAdapter implements Adapter {
+ private final ASTNode declaration;
+ public ASTNodeAdapter(ASTNode declaration) {
+ super();
+ this.declaration = declaration;
+ }
+ public ASTNode getDeclaration() {
+ return this.declaration;
+ }
+ @SuppressWarnings("unchecked")
+ public List<IExtendedModifier> getModifiers() {
+ if (declaration instanceof BodyDeclaration) {
+ return ((BodyDeclaration) declaration).modifiers();
+ } else if (declaration instanceof PackageDeclaration) {
+ return ((PackageDeclaration) declaration).annotations();
+ }
+ return Collections.emptyList();
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.declaration.toString());
+ }
+ }*/
+
+ public static class SingleVariableDeclarationAdapter implements Adapter {
+ private final SingleVariableDeclaration declaration;
+ public SingleVariableDeclarationAdapter(SingleVariableDeclaration declaration) {
+ super();
+ this.declaration = declaration;
+ }
+ public ASTNode getDeclaration() {
+ return this.declaration;
+ }
+ @SuppressWarnings("unchecked")
+ public List<IExtendedModifier> getModifiers() {
+ return this.declaration.modifiers();
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.declaration.toString());
+ }
+ }
+
+ public static class VariableDeclarationExpressionAdapter implements Adapter {
+ private final VariableDeclarationExpression declaration;
+ public VariableDeclarationExpressionAdapter(VariableDeclarationExpression declaration) {
+ super();
+ this.declaration = declaration;
+ }
+ public ASTNode getDeclaration() {
+ return this.declaration;
+ }
+ @SuppressWarnings("unchecked")
+ public List<IExtendedModifier> getModifiers() {
+ return this.declaration.modifiers();
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.declaration.toString());
+ }
+ }
+
+ public static class VariableDeclarationStatementAdapter implements Adapter {
+ private final VariableDeclarationStatement declaration;
+ public VariableDeclarationStatementAdapter(VariableDeclarationStatement declaration) {
+ super();
+ this.declaration = declaration;
+ }
+ public ASTNode getDeclaration() {
+ return this.declaration;
+ }
+ @SuppressWarnings("unchecked")
+ public List<IExtendedModifier> getModifiers() {
+ return this.declaration.modifiers();
+ }
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.declaration.toString());
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTPackage.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTPackage.java
new file mode 100644
index 0000000000..d400f4437f
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTPackage.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Red Hat, Inc.
+ * Distributed under license by Red Hat, Inc. All rights reserved.
+ * This program is made available under the terms of the
+ * Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributor:
+ * Red Hat, Inc. - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IPackageBinding;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotatedPackage;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+import org.eclipse.jpt.utility.CommandExecutor;
+
+/**
+ * @author Dmitry Geraskov
+ *
+ */
+
+public class JDTPackage extends JDTAnnotatedElement implements AnnotatedPackage {
+
+
+ protected JDTPackage(PackageDeclaration declaringPackage,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ super(declaringPackage.getName().getFullyQualifiedName(),
+ compilationUnit,
+ modifySharedDocumentCommandExecutor);
+ }
+
+ public JDTPackage(
+ PackageDeclaration declaringPackage,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super(declaringPackage.getName().getFullyQualifiedName(),
+ compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ @Override
+ public ModifiedDeclaration getModifiedDeclaration(CompilationUnit astRoot) {
+ return new JDTModifiedDeclaration(this.getBodyDeclaration(astRoot));
+ }
+
+ public IPackageBinding getBinding(CompilationUnit astRoot) {
+ PackageDeclaration pd = this.getBodyDeclaration(astRoot);
+ return (pd == null) ? null : pd.resolveBinding();
+ }
+
+ public PackageDeclaration getBodyDeclaration(CompilationUnit astRoot) {
+ return astRoot.getPackage();
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ return new ASTNodeTextRange(this.getBodyDeclaration(astRoot).getName());
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTTools.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTTools.java
new file mode 100644
index 0000000000..fe34f9ef35
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTTools.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+* Copyright (c) 2010 Oracle. All rights reserved.
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0, which accompanies this distribution
+* and is available at http://www.eclipse.org/legal/epl-v10.html.
+*
+* Contributors:
+* Oracle - initial API and implementation
+*******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.utility.Filter;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.jpt.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
+
+/**
+ * Convenience methods for dealing with JDT core
+ */
+public final class JDTTools
+{
+
+ public static boolean packageFragmentRootIsSourceFolder(IPackageFragmentRoot pfr) {
+ try {
+ return packageFragmentRootIsSourceFolder_(pfr);
+ } catch (JavaModelException ex) {
+ JptCommonCorePlugin.log(ex);
+ return false;
+ }
+ }
+
+ protected static boolean packageFragmentRootIsSourceFolder_(IPackageFragmentRoot pfr) throws JavaModelException {
+ return pfr.exists() && (pfr.getKind() == IPackageFragmentRoot.K_SOURCE);
+ }
+
+ public static IJavaElement[] getJDTChildren(IPackageFragmentRoot root) {
+ try {
+ return getJDTChildren_(root);
+ } catch (JavaModelException ex) {
+ // ignore FNFE - which can happen when the workspace is out of synch with O/S file system
+ if ( ! (ex.getCause() instanceof FileNotFoundException)) {
+ JptCommonCorePlugin.log(ex);
+ }
+ return EMPTY_JAVA_ELEMENT_ARRAY;
+ }
+ }
+
+ private static IJavaElement[] getJDTChildren_(IPackageFragmentRoot root) throws JavaModelException {
+ return root.getChildren();
+ }
+
+ private static final IJavaElement[] EMPTY_JAVA_ELEMENT_ARRAY = new IJavaElement[0];
+
+ public static boolean typeNamedImplementsInterfaceNamed(IJavaProject javaProject, String typeName, String interfaceNamed) {
+ try {
+ return typeImplementsInterface(javaProject, javaProject.findType(typeName), javaProject.findType(interfaceNamed));
+ }
+ catch (JavaModelException ex) {
+ JptCommonCorePlugin.log(ex);
+ return false;
+ }
+ }
+
+ public static boolean typeImplementsInterface(IJavaProject javaProject, IType type, IType interfase) {
+ try {
+ if (type == null || interfase == null) {
+ return false;
+ }
+
+ Iterable<String> resolvedSuperInterfaceNames = resolveSuperInterfaceNames(type);
+ if (CollectionTools.contains(resolvedSuperInterfaceNames, interfase.getFullyQualifiedName())) {
+ return true;
+ }
+
+ for (String interfaceName : resolveSuperInterfaceNames(type)) {
+ IType superInterface = javaProject.findType(interfaceName);
+ if (superInterface != null && typeImplementsInterface(javaProject, superInterface, interfase)) {
+ return true;
+ }
+ }
+
+ if (type.getSuperclassName() == null) {
+ return false;
+ }
+
+ return typeImplementsInterface(javaProject, getJDTSuperclass(javaProject, type), interfase);
+ }
+ catch (JavaModelException ex) {
+ return false;
+ }
+
+ }
+
+ /**
+ * This is necessary because for whatever reason getSuperClassName() on IType returns unqualified names
+ * when the type is java sourced.
+ * @param type
+ * @return String - resolved super class name or null
+ */
+ private static String resolveSuperClassName(final IType type) {
+ try {
+ if (!type.isBinary()) {
+ String superClassName = type.getSuperclassName();
+ String[][] resolvedSuperClassName = type.resolveType(superClassName);
+ return resolvedSuperClassName[0][0] + "." + resolvedSuperClassName[0][1]; //$NON-NLS-1$
+ }
+ return type.getSuperclassName();
+ } catch (JavaModelException ex) {
+ JptCommonCorePlugin.log(ex);
+ return null;
+ }
+ }
+
+ /**
+ * This is necessary because for whatever reason getSuperInterfaceNames() on IType returns unqualified names
+ * when the type is java sourced.
+ * @param type
+ * @return Iterable<String> - resolved super interface names
+ */
+ private static Iterable<String> resolveSuperInterfaceNames(final IType type) {
+ try {
+ if (!type.isBinary()) {
+ ArrayList<String> resolvedSuperInterfaceNames = new ArrayList<String>();
+ for (String superInterfaceName : new ArrayIterable<String>(type.getSuperInterfaceNames())) {
+ String[][] resolvedTypeNames = type.resolveType(superInterfaceName);
+ for (String[] resolvedTypeName : resolvedTypeNames) {
+ resolvedSuperInterfaceNames.add(resolvedTypeName[0] + "." + resolvedTypeName[1]); //$NON-NLS-1$
+ }
+ }
+ return resolvedSuperInterfaceNames;
+ }
+ return new ArrayIterable<String>(type.getSuperInterfaceNames());
+ }
+ catch (JavaModelException ex) {
+ JptCommonCorePlugin.log(ex);
+ return EmptyIterable.instance();
+ }
+ }
+
+ public static IType getJDTType(IJavaProject javaProject, String fullyQualifiedName) {
+ try {
+ return javaProject.findType(fullyQualifiedName);
+ }
+ catch (JavaModelException ex) {
+ JptCommonCorePlugin.log(ex);
+ return null;
+ }
+ }
+
+ public static IType getJDTSuperclass(IJavaProject javaProject, IType child) {
+ try {
+ return javaProject.findType(resolveSuperClassName(child));
+ }
+ catch (JavaModelException ex) {
+ JptCommonCorePlugin.log(ex);
+ return null;
+ }
+ }
+
+ public static Iterable<IType> getJDTSuperInterfaces(IJavaProject javaProject, IType child) {
+ ArrayList<IType> superclassInterfaces = new ArrayList<IType>();
+ try {
+ Iterable<String> superInterfaceNameIterable = resolveSuperInterfaceNames(child);
+ for (String superInterfaceName : superInterfaceNameIterable) {
+ superclassInterfaces.add(javaProject.findType(superInterfaceName));
+ }
+ }
+ catch (JavaModelException ex) {
+ JptCommonCorePlugin.log(ex);
+ return EmptyIterable.instance();
+ }
+
+ return superclassInterfaces;
+ }
+
+ public static Iterable<IPackageFragmentRoot> getJavaSourceFolders(IJavaProject javaProject) {
+ try {
+ return new FilteringIterable<IPackageFragmentRoot>(
+ getPackageFragmentRoots(javaProject),
+ SOURCE_PACKAGE_FRAGMENT_ROOT_FILTER);
+ }
+ catch (JavaModelException ex) {
+ JptCommonCorePlugin.log(ex);
+ return EmptyIterable.instance();
+ }
+ }
+
+ /**
+ * This returns the first package fragment root found on this project.
+ * I am not completely sure why, but the JavaTypeCompletionProcessor works with this.
+ */
+ //TODO move this method to JpaProject once API freeze is over
+ public static IPackageFragmentRoot getCodeCompletionContextRoot(IJavaProject javaProject) {
+ try {
+ return javaProject.getPackageFragmentRoots()[0];
+ }
+ catch (JavaModelException e) {
+ JptCommonCorePlugin.log(e);
+ return null;
+ }
+ }
+
+ protected static Iterable<IPackageFragmentRoot> getJavaSourceFolders_(IJavaProject javaProject) throws JavaModelException {
+ return new FilteringIterable<IPackageFragmentRoot>(
+ getPackageFragmentRoots(javaProject),
+ SOURCE_PACKAGE_FRAGMENT_ROOT_FILTER
+ );
+ }
+
+ protected static final Filter<IPackageFragmentRoot> SOURCE_PACKAGE_FRAGMENT_ROOT_FILTER =
+ new Filter<IPackageFragmentRoot>() {
+ public boolean accept(IPackageFragmentRoot pfr) {
+ try {
+ return this.accept_(pfr);
+ } catch (JavaModelException ex) {
+ return false;
+ }
+ }
+ private boolean accept_(IPackageFragmentRoot pfr) throws JavaModelException {
+ return packageFragmentRootIsSourceFolder_(pfr);
+ }
+ };
+
+ protected static Iterable<IPackageFragmentRoot> getPackageFragmentRoots(IJavaProject javaProject) throws JavaModelException {
+ return new ArrayIterable<IPackageFragmentRoot>(javaProject.getPackageFragmentRoots());
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTType.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTType.java
new file mode 100644
index 0000000000..3bd24b903d
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JDTType.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.List;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.jpt.common.core.utility.jdt.Type;
+import org.eclipse.jpt.utility.CommandExecutor;
+
+/**
+ * Adapt and extend a JDT type.
+ */
+public class JDTType
+ extends AbstractJDTType
+ implements Type
+{
+
+ /**
+ * constructor for the compilation unit's primary type
+ */
+ public JDTType(
+ TypeDeclaration typeDeclaration, // exclude annotations and enums
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(typeDeclaration, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ /**
+ * constructor for the compilation unit's primary type
+ */
+ public JDTType(
+ TypeDeclaration typeDeclaration, // exclude annotations and enums
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ this(null, typeDeclaration, 1, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ /**
+ * constructor for nested types
+ */
+ public JDTType(
+ Type declaringType,
+ TypeDeclaration typeDeclaration, // exclude annotations and enums
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor) {
+ this(declaringType, typeDeclaration, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
+ }
+
+ /**
+ * constructor for nested types
+ */
+ public JDTType(
+ Type declaringType,
+ TypeDeclaration typeDeclaration, // exclude annotations and enums
+ int occurrence,
+ ICompilationUnit compilationUnit,
+ CommandExecutor modifySharedDocumentCommandExecutor,
+ AnnotationEditFormatter annotationEditFormatter) {
+ super(declaringType, typeDeclaration, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
+ }
+
+ /**
+ * constructor for testing
+ */
+ public JDTType(Type declaringType, String name, int occurrence, ICompilationUnit compilationUnit) {
+ super(declaringType, name, occurrence, compilationUnit);
+ }
+
+
+ // ********** Member/Type implementation **********
+
+ /**
+ * find the type's body declaration in the specified AST
+ */
+ @Override
+ public TypeDeclaration getBodyDeclaration(CompilationUnit astRoot) {
+ return (TypeDeclaration) super.getBodyDeclaration(astRoot);
+ }
+
+ public boolean isPersistable(CompilationUnit astRoot) {
+ ITypeBinding binding = this.getBinding(astRoot);
+ return (binding == null) ? false : JPTTools.typeIsPersistable(new JPTToolsAdapter(binding));
+ }
+
+ public TypeDeclaration[] getTypes(CompilationUnit astRoot) {
+ return this.getBodyDeclaration(astRoot).getTypes();
+ }
+
+ public EnumDeclaration[] getEnums(CompilationUnit astRoot) {
+ return getEnums(this.getBodyDeclaration(astRoot));
+ }
+
+ public FieldDeclaration[] getFields(CompilationUnit astRoot) {
+ return this.getBodyDeclaration(astRoot).getFields();
+ }
+
+ public MethodDeclaration[] getMethods(CompilationUnit astRoot) {
+ return this.getBodyDeclaration(astRoot).getMethods();
+ }
+
+
+ // ********** internal **********
+
+ /**
+ * return the first top-level type in the specified AST with a matching name
+ */
+ @Override
+ protected TypeDeclaration getTopLevelTypeDeclaration(CompilationUnit astRoot) {
+ return (TypeDeclaration) super.getTopLevelTypeDeclaration(astRoot);
+ }
+
+ @Override
+ protected TypeDeclaration getTypeDeclaration(List<AbstractTypeDeclaration> typeDeclarations) {
+ return (TypeDeclaration) super.getTypeDeclaration(typeDeclarations);
+ }
+
+ /**
+ * return the nested type with a matching name and occurrence
+ */
+ @Override
+ protected TypeDeclaration getNestedTypeDeclaration(TypeDeclaration declaringTypeDeclaration) {
+ return this.getTypeDeclaration(declaringTypeDeclaration.getTypes());
+ }
+
+ /**
+ * return the type declaration corresponding to the type from the specified
+ * set of type declarations (match name and occurrence)
+ */
+ @Override
+ protected TypeDeclaration getTypeDeclaration(AbstractTypeDeclaration[] typeDeclarations) {
+ return (TypeDeclaration) super.getTypeDeclaration(typeDeclarations);
+ }
+
+ @Override
+ protected int getASTNodeType() {
+ return ASTNode.TYPE_DECLARATION;
+ }
+
+
+ // ********** JPT tools adapter **********
+
+ protected static class JPTToolsAdapter implements JPTTools.TypeAdapter {
+ private final ITypeBinding typeBinding;
+ protected JPTToolsAdapter(ITypeBinding typeBinding) {
+ super();
+ if (typeBinding == null) {
+ throw new NullPointerException();
+ }
+ this.typeBinding = typeBinding;
+ }
+
+ public int getModifiers() {
+ return this.typeBinding.getModifiers();
+ }
+
+ public boolean isAnnotation() {
+ return this.typeBinding.isAnnotation();
+ }
+
+ public boolean isAnonymous() {
+ return this.typeBinding.isAnonymous();
+ }
+
+ public boolean isArray() {
+ return this.typeBinding.isArray();
+ }
+
+ public boolean isEnum() {
+ return this.typeBinding.isEnum();
+ }
+
+ public boolean isInterface() {
+ return this.typeBinding.isInterface();
+ }
+
+ public boolean isLocal() {
+ return this.typeBinding.isLocal();
+ }
+
+ public boolean isMember() {
+ return this.typeBinding.isMember();
+ }
+
+ public boolean isPrimitive() {
+ return this.typeBinding.isPrimitive();
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JPTTools.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JPTTools.java
new file mode 100644
index 0000000000..f1930c829c
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/JPTTools.java
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Convenience methods for JPA-related queries concerning JDT objects.
+ */
+//TODO this needs to move because it is only used for JPA
+public class JPTTools {
+
+ // ********** type **********
+
+ /**
+ * Return whether the specified type can be "persisted", i.e. marked as
+ * Entity, MappedSuperclass, Embeddable
+ */
+ public static boolean typeIsPersistable(TypeAdapter typeAdapter) {
+ if (typeAdapter.isInterface()) {
+ return false;
+ }
+ if (typeAdapter.isAnnotation()) {
+ return false;
+ }
+ if (typeAdapter.isEnum()) {
+ return false;
+ }
+ if (typeAdapter.isLocal()) {
+ return false;
+ }
+ if (typeAdapter.isAnonymous()) {
+ return false;
+ }
+ if (typeAdapter.isPrimitive()) {
+ return false; // should never get here(?)
+ }
+ if (typeAdapter.isArray()) {
+ return false; // should never get here(?)
+ }
+ return true;
+ }
+
+ /**
+ * Queries needed to calculate whether a type is "persistable".
+ * Adapted to ITypeBinding and IType.
+ */
+ public interface TypeAdapter {
+ int getModifiers();
+ boolean isAnnotation();
+ boolean isAnonymous();
+ boolean isArray();
+ boolean isEnum();
+ boolean isInterface();
+ boolean isLocal();
+ boolean isMember();
+ boolean isPrimitive();
+ }
+
+
+ // ********** field **********
+
+ /**
+ * Return whether the specified field may be "persisted".
+ * According to the spec, "All non-transient instance variables that are not
+ * annotated with the Transient annotation are persistent."
+ */
+ public static boolean fieldIsPersistable(FieldAdapter fieldAdapter) {
+ int modifiers = fieldAdapter.getModifiers();
+ if (Modifier.isStatic(modifiers)) {
+ return false;
+ }
+ if (Modifier.isTransient(modifiers)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Queries needed to calculate whether a field is "persistable".
+ * Adapted to IVariableBinding and IField.
+ */
+ public interface FieldAdapter {
+ /**
+ * Return the field's modifiers. We use these to check whether the
+ * field is static or transient.
+ */
+ int getModifiers();
+ }
+
+
+ // ********** method **********
+
+ /**
+ * Return whether the specified method is a "getter" method that
+ * represents a property that may be "persisted".
+ */
+ public static boolean methodIsPersistablePropertyGetter(MethodAdapter methodAdapter) {
+ if (methodHasInvalidModifiers(methodAdapter)) {
+ return false;
+ }
+ if (methodAdapter.isConstructor()) {
+ return false;
+ }
+
+ String returnTypeName = methodAdapter.getReturnTypeErasureName();
+ if (returnTypeName == null) {
+ return false; // DOM method bindings can have a null name
+ }
+ if (returnTypeName.equals("void")) { //$NON-NLS-1$
+ return false;
+ }
+ if (methodHasParameters(methodAdapter)) {
+ return false;
+ }
+
+ String name = methodAdapter.getName();
+ int beginIndex = 0;
+ boolean booleanGetter = false;
+ if (name.startsWith("is")) { //$NON-NLS-1$
+ if (returnTypeName.equals("boolean")) { //$NON-NLS-1$
+ beginIndex = 2;
+ } else {
+ return false;
+ }
+ } else if (name.startsWith("get")) { //$NON-NLS-1$
+ beginIndex = 3;
+ if (returnTypeName.equals("boolean")) { //$NON-NLS-1$
+ booleanGetter = true;
+ }
+ } else {
+ return false;
+ }
+
+ String capitalizedAttributeName = name.substring(beginIndex);
+ // if the type has both methods:
+ // boolean isProperty()
+ // boolean getProperty()
+ // then #isProperty() takes precedence and we ignore #getProperty();
+ // but only having #getProperty() is OK too
+ // (see the JavaBeans spec 1.01)
+ if (booleanGetter && methodHasValidSiblingIsMethod(methodAdapter, capitalizedAttributeName)) {
+ return false; // since the type also defines #isProperty(), ignore #getProperty()
+ }
+ return methodHasValidSiblingSetMethod(methodAdapter, capitalizedAttributeName, returnTypeName);
+ }
+
+ /**
+ * Return whether the method's modifiers prevent it
+ * from being a getter or setter for a "persistent" property.
+ */
+ private static boolean methodHasInvalidModifiers(SimpleMethodAdapter methodAdapter) {
+ int modifiers = methodAdapter.getModifiers();
+ if (Modifier.isStatic(modifiers)) {
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean methodHasParameters(MethodAdapter methodAdapter) {
+ return methodAdapter.getParametersLength() != 0;
+ }
+
+ /**
+ * Return whether the method has a sibling "is" method for the specified
+ * property and that method is valid for a "persistable" property.
+ * Pre-condition: the method is a "boolean getter" (e.g. 'public boolean getProperty()');
+ * this prevents us from returning true when the method itself is an
+ * "is" method.
+ */
+ private static boolean methodHasValidSiblingIsMethod(MethodAdapter methodAdapter, String capitalizedAttributeName) {
+ SimpleMethodAdapter isMethodAdapter = methodAdapter.getSibling("is" + capitalizedAttributeName); //$NON-NLS-1$
+ return methodIsValidSibling(isMethodAdapter, "boolean"); //$NON-NLS-1$
+ }
+
+ /**
+ * Return whether the method has a sibling "set" method
+ * and that method is valid for a "persistable" property.
+ */
+ private static boolean methodHasValidSiblingSetMethod(MethodAdapter methodAdapter, String capitalizedAttributeName, String parameterTypeErasureName) {
+ SimpleMethodAdapter setMethodAdapter = methodAdapter.getSibling("set" + capitalizedAttributeName, parameterTypeErasureName); //$NON-NLS-1$
+ return methodIsValidSibling(setMethodAdapter, "void"); //$NON-NLS-1$
+ }
+
+ /**
+ * Return whether the specified method is a valid sibling with the
+ * specified return type.
+ */
+ private static boolean methodIsValidSibling(SimpleMethodAdapter methodAdapter, String returnTypeName) {
+ if (methodAdapter == null) {
+ return false;
+ }
+ if (methodHasInvalidModifiers(methodAdapter)) {
+ return false;
+ }
+ if (methodAdapter.isConstructor()) {
+ return false;
+ }
+ String rtName = methodAdapter.getReturnTypeErasureName();
+ if (rtName == null) {
+ return false; // DOM method bindings can have a null name
+ }
+ return rtName.equals(returnTypeName);
+ }
+
+ /**
+ * Queries needed to calculate whether a method is "persistable".
+ * Adapted to IMethodBinding and IMethod.
+ */
+ public interface SimpleMethodAdapter {
+ /**
+ * Return the method's modifiers.
+ * We use these to check whether the method is static, final, etc.
+ */
+ int getModifiers();
+
+ /**
+ * Return the name of the method's return type erasure.
+ * We use this to check for
+ * - boolean getters
+ * - void return types
+ * - matching getters and setters
+ */
+ String getReturnTypeErasureName();
+
+ /**
+ * Return whether the method is a constructor.
+ */
+ boolean isConstructor();
+ }
+
+ /**
+ * Queries needed to calculate whether a method is "persistable".
+ * Adapted to IMethodBinding and IMethod.
+ */
+ public interface MethodAdapter extends SimpleMethodAdapter {
+ /**
+ * Return the method's name.
+ * We use this to determine
+ * - whether the method is a "getter"
+ * - the property name implied by the getter's name
+ */
+ String getName();
+
+ /**
+ * Return the number of paramters declared by the method.
+ * We use this to determine whether the method is a "getter".
+ */
+ int getParametersLength();
+
+ /**
+ * Return the method's "sibling" with the specified name and no parameters.
+ * We use this to find an "is" boolean getter that would take precedence
+ * over a "get" boolean getter.
+ */
+ SimpleMethodAdapter getSibling(String name);
+
+ /**
+ * Return the method's "sibling" with the specified name and single parameter.
+ * We use this to find a matching "setter" for a possible "getter".
+ */
+ SimpleMethodAdapter getSibling(String name, String parameterTypeErasureName);
+ }
+
+
+ // ********** suppressed constructor **********
+
+ /**
+ * Suppress default constructor, ensuring non-instantiability.
+ */
+ private JPTTools() {
+ super();
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NameStringExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NameStringExpressionConverter.java
new file mode 100644
index 0000000000..5c9bc46dde
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NameStringExpressionConverter.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+
+/**
+ * Convert a name to/from a string representation of a name/identifier
+ * (e.g. "com.xxx.Foo.VALUE1" or "value").
+ */
+public final class NameStringExpressionConverter
+ extends AbstractExpressionConverter<String>
+{
+ private static final ExpressionConverter<String> INSTANCE = new NameStringExpressionConverter();
+
+ /**
+ * Return the singleton.
+ */
+ public static ExpressionConverter<String> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private NameStringExpressionConverter() {
+ super();
+ }
+
+ @Override
+ protected Name convertObject(String string, AST ast) {
+ return ast.newName(string);
+ }
+
+ @Override
+ protected String convertExpression(Expression expression) {
+ switch (expression.getNodeType()) {
+ case ASTNode.QUALIFIED_NAME:
+ case ASTNode.SIMPLE_NAME:
+ return ((Name) expression).getFullyQualifiedName();
+ default:
+ return null;
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NestedDeclarationAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NestedDeclarationAnnotationAdapter.java
new file mode 100644
index 0000000000..17eb956055
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NestedDeclarationAnnotationAdapter.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.MemberValuePair;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+
+/**
+ * Manipulate an annotation that is embedded as an element within
+ * another annotation, e.g.
+ * <pre>
+ * &#64;Outer(foo=&#64;Inner)
+ * private int id;
+ * outerAnnotationAdapter = AnnotationAdapter<&#64;Outer>
+ * elementName = "foo"
+ * annotationName = "Inner"
+ * </pre>
+ */
+public class NestedDeclarationAnnotationAdapter
+ extends AbstractNestedDeclarationAnnotationAdapter
+{
+ // ********** constructors **********
+
+ /**
+ * The default element name is <code>value</code>.
+ */
+ public NestedDeclarationAnnotationAdapter(DeclarationAnnotationAdapter outerAnnotationAdapter, String annotationName) {
+ super(outerAnnotationAdapter, annotationName);
+ }
+
+ /**
+ * default behavior is to remove the outer annotation when it is empty
+ */
+ public NestedDeclarationAnnotationAdapter(DeclarationAnnotationAdapter outerAnnotationAdapter, String elementName, String annotationName) {
+ super(outerAnnotationAdapter, elementName, annotationName);
+ }
+
+
+ // ********** AbstractNestedDeclarationAnnotationAdapter implementation **********
+
+ @Override
+ protected Annotation getAnnotation(Expression value) {
+ return this.annotationValue(value);
+ }
+
+ @Override
+ protected Expression buildNewInnerExpression(Annotation inner) {
+ return inner;
+ }
+
+ /**
+ * the annotation is the expression itself, so the annotation cannot be
+ * "removed" from itself - return 'false'
+ */
+ @Override
+ protected boolean removeAnnotation(ModifiedDeclaration declaration, Annotation outer, Expression value) {
+ return false;
+ }
+
+ /**
+ * <pre>
+ * &#64;Outer("lorem ipsum") => &#64;Outer(&#64;Inner)
+ * </pre>
+ */
+ @Override
+ protected void modifyAnnotationValue(SingleMemberAnnotation outer, Annotation inner) {
+ // replace(?) the current element value
+ outer.setValue(inner);
+ }
+
+ /**
+ * Simply set the pair's value.
+ */
+ @Override
+ protected void modifyMemberValuePair(MemberValuePair pair, Annotation inner) {
+ pair.setValue(inner);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NestedIndexedDeclarationAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NestedIndexedDeclarationAnnotationAdapter.java
new file mode 100644
index 0000000000..acfd74372f
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NestedIndexedDeclarationAnnotationAdapter.java
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.List;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.ArrayInitializer;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.MemberValuePair;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.IndexedDeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+
+/**
+ * Manipulate an annotation that is embedded in an element array within
+ * another annotation, e.g.
+ * <pre>
+ * &#64;Outer(foo={&#64;Inner("zero"), &#64;Inner("one"), &#64;Inner("two")})
+ * private int id;
+ * outerAnnotationAdapter = AnnotationAdapter<&#64;Outer>
+ * elementName = "foo"
+ * index = 0-2
+ * annotationName = "Inner"
+ * </pre>
+ */
+public class NestedIndexedDeclarationAnnotationAdapter
+ extends AbstractNestedDeclarationAnnotationAdapter
+ implements IndexedDeclarationAnnotationAdapter
+{
+ private int index;
+
+
+ // ********** constructors **********
+
+ /**
+ * The default element name is <code>value</code>.
+ */
+ public NestedIndexedDeclarationAnnotationAdapter(DeclarationAnnotationAdapter annotationAdapter, int index, String annotationName) {
+ super(annotationAdapter, annotationName);
+ this.index = index;
+ }
+
+ public NestedIndexedDeclarationAnnotationAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, int index, String annotationName) {
+ super(annotationAdapter, elementName, annotationName);
+ this.index = index;
+ }
+
+
+ // ********** AbstractNestedDeclarationAnnotationAdapter implementation **********
+
+ @Override
+ protected Annotation getAnnotation(Expression value) {
+ if (value.getNodeType() == ASTNode.ARRAY_INITIALIZER) {
+ return this.annotation((ArrayInitializer) value);
+ }
+ return (this.index == 0) ? this.annotationValue(value) : null;
+ }
+
+ @Override
+ protected Expression buildNewInnerExpression(Annotation inner) {
+ return (this.index == 0) ? inner : (Expression) this.buildNewInnerArrayInitializer(inner);
+ }
+
+ @Override
+ protected boolean removeAnnotation(ModifiedDeclaration declaration, Annotation outer, Expression value) {
+ if (value.getNodeType() == ASTNode.ARRAY_INITIALIZER) {
+ this.removeAnnotation(declaration, outer, (ArrayInitializer) value);
+ return true;
+ }
+ // if our index is greater than zero, but we don't have an array,
+ // then the annotation must already be gone
+ return (this.index != 0);
+ }
+
+ /**
+ * <pre>
+ * &#64;Outer({&#64;Inner(0), &#64;Inner(1)}) => &#64;Outer({&#64;Inner(0), &#64;Inner(1), &#64;Inner(2)})
+ * or
+ * &#64;Outer("lorem ipsum") => &#64;Outer(&#64;Inner(0))
+ * or
+ * &#64;Outer(&#64;Inner(0)) => &#64;Outer({&#64;Inner(0), &#64;Inner(1)})
+ * </pre>
+ */
+ @Override
+ protected void modifyAnnotationValue(SingleMemberAnnotation outer, Annotation inner) {
+ this.modifyExpression(outer, SINGLE_MEMBER_ANNOTATION_EXPRESSION_PROVIDER, inner);
+ }
+
+ /**
+ * <pre>
+ * &#64;Outer(text="lorem ipsum") => &#64;Outer(text="lorem ipsum", foo=&#64;Inner(0))
+ * or
+ * &#64;Outer(foo={&#64;Inner(0), &#64;Inner(1)}) => &#64;Outer(foo={&#64;Inner(0), &#64;Inner(1), &#64;Inner(2)})
+ * or
+ * &#64;Outer(foo="lorem ipsum") => &#64;Outer(foo=&#64;Inner(0))
+ * or
+ * &#64;Outer(foo=&#64;NotInner) => &#64;Outer(foo=&#64;Inner(0))
+ * or
+ * &#64;Outer(foo=&#64;Inner(0)) => &#64;Outer(foo={&#64;Inner(0), &#64;Inner(1)})
+ * </pre>
+ */
+ @Override
+ protected void modifyMemberValuePair(MemberValuePair pair, Annotation inner) {
+ this.modifyExpression(pair, MEMBER_VALUE_PAIR_EXPRESSION_PROVIDER, inner);
+ }
+
+
+ // ********** IndexedDeclarationAnnotationAdapter implementation **********
+
+ public int getIndex() {
+ return this.index;
+ }
+
+ /**
+ * Move the annotation to the specified index, leaving its original
+ * position cleared out.
+ */
+ public void moveAnnotation(int newIndex, ModifiedDeclaration declaration) {
+ int oldIndex = this.index;
+ if (newIndex == oldIndex) {
+ return;
+ }
+
+ Annotation original = this.getAnnotation(declaration);
+ if (original == null) {
+ this.index = newIndex;
+ this.removeAnnotation(declaration); // clear out the new location (?)
+ } else {
+ Annotation copy = (Annotation) ASTNode.copySubtree(original.getAST(), original);
+ this.index = newIndex;
+ this.addAnnotation(declaration, copy); // install the copy in the new location
+ this.index = oldIndex;
+ this.removeAnnotation(declaration); // go back and clear out the original location (AFTER the move)
+ this.index = newIndex;
+ }
+ }
+
+
+ // ********** internal methods **********
+
+ /**
+ * Return the adapter's annotation from the specified array initializer.
+ */
+ private Annotation annotation(ArrayInitializer value) {
+ List<Expression> expressions = this.expressions(value);
+ return (this.index >= expressions.size()) ? null : this.annotationValue(expressions.get(this.index));
+ }
+
+ /**
+ * Build a new array initializer to hold the specified annotation,
+ * padding it with 'null' literals as necessary
+ */
+ private ArrayInitializer buildNewInnerArrayInitializer(Annotation inner) {
+ ArrayInitializer ai = inner.getAST().newArrayInitializer();
+ this.addInnerToExpressions(inner, this.expressions(ai));
+ return ai;
+ }
+
+ /**
+ * Add the specified annotation to the specified array initializer,
+ * padding it with 'null' literals as necessary
+ */
+ private void addInnerToExpressions(Annotation inner, List<Expression> expressions) {
+ if (expressions.size() > this.index) {
+ throw new IllegalStateException("expressions size is greater than index (size: " + expressions.size() + " index: " + this.index + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ while (expressions.size() < this.index) {
+ expressions.add(inner.getAST().newNullLiteral());
+ }
+ expressions.add(inner);
+ }
+
+ /**
+ * Remove the adapter's annotation from the specified array initializer.
+ */
+ private void removeAnnotation(ModifiedDeclaration declaration, Annotation outer, ArrayInitializer value) {
+ List<Expression> expressions = this.expressions(value);
+ if (this.index >= expressions.size()) {
+ return; // avoid IndexOutOfBoundsException(?)
+ }
+ Annotation inner = this.annotationValue(expressions.get(this.index));
+ if (inner == null) {
+ return;
+ }
+ if ( ! this.nameMatches(declaration, inner)) {
+ return;
+ }
+ if (this.index == (expressions.size() - 1)) {
+ expressions.remove(this.index);
+ } else {
+ expressions.set(this.index, value.getAST().newNullLiteral());
+ }
+ this.trimExpressions(declaration, outer, expressions);
+ }
+
+ /**
+ * Strip all the null literals off the end of the specified list of expressions
+ * and normalize the specified outer annotation.
+ */
+ private void trimExpressions(ModifiedDeclaration declaration, Annotation outer, List<Expression> expressions) {
+ // start at the end of the list
+ for (int i = expressions.size(); i-- > 0; ) {
+ if (expressions.get(i).getNodeType() == ASTNode.NULL_LITERAL) {
+ expressions.remove(i);
+ } else {
+ break; // stop with the first non-null literal encountered
+ }
+ }
+ switch (expressions.size()) {
+ case 0:
+ this.removeElementAndNormalize(declaration, outer);
+ break;
+ case 1:
+ this.convertArrayToLastRemainingExpression(outer, expressions.get(0));
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * When there is only a single element in an array initializer, convert the
+ * expression to be just the single element; e.g.
+ * <pre>
+ * &#64;Foo(xxx={"abc"}) => &#64;Foo(xxx="abc")
+ * or
+ * &#64;Foo({"abc"}) => &#64;Foo("abc")
+ * </pre>
+ */
+ private void convertArrayToLastRemainingExpression(Annotation outer, Expression lastValue) {
+ lastValue = (Expression) ASTNode.copySubtree(lastValue.getAST(), lastValue);
+ if (outer.isNormalAnnotation()) {
+ this.memberValuePair((NormalAnnotation) outer).setValue(lastValue);
+ } else if (outer.isSingleMemberAnnotation()) {
+ ((SingleMemberAnnotation) outer).setValue(lastValue);
+ } else {
+ throw new IllegalArgumentException("unexpected annotation type: " + outer); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Manipulate the specified expression appropriately.
+ * If it is an array initializer, add the specified annotation to it.
+ * If it is not, replace the expression or convert it into an array
+ * initializer.
+ */
+ private void modifyExpression(ASTNode node, ExpressionProvider expProvider, Annotation inner) {
+ Expression value = expProvider.getExpression(node);
+ if (value.getNodeType() == ASTNode.ARRAY_INITIALIZER) {
+ // ignore the other entries in the array initializer(?) - they may not be matching Annotations...
+ List<Expression> expressions = this.expressions((ArrayInitializer) value);
+ if (this.index >= expressions.size()) {
+ this.addInnerToExpressions(inner, expressions);
+ } else {
+ expressions.set(this.index, inner);
+ }
+ } else {
+ if (this.index == 0) {
+ // replace whatever was there before
+ expProvider.setExpression(node, inner);
+ } else {
+ // convert to an array
+ ArrayInitializer ai = inner.getAST().newArrayInitializer();
+ List<Expression> expressions = this.expressions(ai);
+ expressions.add((Expression) ASTNode.copySubtree(value.getAST(), value));
+ this.addInnerToExpressions(inner, expressions);
+ expProvider.setExpression(node, ai);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected List<Expression> expressions(ArrayInitializer ai) {
+ return ai.expressions();
+ }
+
+
+ // ********** expression providers **********
+
+ /**
+ * define interface that allows us to "re-use" the code in
+ * #modifyExpression(ASTNode, ExpressionProvider, Annotation)
+ */
+ private interface ExpressionProvider {
+ Expression getExpression(ASTNode node);
+ void setExpression(ASTNode node, Expression expression);
+ }
+
+ private static final ExpressionProvider MEMBER_VALUE_PAIR_EXPRESSION_PROVIDER = new ExpressionProvider() {
+ public Expression getExpression(ASTNode node) {
+ return ((MemberValuePair) node).getValue();
+ }
+ public void setExpression(ASTNode node, Expression expression) {
+ ((MemberValuePair) node).setValue(expression);
+ }
+ @Override
+ public String toString() {
+ return "MemberValuePairExpressionProvider"; //$NON-NLS-1$
+ }
+ };
+
+ private static final ExpressionProvider SINGLE_MEMBER_ANNOTATION_EXPRESSION_PROVIDER = new ExpressionProvider() {
+ public Expression getExpression(ASTNode node) {
+ return ((SingleMemberAnnotation) node).getValue();
+ }
+ public void setExpression(ASTNode node, Expression expression) {
+ ((SingleMemberAnnotation) node).setValue(expression);
+ }
+ @Override
+ public String toString() {
+ return "SingleMemberAnnotationExpressionProvider"; //$NON-NLS-1$
+ }
+ };
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullAnnotationEditFormatter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullAnnotationEditFormatter.java
new file mode 100644
index 0000000000..284e9379b4
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullAnnotationEditFormatter.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationEditFormatter;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.TextEdit;
+
+public final class NullAnnotationEditFormatter
+ implements AnnotationEditFormatter
+{
+
+ private static final NullAnnotationEditFormatter INSTANCE = new NullAnnotationEditFormatter();
+
+ /**
+ * Return the singleton.
+ */
+ public static AnnotationEditFormatter instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private NullAnnotationEditFormatter() {
+ super();
+ }
+
+ public void format(IDocument doc, TextEdit editTree) throws MalformedTreeException, BadLocationException {
+ // no formatting
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullDeclarationAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullDeclarationAnnotationAdapter.java
new file mode 100644
index 0000000000..c9fe2d94e4
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullDeclarationAnnotationAdapter.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.MarkerAnnotation;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jpt.common.core.utility.jdt.IndexedDeclarationAnnotationAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+
+/**
+ * Behaviorless implementation.
+ */
+public final class NullDeclarationAnnotationAdapter
+ implements IndexedDeclarationAnnotationAdapter
+{
+
+ // singleton
+ private static final NullDeclarationAnnotationAdapter INSTANCE = new NullDeclarationAnnotationAdapter();
+
+ /**
+ * Return the singleton.
+ */
+ public static IndexedDeclarationAnnotationAdapter instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private NullDeclarationAnnotationAdapter() {
+ super();
+ }
+
+
+ // ********** DeclarationAnnotationAdapter implementation **********
+
+ public Annotation getAnnotation(ModifiedDeclaration declaration) {
+ return null;
+ }
+
+ public MarkerAnnotation newMarkerAnnotation(ModifiedDeclaration declaration) {
+ return null;
+ }
+
+ public SingleMemberAnnotation newSingleMemberAnnotation(ModifiedDeclaration declaration) {
+ return null;
+ }
+
+ public NormalAnnotation newNormalAnnotation(ModifiedDeclaration declaration) {
+ return null;
+ }
+
+ public void removeAnnotation(ModifiedDeclaration declaration) {
+ // do nothing
+ }
+
+ public ASTNode getAstNode(ModifiedDeclaration declaration) {
+ return declaration.getDeclaration();
+ }
+
+
+ // ********** IndexedDeclarationAnnotationAdapter implementation **********
+
+ public int getIndex() {
+ return -1;
+ }
+
+ public void moveAnnotation(int newIndex, ModifiedDeclaration declaration) {
+ // do nothing
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullDeclarationAnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullDeclarationAnnotationElementAdapter.java
new file mode 100644
index 0000000000..dd3e616a2d
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullDeclarationAnnotationElementAdapter.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationElementAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+
+/**
+ * Behaviorless implementation.
+ */
+public class NullDeclarationAnnotationElementAdapter<T>
+ implements DeclarationAnnotationElementAdapter<T>
+{
+
+ // singleton
+ @SuppressWarnings("rawtypes")
+ private static final DeclarationAnnotationElementAdapter INSTANCE
+ = new NullDeclarationAnnotationElementAdapter();
+
+ /**
+ * Return the singleton.
+ */
+ @SuppressWarnings("unchecked")
+ public static <S> DeclarationAnnotationElementAdapter<S> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private NullDeclarationAnnotationElementAdapter() {
+ super();
+ }
+
+ public T getValue(ModifiedDeclaration declaration) {
+ return null;
+ }
+
+ public void setValue(T value, ModifiedDeclaration declaration) {
+ // do nothing
+ }
+
+ public ASTNode getAstNode(ModifiedDeclaration declaration) {
+ return declaration.getDeclaration();
+ }
+
+ public Expression getExpression(ModifiedDeclaration declaration) {
+ return null;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullExpressionConverter.java
new file mode 100644
index 0000000000..405c70f82c
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NullExpressionConverter.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * No conversion.
+ */
+public final class NullExpressionConverter
+ implements ExpressionConverter<Expression>
+{
+
+ // singleton
+ private static final ExpressionConverter<Expression> INSTANCE = new NullExpressionConverter();
+
+ /**
+ * Return the singleton.
+ */
+ public static ExpressionConverter<Expression> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private NullExpressionConverter() {
+ super();
+ }
+
+ public Expression convert(Expression expression, AST ast) {
+ return expression;
+ }
+
+ public Expression convert(Expression expression) {
+ return expression;
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NumberIntegerExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NumberIntegerExpressionConverter.java
new file mode 100644
index 0000000000..775d2d705a
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/NumberIntegerExpressionConverter.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.NumberLiteral;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+
+/**
+ * Convert a number literal to/from an Integer
+ * (e.g. 5).
+ */
+public final class NumberIntegerExpressionConverter
+ extends AbstractExpressionConverter<Integer>
+{
+ private static final ExpressionConverter<Integer> INSTANCE = new NumberIntegerExpressionConverter();
+
+ /**
+ * Return the singleton.
+ */
+ public static ExpressionConverter<Integer> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private NumberIntegerExpressionConverter() {
+ super();
+ }
+
+ @Override
+ protected NumberLiteral convertObject(Integer integer, AST ast) {
+ return ast.newNumberLiteral(integer.toString());
+ }
+
+ @Override
+ protected Integer convertExpression(Expression expression) {
+ Object value = expression.resolveConstantExpressionValue();
+ return (value instanceof Integer) ? ((Integer) value) : null;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/PrimitiveTypeStringExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/PrimitiveTypeStringExpressionConverter.java
new file mode 100644
index 0000000000..7b17501e51
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/PrimitiveTypeStringExpressionConverter.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.TypeLiteral;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+
+/**
+ * Convert a type literal to/from a string representation of a primitive type
+ * (e.g. "int").
+ */
+public final class PrimitiveTypeStringExpressionConverter
+ extends AbstractExpressionConverter<String>
+{
+ private static final ExpressionConverter<String> INSTANCE = new PrimitiveTypeStringExpressionConverter();
+
+ /**
+ * Return the singleton.
+ */
+ public static ExpressionConverter<String> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private PrimitiveTypeStringExpressionConverter() {
+ super();
+ }
+
+ @Override
+ protected TypeLiteral convertObject(String string, AST ast) {
+ org.eclipse.jdt.core.dom.Type type = ast.newPrimitiveType(PrimitiveType.toCode(string));
+ TypeLiteral typeLiteral = ast.newTypeLiteral();
+ typeLiteral.setType(type);
+ return typeLiteral;
+ }
+
+ @Override
+ protected String convertExpression(Expression expression) {
+ if (expression.getNodeType() == ASTNode.TYPE_LITERAL) {
+ org.eclipse.jdt.core.dom.Type type = ((TypeLiteral) expression).getType();
+ if (type.getNodeType() == ASTNode.PRIMITIVE_TYPE) {
+ return ((PrimitiveType) type).getPrimitiveTypeCode().toString();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ShortCircuitAnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ShortCircuitAnnotationElementAdapter.java
new file mode 100644
index 0000000000..0f702424f8
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ShortCircuitAnnotationElementAdapter.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotatedElement;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationElementAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationElementAdapter;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Wrap another annotation element adapter and short-circuit the
+ * #setValue method if the value has not changed.
+ */
+public class ShortCircuitAnnotationElementAdapter<T>
+ implements AnnotationElementAdapter<T>
+{
+ /** the wrapped adapter */
+ private final AnnotationElementAdapter<T> adapter;
+
+
+ // ********** constructor **********
+
+ public ShortCircuitAnnotationElementAdapter(AnnotatedElement annotatedElement, DeclarationAnnotationElementAdapter<T> daea) {
+ this(new AnnotatedElementAnnotationElementAdapter<T>(annotatedElement, daea));
+ }
+
+ public ShortCircuitAnnotationElementAdapter(AnnotationElementAdapter<T> adapter) {
+ super();
+ this.adapter = adapter;
+ }
+
+
+ // ********** AnnotationElementAdapter implementation **********
+
+ public T getValue() {
+ return this.adapter.getValue();
+ }
+
+ public T getValue(CompilationUnit astRoot) {
+ return this.adapter.getValue(astRoot);
+ }
+
+ public void setValue(T value) {
+ this.setValue(this.adapter.getValue(), value);
+ }
+
+ public Expression getExpression(CompilationUnit astRoot) {
+ return this.adapter.getExpression(astRoot);
+ }
+
+ public ASTNode getAstNode(CompilationUnit astRoot) {
+ return this.adapter.getAstNode(astRoot);
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.adapter);
+ }
+
+
+ // ********** internal methods **********
+
+ /**
+ * set the adapter's value to the specified new value if it
+ * is different from the specified old value
+ */
+ protected void setValue(T oldValue, T newValue) {
+ if (oldValue == null) {
+ if (newValue == null) { // null => null
+ // do nothing
+ } else { // null => object
+ this.adapter.setValue(newValue);
+ }
+ } else {
+ if (newValue == null) { // object => null
+ this.adapter.setValue(null);
+ } else { // object => object
+ if (this.valuesAreEqual(oldValue, newValue)) {
+ // do nothing
+ } else {
+ this.adapter.setValue(newValue);
+ }
+ }
+ }
+ }
+
+ /**
+ * both values are non-null when this method is called
+ */
+ protected boolean valuesAreEqual(T oldValue, T newValue) {
+ return newValue.equals(oldValue);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ShortCircuitArrayAnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ShortCircuitArrayAnnotationElementAdapter.java
new file mode 100644
index 0000000000..0676bc2840
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/ShortCircuitArrayAnnotationElementAdapter.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.Arrays;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotatedElement;
+import org.eclipse.jpt.common.core.utility.jdt.AnnotationElementAdapter;
+import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationElementAdapter;
+
+/**
+ * Wrap another annotation element adapter and short-circuit the
+ * #setValue method if the value has not changed. Overrides #valuesAreEqual()
+ * to check equality on arrays
+ */
+public class ShortCircuitArrayAnnotationElementAdapter<T>
+ extends ShortCircuitAnnotationElementAdapter<T[]>
+{
+ // ********** constructor **********
+
+ public ShortCircuitArrayAnnotationElementAdapter(AnnotatedElement annotatedElement, DeclarationAnnotationElementAdapter<T[]> daea) {
+ super(annotatedElement, daea);
+ }
+
+ public ShortCircuitArrayAnnotationElementAdapter(AnnotationElementAdapter<T[]> adapter) {
+ super(adapter);
+ }
+
+
+ // ********** AnnotationElementAdapter implementation **********
+
+ @Override
+ protected boolean valuesAreEqual(T[] oldValue, T[] newValue) {
+ return Arrays.equals(newValue, oldValue);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/SimpleDeclarationAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/SimpleDeclarationAnnotationAdapter.java
new file mode 100644
index 0000000000..195dc197ec
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/SimpleDeclarationAnnotationAdapter.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jpt.common.core.utility.jdt.ModifiedDeclaration;
+
+/**
+ * Manipulate an annotation with a specific name, e.g.
+ * <pre>
+ * &#64;Foo
+ * private int id;
+ * </pre>
+ *
+ * NB:
+ * If the declaration contains more than one annotation with the same
+ * name, the adapter will correspond to the first annotation with the specified
+ * name. (Also note that the compiler will not allow a declaration to be
+ * modified by multiple annotations with the same name, i.e. of the same type;
+ * so if there *are* multiple annotations of the same type, there are bigger
+ * problems to worry about than which annotation the adapter manipulates.)
+ */
+public class SimpleDeclarationAnnotationAdapter extends AbstractDeclarationAnnotationAdapter {
+
+
+ // ********** constructors **********
+
+ public SimpleDeclarationAnnotationAdapter(String annotationName) {
+ super(annotationName);
+ }
+
+
+ // ********** DeclarationAnnotationAdapter implementation **********
+
+ public Annotation getAnnotation(ModifiedDeclaration declaration) {
+ return declaration.getAnnotationNamed(this.getAnnotationName());
+ }
+
+ public void removeAnnotation(ModifiedDeclaration declaration) {
+ declaration.removeAnnotationNamed(this.getAnnotationName());
+ }
+
+ @Override
+ protected void addAnnotation(ModifiedDeclaration declaration, Annotation annotation) {
+ declaration.replaceAnnotationNamed(this.getAnnotationName(), annotation);
+ }
+
+ public ASTNode getAstNode(ModifiedDeclaration declaration) {
+ // if the annotation is missing, return the declaration
+ Annotation annotation = this.getAnnotation(declaration);
+ return (annotation != null) ? annotation : declaration.getDeclaration();
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/SimpleTypeStringExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/SimpleTypeStringExpressionConverter.java
new file mode 100644
index 0000000000..156dc5fa73
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/SimpleTypeStringExpressionConverter.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.SimpleType;
+import org.eclipse.jdt.core.dom.TypeLiteral;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+
+/**
+ * Convert a type literal to/from a string representation of a simple type
+ * (e.g. "java.lang.Object").
+ */
+public final class SimpleTypeStringExpressionConverter
+ extends AbstractExpressionConverter<String>
+{
+ private static final ExpressionConverter<String> INSTANCE = new SimpleTypeStringExpressionConverter();
+
+ /**
+ * Return the singleton.
+ */
+ public static ExpressionConverter<String> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private SimpleTypeStringExpressionConverter() {
+ super();
+ }
+
+ @Override
+ protected TypeLiteral convertObject(String string, AST ast) {
+ Name name = ast.newName(string);
+ org.eclipse.jdt.core.dom.Type type = ast.newSimpleType(name);
+ TypeLiteral typeLiteral = ast.newTypeLiteral();
+ typeLiteral.setType(type);
+ return typeLiteral;
+ }
+
+ @Override
+ protected String convertExpression(Expression expression) {
+ if (expression.getNodeType() == ASTNode.TYPE_LITERAL) {
+ org.eclipse.jdt.core.dom.Type type = ((TypeLiteral) expression).getType();
+ if (type.getNodeType() == ASTNode.SIMPLE_TYPE) {
+ return ((SimpleType) type).getName().getFullyQualifiedName();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/StringArrayExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/StringArrayExpressionConverter.java
new file mode 100644
index 0000000000..ddd37ad5d0
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/StringArrayExpressionConverter.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import java.util.List;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ArrayInitializer;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Convert an array initializer to/from an array of strings (e.g. {"text0", "text1"}).
+ *
+ * Do NOT use this class for converting array initializers in annotation elements.
+ * Java5 has a bit of syntactic sugar that allows a single-element array
+ * initializer to not have curly braces. This converter will return null if it encounters
+ * anything other than an array initializer.
+ *
+ * Invalid entries in the array initializer will result in null elements in the
+ * resulting string array. This allows clients to manipulate elements at
+ * the appropriate index.
+ */
+public class StringArrayExpressionConverter
+ extends AbstractExpressionConverter<String[]>
+{
+ private final ExpressionConverter<String> elementConverter;
+ private final boolean removeArrayInitializerWhenEmpty;
+
+
+ /**
+ * The default behavior is to remove the array initializer if it is empty.
+ */
+ public StringArrayExpressionConverter(ExpressionConverter<String> elementConverter) {
+ this(elementConverter, true);
+ }
+
+ public StringArrayExpressionConverter(ExpressionConverter<String> elementConverter, boolean removeArrayInitializerWhenEmpty) {
+ super();
+ this.elementConverter = elementConverter;
+ this.removeArrayInitializerWhenEmpty = removeArrayInitializerWhenEmpty;
+ }
+
+ /*
+ * this method is 'public' so it can be called by
+ * AnnotationStringArrayExpressionConverter
+ */
+ @Override
+ public ArrayInitializer convertObject(String[] strings, AST ast) {
+ if ((strings.length == 0) && this.removeArrayInitializerWhenEmpty) {
+ return null;
+ }
+ ArrayInitializer arrayInitializer = ast.newArrayInitializer();
+ List<Expression> expressions = this.expressions(arrayInitializer);
+ for (String string : strings) {
+ expressions.add(this.elementConverter.convert(string, ast));
+ }
+ return arrayInitializer;
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<Expression> expressions(ArrayInitializer arrayInitializer) {
+ return arrayInitializer.expressions();
+ }
+
+ /*
+ * this method is 'public' so it can be called by
+ * AnnotationStringArrayExpressionConverter
+ */
+ @Override
+ public String[] convertNull() {
+ return StringTools.EMPTY_STRING_ARRAY;
+ }
+
+ @Override
+ protected String[] convertExpression(Expression expression) {
+ return (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) ?
+ this.convertArrayInitializer((ArrayInitializer) expression) :
+ StringTools.EMPTY_STRING_ARRAY;
+ }
+
+ /*
+ * this method is 'public' so it can be called by
+ * AnnotationStringArrayExpressionConverter
+ */
+ public String[] convertArrayInitializer(ArrayInitializer arrayInitializer) {
+ List<Expression> expressions = this.expressions(arrayInitializer);
+ int len = expressions.size();
+ String[] strings = new String[len];
+ for (int i = len; i-- > 0; ) {
+ strings[i] = this.elementConverter.convert(expressions.get(i));
+ }
+ return strings;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/StringExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/StringExpressionConverter.java
new file mode 100644
index 0000000000..f0e88b5331
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/StringExpressionConverter.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.StringLiteral;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+
+/**
+ * Convert a string literal to/from a string (e.g. "text").
+ */
+public final class StringExpressionConverter
+ extends AbstractExpressionConverter<String>
+{
+ private static final ExpressionConverter<String> INSTANCE = new StringExpressionConverter();
+
+ /**
+ * Return the singleton.
+ */
+ public static ExpressionConverter<String> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private StringExpressionConverter() {
+ super();
+ }
+
+ @Override
+ protected StringLiteral convertObject(String string, AST ast) {
+ StringLiteral stringLiteral = ast.newStringLiteral();
+ stringLiteral.setLiteralValue(string);
+ return stringLiteral;
+ }
+
+ @Override
+ protected String convertExpression(Expression expression) {
+ Object value = expression.resolveConstantExpressionValue();
+ return (value instanceof String) ? (String) value : null;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/TypeStringExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/TypeStringExpressionConverter.java
new file mode 100644
index 0000000000..3ed1b74189
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/jdt/TypeStringExpressionConverter.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.TypeLiteral;
+import org.eclipse.jpt.common.core.utility.jdt.ExpressionConverter;
+
+/**
+ * Convert a type literal to/from a string representation of a
+ * simple type (e.g. "java.lang.Object") or primitive type (e.g. "int").
+ */
+public final class TypeStringExpressionConverter
+ extends AbstractExpressionConverter<String>
+{
+ private static final ExpressionConverter<String> INSTANCE = new TypeStringExpressionConverter();
+
+ /**
+ * Return the singleton.
+ */
+ public static ExpressionConverter<String> instance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Ensure single instance.
+ */
+ private TypeStringExpressionConverter() {
+ super();
+ }
+
+ @Override
+ protected TypeLiteral convertObject(String string, AST ast) {
+ if (PrimitiveType.toCode(string) != null) {
+ return (TypeLiteral) PrimitiveTypeStringExpressionConverter.instance().convert(string, ast);
+ }
+ return (TypeLiteral) SimpleTypeStringExpressionConverter.instance().convert(string, ast);
+ }
+
+ @Override
+ protected String convertExpression(Expression expression) {
+ String name = SimpleTypeStringExpressionConverter.instance().convert(expression);
+ return name != null ? name : PrimitiveTypeStringExpressionConverter.instance().convert(expression);
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/BooleanTranslator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/BooleanTranslator.java
new file mode 100644
index 0000000000..7f2825c1a3
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/BooleanTranslator.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.translators;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.wst.common.internal.emf.resource.Translator;
+
+public class BooleanTranslator
+ extends Translator
+{
+ public BooleanTranslator(String domPathAndNames, EStructuralFeature structuralFeature) {
+ super(domPathAndNames, structuralFeature, BOOLEAN_FEATURE | BOOLEAN_LOWERCASE);
+ }
+
+ public BooleanTranslator(String domPathAndNames, EStructuralFeature structuralFeature, int style) {
+ super(domPathAndNames, structuralFeature, BOOLEAN_FEATURE | BOOLEAN_LOWERCASE | style);
+ }
+
+ @Override
+ public Object convertStringToValue(String string, EObject owner) {
+ return Boolean.valueOf(string);
+ }
+
+ @Override
+ public String convertValueToString(Object value, EObject owner) {
+ return ((Boolean) value).toString();
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/EmptyTagBooleanTranslator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/EmptyTagBooleanTranslator.java
new file mode 100644
index 0000000000..1d94705cca
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/EmptyTagBooleanTranslator.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.translators;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.wst.common.internal.emf.resource.Translator;
+
+/**
+ * This translator is to be used for empty xml tags that correspond
+ * to a boolean attribute in the emf model.
+ * cascade-persist is an example from the orm.xsd:
+ *
+ * <persistence-unit-defaults>
+ * <cascade-persist/>
+ * </persistence-unit-defaults> ==> cascadePersist == true
+ *
+ * vs.
+ *
+ * <persistence-unit-defaults>
+ * </persistence-unit-defaults> ==> cascadePersist == false
+ *
+ */
+public class EmptyTagBooleanTranslator
+ extends Translator
+{
+ public EmptyTagBooleanTranslator(String domPathAndNames, EStructuralFeature structuralFeature) {
+ this(domPathAndNames, structuralFeature, NO_STYLE);
+ }
+
+ public EmptyTagBooleanTranslator(String domPathAndNames, EStructuralFeature structuralFeature, int style) {
+ super(domPathAndNames, structuralFeature, style | EMPTY_TAG | BOOLEAN_FEATURE);
+ }
+
+ @Override
+ public Object getMOFValue(EObject mofObject) {
+ // I am overriding this method. This is so the tag will be removed when
+ // the value is false.
+ // I'm not sure if this is a bug in the ecore or maybe in the translators,
+ // but I really don't think that we should have to depend on the boolean
+ // being "unset" to remove the tag.
+ Boolean value = (Boolean) super.getMOFValue(mofObject);
+ return (value == null) ? null : value.booleanValue() ? value : null;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/EnumeratedValueTranslator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/EnumeratedValueTranslator.java
new file mode 100644
index 0000000000..fc74b4a730
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/EnumeratedValueTranslator.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 Oracle.
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.translators;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.wst.common.internal.emf.resource.Translator;
+
+public abstract class EnumeratedValueTranslator
+ extends Translator
+{
+ public EnumeratedValueTranslator(String domPathAndNames, EStructuralFeature structuralFeature) {
+ super(domPathAndNames, structuralFeature);
+ }
+
+ public EnumeratedValueTranslator(String domPathAndNames, EStructuralFeature structuralFeature, int style) {
+ super(domPathAndNames, structuralFeature, style);
+ }
+
+
+ protected abstract Iterable<?> getEnumeratedObjectValues();
+
+ @Override
+ public Object convertStringToValue(String string, EObject owner) {
+ for (Object each : getEnumeratedObjectValues()) {
+ if (each.toString().equals(string)) {
+ return each;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String convertValueToString(Object value, EObject owner) {
+ return value.toString();
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/SimpleRootTranslator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/SimpleRootTranslator.java
new file mode 100644
index 0000000000..1129172c05
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/SimpleRootTranslator.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.translators;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.jpt.utility.internal.ArrayTools;
+import org.eclipse.wst.common.internal.emf.resource.RootTranslator;
+import org.eclipse.wst.common.internal.emf.resource.Translator;
+
+/**
+ * Root translator that contains a list of child translators and no special
+ * behavior.
+ */
+public class SimpleRootTranslator
+ extends RootTranslator
+{
+ protected Translator[] children;
+
+ public SimpleRootTranslator(String domPathAndNames, EClass eClass) {
+ super(domPathAndNames, eClass);
+ }
+
+ public SimpleRootTranslator(String domPathAndNames, EClass eClass, Translator[] children) {
+ super(domPathAndNames, eClass);
+ this.children = children;
+ }
+
+ /**
+ * Widen method access to 'public'.
+ */
+ @Override
+ public Translator[] getChildren() {
+ return this.children;
+ }
+
+ protected Translator[] getChildren_() {
+ return (this.children == null) ? EMPTY_TRANSLATOR_ARRAY : this.children;
+ }
+ protected static final Translator[] EMPTY_TRANSLATOR_ARRAY = new Translator[0];
+
+ /**
+ * Set the translator's children.
+ * Return the translator.
+ */
+ public void setChildren(Translator[] children) {
+ this.children = children;
+ }
+
+ /**
+ * Add the specified translator to the translator's list of children.
+ * Return the translator for method chaining.
+ */
+ public SimpleRootTranslator addChild(Translator translator) {
+ this.children = ArrayTools.add(this.getChildren_(), translator);
+ return this;
+ }
+
+ /**
+ * Add the specified translators to the translator's list of children.
+ * Return the translator for method chaining.
+ */
+ public SimpleRootTranslator addChildren(Translator[] translators) {
+ this.children = ArrayTools.addAll(this.getChildren_(), translators);
+ return this;
+ }
+
+ /**
+ * Remove the specified translator from the translator's list of children.
+ * Return the translator for method chaining.
+ */
+ public SimpleRootTranslator removeChild(Translator translator) {
+ this.children = ArrayTools.remove(this.children, translator);
+ return this;
+ }
+
+ /**
+ * Remove the specified translators from the translator's list of children.
+ * Return the translator for method chaining.
+ */
+ public SimpleRootTranslator removeChildren(Translator[] translators) {
+ this.children = ArrayTools.removeAll(this.children, (Object[]) translators);
+ return this;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/SimpleTranslator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/SimpleTranslator.java
new file mode 100644
index 0000000000..4be40679e3
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/internal/utility/translators/SimpleTranslator.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.internal.utility.translators;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.jpt.utility.internal.ArrayTools;
+import org.eclipse.wst.common.internal.emf.resource.Translator;
+import org.eclipse.wst.common.internal.emf.resource.TranslatorPath;
+
+/**
+ * Translator that contains a list of child translators and no special
+ * behavior.
+ */
+public class SimpleTranslator
+ extends Translator
+{
+ protected Translator[] children;
+
+
+ // ********** constructors **********
+
+ public SimpleTranslator(String domPathAndNames, EClass eClass) {
+ super(domPathAndNames, eClass);
+ }
+
+ public SimpleTranslator(String domPathAndNames, EStructuralFeature eStructuralFeature) {
+ super(domPathAndNames, eStructuralFeature);
+ }
+
+ public SimpleTranslator(String domPathAndNames, EStructuralFeature eStructuralFeature, Translator[] children) {
+ super(domPathAndNames, eStructuralFeature);
+ this.children = children;
+ }
+
+ public SimpleTranslator(String domPathAndNames, EStructuralFeature eStructuralFeature, EClass eClass) {
+ super(domPathAndNames, eStructuralFeature, eClass);
+ }
+
+ public SimpleTranslator(String domPathAndNames, EStructuralFeature eStructuralFeature, EClass eClass, Translator[] children) {
+ super(domPathAndNames, eStructuralFeature, eClass);
+ this.children = children;
+ }
+
+ public SimpleTranslator(String domPathAndNames, EStructuralFeature eStructuralFeature, TranslatorPath translatorPath) {
+ super(domPathAndNames, eStructuralFeature, translatorPath);
+ }
+
+ public SimpleTranslator(String domPathAndNames, EStructuralFeature eStructuralFeature, TranslatorPath[] translatorPaths) {
+ super(domPathAndNames, eStructuralFeature, translatorPaths);
+ }
+
+ public SimpleTranslator(String domPathAndNames, EStructuralFeature eStructuralFeature, int style) {
+ super(domPathAndNames, eStructuralFeature, style);
+ }
+
+ public SimpleTranslator(String domPathAndNames, EStructuralFeature aFeature, int style, EClass eClass, Translator[] children) {
+ this(domPathAndNames, aFeature, style);
+ setEMFClass(eClass);
+ this.children = children;
+ }
+
+ public SimpleTranslator(String domPathAndNames, EStructuralFeature eStructuralFeature, int style, Translator[] children) {
+ super(domPathAndNames, eStructuralFeature, style);
+ this.children = children;
+ }
+
+
+ // ********** children **********
+
+ /**
+ * Widen method access to 'public'.
+ */
+ @Override
+ public Translator[] getChildren() {
+ return this.children;
+ }
+
+ protected Translator[] getChildren_() {
+ return (this.children == null) ? EMPTY_TRANSLATOR_ARRAY : this.children;
+ }
+ protected static final Translator[] EMPTY_TRANSLATOR_ARRAY = new Translator[0];
+
+ /**
+ * Set the translator's children.
+ * Return the translator.
+ */
+ public void setChildren(Translator[] children) {
+ this.children = children;
+ }
+
+ /**
+ * Add the specified translator to the translator's list of children.
+ * Return the translator for method chaining.
+ */
+ public SimpleTranslator addChild(Translator translator) {
+ this.children = ArrayTools.add(this.getChildren_(), translator);
+ return this;
+ }
+
+ /**
+ * Add the specified translators to the translator's list of children.
+ * Return the translator for method chaining.
+ */
+ public SimpleTranslator addChildren(Translator[] translators) {
+ this.children = ArrayTools.addAll(this.getChildren_(), translators);
+ return this;
+ }
+
+ /**
+ * Remove the specified translator from the translator's list of children.
+ * Return the translator for method chaining.
+ */
+ public SimpleTranslator removeChild(Translator translator) {
+ this.children = ArrayTools.remove(this.children, translator);
+ return this;
+ }
+
+ /**
+ * Remove the specified translators from the translator's list of children.
+ * Return the translator for method chaining.
+ */
+ public SimpleTranslator removeChildren(Translator[] translators) {
+ this.children = ArrayTools.removeAll(this.children, (Object[]) translators);
+ return this;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/libprov/JptLibraryProviderInstallOperationConfig.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/libprov/JptLibraryProviderInstallOperationConfig.java
new file mode 100644
index 0000000000..edd548d72a
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/libprov/JptLibraryProviderInstallOperationConfig.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.libprov;
+
+import org.eclipse.jst.common.project.facet.core.libprov.ILibraryProvider;
+import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
+
+/**
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * @version 3.0
+ * @since 3.0
+ */
+public interface JptLibraryProviderInstallOperationConfig {
+
+ ILibraryProvider getLibraryProvider();
+
+ IProjectFacetVersion getProjectFacetVersion();
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/libval/LibraryValidator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/libval/LibraryValidator.java
new file mode 100644
index 0000000000..af15c438ce
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/libval/LibraryValidator.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.libval;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jpt.common.core.libprov.JptLibraryProviderInstallOperationConfig;
+
+/**
+ * Interface for extender-supplied library validators.
+ * Each library validator must have a zero-arg constructor.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * @version 3.0
+ * @since 3.0
+ */
+public interface LibraryValidator {
+
+ IStatus validate(JptLibraryProviderInstallOperationConfig config);
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/resource/ResourceLocator.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/resource/ResourceLocator.java
new file mode 100644
index 0000000000..491608c147
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/resource/ResourceLocator.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.common.core.resource;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * @version 3.0
+ * @since 3.0
+ */
+public interface ResourceLocator {
+
+ /**
+ * Return whether the given container is an acceptable (non-java) resource
+ * location for the given project
+ */
+ boolean acceptResourceLocation(IProject project, IContainer container);
+
+ /**
+ * Return the default location in which to create new (non-java) resources
+ */
+ IContainer getDefaultResourceLocation(IProject project);
+
+ /**
+ * Return the workspace relative absolute resource path best represented by the given
+ * runtime path for the given project
+ */
+ IPath getResourcePath(IProject project, IPath runtimePath);
+
+ /**
+ * Return the runtime path best represented by the given workspace relative absolute
+ * resource path for the given project
+ */
+ IPath getRuntimePath(IProject project, IPath resourcePath);
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/AbstractTextRange.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/AbstractTextRange.java
new file mode 100644
index 0000000000..73b7b9b5e0
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/AbstractTextRange.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility;
+
+import org.eclipse.jpt.utility.internal.StringTools;
+
+/**
+ * Partial implementation of text range.
+ *
+ * Provisional API: This class is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * @version 2.0
+ * @since 2.0
+ */
+public abstract class AbstractTextRange
+ implements TextRange
+{
+
+ public boolean includes(int index) {
+ return (this.getOffset() <= index) && (index < this.end());
+ }
+
+ public boolean touches(int index) {
+ return this.includes(index) || (index == this.end());
+ }
+
+ /**
+ * The end offset is "exclusive", i.e. the element at the end offset
+ * is not included in the range.
+ */
+ protected int end() {
+ return this.getOffset() + this.getLength();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if ( ! (o instanceof TextRange)) {
+ return false;
+ }
+ TextRange r = (TextRange) o;
+ return (r.getOffset() == this.getOffset())
+ && (r.getLength() == this.getLength());
+ }
+
+ @Override
+ public int hashCode() {
+ return this.getOffset() ^ this.getLength();
+ }
+
+ @Override
+ public String toString() {
+ String start = String.valueOf(this.getOffset());
+ String end = String.valueOf(this.end());
+ return StringTools.buildToStringFor(this, start + ", " + end); //$NON-NLS-1$
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/BodySourceWriter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/BodySourceWriter.java
new file mode 100644
index 0000000000..6ebdaeb911
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/BodySourceWriter.java
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility;
+
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeSet;
+
+import org.eclipse.jpt.utility.Filter;
+import org.eclipse.jpt.utility.IndentingPrintWriter;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.jpt.utility.internal.Transformer;
+import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;
+
+import com.ibm.icu.text.Collator;
+
+/**
+ * Extend {@link IndentingPrintWriter} with some methods that facilitate
+ * building class source code.
+ */
+@SuppressWarnings("nls")
+public class BodySourceWriter
+ extends IndentingPrintWriter
+{
+ protected final String packageName;
+ protected final String className;
+ // key = short class name; value = import package
+ protected final HashMap<String, ImportPackage> imports = new HashMap<String, ImportPackage>();
+
+ public BodySourceWriter(String packageName, String className) {
+ super(new StringWriter(2000));
+ this.packageName = packageName;
+ this.className = className;
+ }
+
+ public String getSource() {
+ return this.out.toString();
+ }
+
+ public int getLength() {
+ return ((StringWriter) this.out).getBuffer().length();
+ }
+
+ protected void printVisibility(String visibilityModifier) {
+ if (visibilityModifier.length() != 0) {
+ this.print(visibilityModifier);
+ this.print(' ');
+ }
+ }
+
+ public void printAnnotation(String annotationName) {
+ this.print('@');
+ this.printTypeDeclaration(annotationName);
+ }
+
+ public void printTypeDeclaration(String typeDeclaration) {
+ this.print(this.buildImportedTypeDeclaration(typeDeclaration));
+ }
+
+ protected void printField(String fieldName, String typeDeclaration, String visibility) {
+ this.printVisibility(visibility);
+ this.printTypeDeclaration(typeDeclaration);
+ this.print(' ');
+ this.print(fieldName);
+ this.print(';');
+ this.println();
+ this.println();
+ }
+
+ protected void printParameterizedField(String fieldName, String typeDeclaration, String parameterTypeDeclaration, String visibility) {
+ this.printVisibility(visibility);
+ this.printTypeDeclaration(typeDeclaration);
+ this.print('<');
+ this.printTypeDeclaration(parameterTypeDeclaration);
+ this.print('>');
+ this.print(' ');
+ this.print(fieldName);
+ this.print(';');
+ this.println();
+ this.println();
+ }
+
+ /**
+ * Convert the specified string to a <em>String Literal</em> and print it,
+ * adding the surrounding double-quotes and escaping characters
+ * as necessary.
+ */
+ public void printStringLiteral(String string) {
+ StringTools.convertToJavaStringLiteralOn(string, this);
+ }
+
+
+ // ********** imports **********
+
+ // ***** writing
+ /**
+ * Return the specified class's "imported" name.
+ * The class declaration must be of the form:
+ * "int"
+ * "int[]" (not "[I")
+ * "java.lang.Object"
+ * "java.lang.Object[]" (not "[Ljava.lang.Object;")
+ * "java.util.Map.Entry" (not "java.util.Map$Entry")
+ * "java.util.Map.Entry[][]" (not "[[Ljava.util.Map$Entry;")
+ *
+ * To really do this right, we would need to gather all the types from
+ * the "unamed" (default) package that were referenced in the
+ * compilation unit beforehand. *Any* collisions with one of these
+ * types would have to be fully qualified (whether it was from
+ * 'java.lang' or the same package as the current compilation unit).
+ * In other words, if we have any types from the "unnamed" package,
+ * results are unpredictable....
+ */
+ protected String buildImportedTypeDeclaration(String typeDeclaration) {
+ if (this.typeDeclarationIsMemberClass(typeDeclaration)) {
+ // no need for an import, just return the partially-qualified name
+ return this.buildMemberClassTypeDeclaration(typeDeclaration);
+ }
+ int last = typeDeclaration.lastIndexOf('.');
+ String currentPackageName = (last == -1) ? "" : typeDeclaration.substring(0, last);
+ String shortTypeDeclaration = typeDeclaration.substring(last + 1);
+ String shortElementTypeName = shortTypeDeclaration;
+ while (shortElementTypeName.endsWith("[]")) {
+ shortElementTypeName = shortElementTypeName.substring(0, shortElementTypeName.length() - 2);
+ }
+ ImportPackage prev = this.imports.get(shortElementTypeName);
+ if (prev == null) {
+ // this is the first class with this short element type name
+ this.imports.put(shortElementTypeName, new ImportPackage(currentPackageName));
+ return shortTypeDeclaration;
+ }
+ if (prev.packageName.equals(currentPackageName)) {
+ // this element type has already been imported
+ return shortTypeDeclaration;
+ }
+ if (currentPackageName.equals(this.packageName) &&
+ prev.packageName.equals("java.lang")) {
+ // we force the 'java.lang' class to be explicitly imported
+ prev.collision = true;
+ }
+ // another class with the same short element type name has been
+ // previously imported, so this one must be used fully-qualified
+ return typeDeclaration;
+ }
+
+ /**
+ * e.g. "foo.bar.Employee.PK" will return true
+ */
+ protected boolean typeDeclarationIsMemberClass(String typeDeclaration) {
+ return (typeDeclaration.length() > this.className.length())
+ && typeDeclaration.startsWith(this.className)
+ && (typeDeclaration.charAt(this.className.length()) == '.');
+ }
+
+ /**
+ * e.g. "foo.bar.Employee.PK" will return "Employee.PK"
+ * this prevents collisions with other imported classes (e.g. "joo.jar.PK")
+ */
+ protected String buildMemberClassTypeDeclaration(String typeDeclaration) {
+ int index = this.packageName.length();
+ if (index != 0) {
+ index++; // bump past the '.'
+ }
+ return typeDeclaration.substring(index);
+ }
+
+ // ***** reading
+ public Iterable<String> getImports() {
+ return this.getSortedRequiredImports();
+ }
+
+ /**
+ * transform our map entries to class names
+ */
+ protected Iterable<String> getSortedRequiredImports() {
+ return new TransformationIterable<Map.Entry<String, ImportPackage>, String>(this.getSortedRequiredImportEntries(), this.buildImportEntriesTransformer());
+ }
+
+ protected Transformer<Map.Entry<String, ImportPackage>, String> buildImportEntriesTransformer() {
+ return IMPORT_ENTRIES_TRANSFORMER;
+ }
+
+ protected static final Transformer<Map.Entry<String, ImportPackage>, String> IMPORT_ENTRIES_TRANSFORMER = new ImportEntriesTransformer();
+
+ protected static class ImportEntriesTransformer
+ implements Transformer<Map.Entry<String, ImportPackage>, String>
+ {
+ public String transform(Entry<String, ImportPackage> importEntry) {
+ String pkg = importEntry.getValue().packageName;
+ String type = importEntry.getKey();
+ StringBuilder sb = new StringBuilder(pkg.length() + 1 + type.length());
+ sb.append(pkg);
+ sb.append('.');
+ sb.append(type);
+ return sb.toString();
+ }
+ }
+
+ /**
+ * sort by package first, then class (*not* by fully-qualified class name)
+ */
+ protected Iterable<Map.Entry<String, ImportPackage>> getSortedRequiredImportEntries() {
+ TreeSet<Map.Entry<String, ImportPackage>> sortedEntries = new TreeSet<Map.Entry<String, ImportPackage>>(this.buildImportEntriesComparator());
+ CollectionTools.addAll(sortedEntries, this.getRequiredImportEntries());
+ return sortedEntries;
+ }
+
+ protected Comparator<Map.Entry<String, ImportPackage>> buildImportEntriesComparator() {
+ return IMPORT_ENTRIES_COMPARATOR;
+ }
+
+ protected static final Comparator<Map.Entry<String, ImportPackage>> IMPORT_ENTRIES_COMPARATOR = new ImportEntriesComparator();
+
+ protected static class ImportEntriesComparator
+ implements Comparator<Map.Entry<String, ImportPackage>>, Serializable
+ {
+ public int compare(Map.Entry<String, ImportPackage> e1, Map.Entry<String, ImportPackage> e2) {
+ Collator collator = Collator.getInstance();
+ int pkg = collator.compare(e1.getValue().packageName, e2.getValue().packageName);
+ return (pkg == 0) ? collator.compare(e1.getKey(), e2.getKey()) : pkg;
+ }
+ }
+
+ /**
+ * strip off any non-required imports (e.g. "java.lang.Object')
+ */
+ protected Iterable<Map.Entry<String, ImportPackage>> getRequiredImportEntries() {
+ return new FilteringIterable<Map.Entry<String, ImportPackage>>(this.imports.entrySet(), this.buildRequiredImportEntriesFilter());
+ }
+
+ protected Filter<Map.Entry<String, ImportPackage>> buildRequiredImportEntriesFilter() {
+ return new RequiredImportEntriesFilter();
+ }
+
+ protected class RequiredImportEntriesFilter
+ implements Filter<Map.Entry<String, ImportPackage>>
+ {
+ public boolean accept(Map.Entry<String, ImportPackage> importEntry) {
+ return this.packageMustBeImported(importEntry.getValue());
+ }
+
+ protected boolean packageMustBeImported(ImportPackage importPackage) {
+ String pkg = importPackage.packageName;
+ if (pkg.equals("")) {
+ // cannot import a type from the "unnamed" package
+ return false;
+ }
+ if (pkg.equals("java.lang")) {
+ // we must import from 'java.lang' if we also have a class in the same package
+ return importPackage.collision;
+ }
+ if (pkg.equals(BodySourceWriter.this.packageName)) {
+ // we never need to import a class from the same package
+ return false;
+ }
+ return true;
+ }
+ }
+
+ /**
+ * We need a 'collision' flag for when we encounter a class from
+ * 'java.lang' followed by a class from the current compilation unit's
+ * package. We will need to include the explicit import of the
+ * 'java.lang' class and all the references to the other class will
+ * have to be fully-qualified.
+ *
+ * If the classes are encountered in the opposite order (i.e. the class
+ * from the current compilation unit's package followed by the class
+ * from 'java.lang'), we do *not* need to import the first class while
+ * all the references to the 'java.lang' class will be fully-qualified.
+ *
+ * Unfortunately, we still have a problem: if we reference a class from
+ * 'java.lang' and there is a conflicting class from the current
+ * compilation unit's package (but that class is *not* revealed to us
+ * here), the simple name will be resolved to the non-'java.lang' class.
+ * Unless we simply force an import of *all* 'java.lang' classes.... :-(
+ *
+ * This shouldn't happen very often. :-)
+ */
+ protected static class ImportPackage {
+ protected final String packageName;
+ protected boolean collision = false;
+
+ protected ImportPackage(String packageName) {
+ super();
+ this.packageName = packageName;
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/TextRange.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/TextRange.java
new file mode 100644
index 0000000000..419c98d0c6
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/TextRange.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility;
+
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+
+/**
+ * A text range defines the offset into, length of, and line of a piece
+ * of text.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ *
+ * @version 2.0
+ * @since 2.0
+ */
+public interface TextRange {
+
+ /**
+ * Returns the offset of the text.
+ *
+ * @return the offset of the text
+ */
+ int getOffset();
+
+ /**
+ * Return the length of the text.
+ */
+ int getLength();
+
+ /**
+ * Return whether the range includes the character at the specified index.
+ */
+ boolean includes(int index);
+
+ /**
+ * Return whether the range touches an insertion cursor at the
+ * specified index.
+ */
+ boolean touches(int index);
+
+ /**
+ * Return the line number of the text.
+ */
+ int getLineNumber();
+
+ /**
+ * Return true if the offsets and lengths are the same.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * Return a hash code that corresponds to the #equals() contract.
+ */
+ int hashCode();
+
+
+ /**
+ * Empty implementation of text range.
+ */
+ final class Empty implements TextRange {
+ public static final TextRange INSTANCE = new Empty();
+ public static TextRange instance() {
+ return INSTANCE;
+ }
+ // ensure single instance
+ private Empty() {
+ super();
+ }
+ public int getLineNumber() {
+ return IMessage.LINENO_UNSET;
+ }
+ public int getOffset() {
+ return IMessage.OFFSET_UNSET;
+ }
+ public int getLength() {
+ return IMessage.OFFSET_UNSET;
+ }
+ public boolean includes(int index) {
+ return false;
+ }
+ public boolean touches(int index) {
+ return index == 0; // ???
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if ( ! (o instanceof TextRange)) {
+ return false;
+ }
+ TextRange r = (TextRange) o;
+ return (r.getOffset() == 0)
+ && (r.getLength() == 0);
+ }
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+ @Override
+ public String toString() {
+ return "TextRange.Empty"; //$NON-NLS-1$
+ }
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AbstractType.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AbstractType.java
new file mode 100644
index 0000000000..8be7a07d97
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AbstractType.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+
+/**
+ * AbstractType: just some covariant overrides.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface AbstractType extends Member {
+
+ /**
+ * Covariant override.
+ */
+ ITypeBinding getBinding(CompilationUnit astRoot);
+
+ /**
+ * Covariant override.
+ */
+ AbstractTypeDeclaration getBodyDeclaration(CompilationUnit astRoot);
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotatedElement.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotatedElement.java
new file mode 100644
index 0000000000..8ce99cf49c
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotatedElement.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jpt.common.core.utility.TextRange;
+
+/**
+ * Dali manipulates annotations on elements (packages, types, fields, and methods).
+ * This interface simplifies those manipulations.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface AnnotatedElement {
+
+ String getName();
+
+ /**
+ * Return the annotated element's body declaration from the specified AST.
+ * This can be null if the annotated element is no longer present in the AST
+ * because the source has been changed in another thread.
+ */
+ ASTNode getBodyDeclaration(CompilationUnit astRoot);
+
+ /**
+ * Return the annotated element's binding from the specified AST.
+ */
+ IBinding getBinding(CompilationUnit astRoot);
+
+ /**
+ * Return the annotated element's "modified" declaration from the specified AST.
+ */
+ ModifiedDeclaration getModifiedDeclaration(CompilationUnit astRoot);
+
+ /**
+ * Return the annotated element's "modified" declaration from a newly-generated AST.
+ */
+ ModifiedDeclaration getModifiedDeclaration();
+
+ /**
+ * Return the annotated element's name text range from the specified AST.
+ */
+ TextRange getNameTextRange(CompilationUnit astRoot);
+
+ /**
+ * Edit the annotated element's declaration using the specified editor.
+ */
+ void edit(Editor editor);
+
+
+ // ********** "editor" interface **********
+
+ /**
+ * This interface defines a callback that is invoked when the annotated element's
+ * compilation unit/AST is in a state to be manipulated.
+ */
+ public interface Editor {
+
+ /**
+ * Edit the specified declaration. Any changes made to the declaration
+ * will be captured and applied to the annotated element's compilation unit.
+ */
+ void edit(ModifiedDeclaration declaration);
+
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotatedPackage.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotatedPackage.java
new file mode 100644
index 0000000000..c0a3ccc098
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotatedPackage.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Red Hat, Inc.
+ * Distributed under license by Red Hat, Inc. All rights reserved.
+ * This program is made available under the terms of the
+ * Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributor:
+ * Red Hat, Inc. - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IPackageBinding;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+
+/**
+ * @author Dmitry Geraskov
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface AnnotatedPackage extends AnnotatedElement {
+
+ /**
+ * Covariant override.
+ */
+ IPackageBinding getBinding(CompilationUnit astRoot);
+
+ /**
+ * Covariant override.
+ */
+ PackageDeclaration getBodyDeclaration(CompilationUnit astRoot);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationAdapter.java
new file mode 100644
index 0000000000..b0b04c4938
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationAdapter.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+
+/**
+ * Adapt a Java annotation with a simple-to-use interface.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface AnnotationAdapter {
+
+ /**
+ * Given the specified compilation unit, return the value of the
+ * adapter's annotation.
+ * @see #getAnnotation()
+ */
+ Annotation getAnnotation(CompilationUnit astRoot);
+
+ /**
+ * Build a new marker annotation, replacing the original annotation if present.
+ */
+ void newMarkerAnnotation();
+
+ /**
+ * Build a new single member annotation, replacing the original annotation if present.
+ */
+ void newSingleMemberAnnotation();
+
+ /**
+ * Build a new normal annotation, replacing the original annotation if present.
+ */
+ void newNormalAnnotation();
+
+ /**
+ * Remove the annotation.
+ */
+ void removeAnnotation();
+
+ /**
+ * Return the AST node corresponding to the annotation.
+ * If the annotation is missing, return the annotation's parent node.
+ * @see #getAstNode()
+ */
+ ASTNode getAstNode(CompilationUnit astRoot);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationEditFormatter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationEditFormatter.java
new file mode 100644
index 0000000000..77b3ac0682
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationEditFormatter.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface AnnotationEditFormatter {
+
+ /**
+ * Review the specified edits and format the specified document as needed.
+ */
+ void format(IDocument doc, TextEdit editTree) throws MalformedTreeException, BadLocationException;
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationElementAdapter.java
new file mode 100644
index 0000000000..3fc6e95434
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/AnnotationElementAdapter.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.Expression;
+
+/**
+ * Adapt a Java annotation element with a simple-to-use interface.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface AnnotationElementAdapter<T> {
+
+ /**
+ * Return the value of the adapter's annotation element.
+ * Return null if the element is not present.
+ * If the compilation unit is available, #value(CompilationUnit)
+ * might be more performant.
+ * @see #getValue(org.eclipse.jdt.core.dom.CompilationUnit)
+ */
+ T getValue();
+
+ /**
+ * Given the specified compilation unit, return the value of the
+ * adapter's annotation element.
+ * Return null if the element is not present.
+ * @see #getValue()
+ */
+ T getValue(CompilationUnit astRoot);
+
+ /**
+ * Set the value of the adapter's annotation element.
+ * Setting the value of the element to null will cause
+ * the element to be removed from its annotation.
+ */
+ void setValue(T value);
+
+ /**
+ * Given the specified compilation unit, return the expression value of the
+ * adapter's annotation element.
+ * Return null if the element is not present.
+ * @see #getExpression()
+ */
+ Expression getExpression(CompilationUnit astRoot);
+
+ /**
+ * Return the AST node corresponding to the element.
+ * If the element is missing, return the annotation's node.
+ * @see #getAstNode()
+ */
+ ASTNode getAstNode(CompilationUnit astRoot);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Attribute.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Attribute.java
new file mode 100644
index 0000000000..cce19d5abc
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Attribute.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+
+/**
+ * Attributes are either represented by fields ('foo') or properties/method
+ * pairs ('getFoo()'/'setFoo()').
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface Attribute extends Member {
+
+ /**
+ * Return the attribute's name, as opposed to the member's name
+ * (e.g. "getFoo()" returns "foo").
+ */
+ String getAttributeName();
+
+ /**
+ * Return the type binding for the attribute's declared type,
+ * as opposed to its declaring type.
+ */
+ ITypeBinding getTypeBinding(CompilationUnit astRoot);
+
+ /**
+ * Return whether the attribute is a field.
+ */
+ boolean isField();
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/DeclarationAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/DeclarationAnnotationAdapter.java
new file mode 100644
index 0000000000..9f93a16ffd
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/DeclarationAnnotationAdapter.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.MarkerAnnotation;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+
+/**
+ * Provide clients with a pluggable way to manipulate an
+ * annotation modifying a "declaration".
+ *
+ * TODO specify how multiple annotations with the same name are to be handled
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface DeclarationAnnotationAdapter {
+
+ /**
+ * Given the specified declaration, return the annotation.
+ */
+ Annotation getAnnotation(ModifiedDeclaration declaration);
+
+ /**
+ * Given the specified declaration, modify it with
+ * a new marker annotation, replacing the original annotation if present.
+ * Return the new annotation.
+ */
+ MarkerAnnotation newMarkerAnnotation(ModifiedDeclaration declaration);
+
+ /**
+ * Given the specified declaration, modify it with
+ * a new single member annotation, replacing the original annotation if present.
+ * Return the new annotation.
+ */
+ SingleMemberAnnotation newSingleMemberAnnotation(ModifiedDeclaration declaration);
+
+ /**
+ * Given the specified declaration, modify it with
+ * a new normal annotation, replacing the original annotation if present.
+ * Return the new annotation.
+ */
+ NormalAnnotation newNormalAnnotation(ModifiedDeclaration declaration);
+
+ /**
+ * Remove the annotation from the specified declaration.
+ */
+ void removeAnnotation(ModifiedDeclaration declaration);
+
+ /**
+ * Given the specified declaration, return the AST node
+ * corresponding to the annotation.
+ * If the annotation is missing, return its parent node.
+ */
+ ASTNode getAstNode(ModifiedDeclaration declaration);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/DeclarationAnnotationElementAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/DeclarationAnnotationElementAdapter.java
new file mode 100644
index 0000000000..1d5e4ff250
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/DeclarationAnnotationElementAdapter.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
+
+/**
+ * Provide clients with a pluggable way to manipulate an
+ * annotation element modifying a "declaration".
+ * T is the type of the object to be passed to and returned by the adapter.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface DeclarationAnnotationElementAdapter<T> {
+
+ /**
+ * Reduce the number of NLS warnings.
+ */
+ String VALUE = "value"; //$NON-NLS-1$
+
+ /**
+ * Given the specified declaration, return the value of the
+ * annotation element. Return null or an empty array
+ * if the element is not present.
+ */
+ T getValue(ModifiedDeclaration declaration);
+
+ /**
+ * Given the specified declaration, set the value of the
+ * annotation element. Setting the value of the element
+ * to null will cause the element to be removed from its
+ * annotation.
+ */
+ void setValue(T value, ModifiedDeclaration declaration);
+
+ /**
+ * Given the specified declaration, return the element's value expression.
+ * Return null if the element is not present.
+ */
+ Expression getExpression(ModifiedDeclaration declaration);
+
+ /**
+ * Given the specified declaration, return the AST node
+ * corresponding to the element's value.
+ * If the element is missing, return the annotation's node.
+ */
+ ASTNode getAstNode(ModifiedDeclaration declaration);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Enum.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Enum.java
new file mode 100644
index 0000000000..da690b148b
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Enum.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
+import org.eclipse.jdt.core.dom.EnumDeclaration;
+
+/**
+ * Enum: some covariant overrides plus enumConstants
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface Enum extends AbstractType {
+
+ /**
+ * Covariant override.
+ */
+ EnumDeclaration getBodyDeclaration(CompilationUnit astRoot);
+
+ /**
+ * Return the enum's constants
+ */
+ EnumConstantDeclaration[] getEnumConstants(CompilationUnit astRoot);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/EnumConstant.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/EnumConstant.java
new file mode 100644
index 0000000000..88693d415a
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/EnumConstant.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+
+/**
+ * Enum constants are part of Enums
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface EnumConstant extends Member {
+
+ String getName();
+
+ /**
+ * Covariant override.
+ */
+ IVariableBinding getBinding(CompilationUnit astRoot);
+
+ /**
+ * Covariant override.
+ */
+ EnumConstantDeclaration getBodyDeclaration(CompilationUnit astRoot);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/ExpressionConverter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/ExpressionConverter.java
new file mode 100644
index 0000000000..c5d7ed10e2
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/ExpressionConverter.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.Expression;
+
+/**
+ * Define the protocol for converting an AST expression back and forth
+ * from an arbitrary type (e.g. StringLiteral <=> String).
+ * T is the type of the object to be converted to and from an expression.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface ExpressionConverter<T> {
+
+ /**
+ * Convert the specified object to an
+ * expression that is owned by the specified AST.
+ * The type of the object is determined by the
+ * contract specified by the client.
+ */
+ Expression convert(T object, AST ast);
+
+ /**
+ * Convert the specified expression to an object of some
+ * pre-determined type.
+ */
+ T convert(Expression expression);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/FieldAttribute.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/FieldAttribute.java
new file mode 100644
index 0000000000..4e014ac72b
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/FieldAttribute.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+
+/**
+ * Field attribute: just some covariant overrides.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface FieldAttribute extends Attribute {
+
+ /**
+ * Covariant override.
+ */
+ IVariableBinding getBinding(CompilationUnit astRoot);
+
+ /**
+ * Covariant override.
+ */
+ FieldDeclaration getBodyDeclaration(CompilationUnit astRoot);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/IndexedAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/IndexedAnnotationAdapter.java
new file mode 100644
index 0000000000..a55e9cbc77
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/IndexedAnnotationAdapter.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+
+/**
+ * Adapt an indexed Java annotation with a simple-to-use interface.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface IndexedAnnotationAdapter extends AnnotationAdapter {
+
+ /**
+ * Return the the index at which the annotation is situated.
+ */
+ int getIndex();
+
+ /**
+ * Move the annotation to the specified index, leaving its original
+ * position cleared out.
+ */
+ void moveAnnotation(int newIndex);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/IndexedDeclarationAnnotationAdapter.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/IndexedDeclarationAnnotationAdapter.java
new file mode 100644
index 0000000000..438f21e1e6
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/IndexedDeclarationAnnotationAdapter.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+
+/**
+ * Allow clients to manipulate an annotation within an array of annotations.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface IndexedDeclarationAnnotationAdapter extends DeclarationAnnotationAdapter {
+
+ /**
+ * Return the the index at which the annotation is situated.
+ */
+ int getIndex();
+
+ /**
+ * Move the annotation to the specified index, leaving its original
+ * position cleared out.
+ */
+ void moveAnnotation(int newIndex, ModifiedDeclaration declaration);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Member.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Member.java
new file mode 100644
index 0000000000..8b9f398ea0
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Member.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+
+/**
+ * Dali manipulates annotations on members (types, fields, and methods).
+ * This interface simplifies those manipulations.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface Member extends AnnotatedElement {
+
+ /**
+ * Return whether the member is persistable.
+ */
+ boolean isPersistable(CompilationUnit astRoot);
+
+ /**
+ * Return whether the member matches the specified member
+ * and occurrence.
+ */
+ boolean matches(String memberName, int occurrence);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/MethodAttribute.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/MethodAttribute.java
new file mode 100644
index 0000000000..752426ee54
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/MethodAttribute.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jpt.utility.MethodSignature;
+
+/**
+ * Method attribute: just some covariant overrides.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface MethodAttribute extends Attribute {
+
+ /**
+ * Covariant override.
+ */
+ IMethodBinding getBinding(CompilationUnit astRoot);
+
+ /**
+ * Covariant override.
+ */
+ MethodDeclaration getBodyDeclaration(CompilationUnit astRoot);
+
+ /**
+ * This method must be used instead of Member#matches(String, int).
+ */
+ boolean matches(MethodSignature signature, int occurrence);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/ModifiedDeclaration.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/ModifiedDeclaration.java
new file mode 100644
index 0000000000..331e5391a0
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/ModifiedDeclaration.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+
+/**
+ * Define a wrapper that provides a common protocol for all the various AST
+ * declarations that have modifiers (i.e. there are a number of AST node
+ * classes that implement the method #modifiers(), but they do not implement
+ * a common interface):
+ * BodyDeclaration
+ * SingleVariableDeclaration
+ * VariableDeclarationExpression
+ * VariableDeclarationStatement
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface ModifiedDeclaration {
+
+ /**
+ * Return the "declaration" AST node.
+ */
+ ASTNode getDeclaration();
+
+ /**
+ * Return the "declaration" AST.
+ */
+ AST getAst();
+
+ /**
+ * Return the *first* annotation with the specified name.
+ * Return null if the declaration has no such annotation.
+ */
+ Annotation getAnnotationNamed(String annotationName);
+
+ /**
+ * Remove the *first* annotation with the specified name from the declaration.
+ */
+ void removeAnnotationNamed(String annotationName);
+
+ /**
+ * Replace the specified old annotation with the specified new annotation.
+ * If there is no annotation with the specified name, simply add the new
+ * annotation to the declaration's modifiers.
+ */
+ void replaceAnnotationNamed(String oldAnnotationName, Annotation newAnnotation);
+
+ /**
+ * Add the specified import to the declaration's compilation unit.
+ * Return whether the appropriate import was added to or already present in
+ * the declaration's compilation unit (i.e. the specified class can be
+ * subsequently referenced using a "short" name).
+ * Also return true if an import was unnecessary (i.e. the specified class
+ * is part of the "default" package).
+ * This does not support adding a "wildcard" import (e.g. "java.util.*").
+ */
+ boolean addImport(String className);
+
+ /**
+ * Add the specified static import to the declaration's compilation unit.
+ * Return whether the appropriate import was added to or already present in
+ * the declaration's compilation unit (i.e. the specified constant can be
+ * subsequently referenced using a "short" name).
+ * Also return true if an import was unnecessary (i.e. the specified enum
+ * is part of the "default" package).
+ * This does not support adding a "wildcard" import (e.g. "java.lang.annotation.ElementType.*").
+ */
+ boolean addStaticImport(String enumConstantName);
+
+ /**
+ * Add the specified import to the declaration's compilation unit.
+ * Return whether the appropriate import was added to or already present in
+ * the declaration's compilation unit (i.e. the specified name can be
+ * subsequently referenced using a "short" name).
+ * Also return true if an import was unnecessary (i.e. the specified class
+ * or enum is part of the "default" package).
+ * This does not support adding a "wildcard" import (e.g. "java.util.*").
+ */
+ boolean addImport(String importName, boolean static_);
+
+ /**
+ * Return whether the specified annotation has the specified
+ * (fully-qualified) name within the declaration's context; i.e. attempt
+ * to resolve the annotation's name (using imports etc.) and return
+ * whether it matches the specified name.
+ */
+ boolean annotationIsNamed(Annotation annotation, String name);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Type.java b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Type.java
new file mode 100644
index 0000000000..5a3a6a5a98
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.core/src/org/eclipse/jpt/common/core/utility/jdt/Type.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.core.utility.jdt;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+
+/**
+ * Type: nestedTypes, nestedEnums, fields, and methods.
+ *
+ * Provisional API: This interface is part of an interim API that is still
+ * under development and expected to change significantly before reaching
+ * stability. It is available at this early stage to solicit feedback from
+ * pioneering adopters on the understanding that any code that uses this API
+ * will almost certainly be broken (repeatedly) as the API evolves.
+ *
+ * This interface is not intended to be implemented by clients.
+ */
+public interface Type extends AbstractType {
+
+ /**
+ * Covariant override.
+ */
+ TypeDeclaration getBodyDeclaration(CompilationUnit astRoot);
+
+ /**
+ * Return the type's nested types (does not include annotations or enums).
+ */
+ TypeDeclaration[] getTypes(CompilationUnit astRoot);
+
+ /**
+ * Return the type's nested enums.
+ */
+ EnumDeclaration[] getEnums(CompilationUnit astRoot);
+
+ /**
+ * Return the type's fields.
+ */
+ FieldDeclaration[] getFields(CompilationUnit astRoot);
+
+ /**
+ * Return the type's methods.
+ */
+ MethodDeclaration[] getMethods(CompilationUnit astRoot);
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.ui/.classpath b/common/plugins/org.eclipse.jpt.common.ui/.classpath
new file mode 100644
index 0000000000..bd4371771c
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/.classpath
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+ <accessrules>
+ <accessrule kind="accessible" pattern="org/eclipse/wst/**"/>
+ <accessrule kind="accessible" pattern="org/eclipse/jst/**"/>
+ </accessrules>
+ </classpathentry>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="property_files"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/common/plugins/org.eclipse.jpt.common.ui/.project b/common/plugins/org.eclipse.jpt.common.ui/.project
new file mode 100644
index 0000000000..7fde966914
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.jpt.common.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/common/plugins/org.eclipse.jpt.common.ui/.settings/org.eclipse.jdt.core.prefs b/common/plugins/org.eclipse.jpt.common.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..6e2f42326d
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Mon Jan 24 09:48:38 EST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/common/plugins/org.eclipse.jpt.common.ui/META-INF/MANIFEST.MF b/common/plugins/org.eclipse.jpt.common.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..1dcfdd5939
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,36 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-SymbolicName: org.eclipse.jpt.common.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.jpt.common.ui.JptCommonUiPlugin
+Bundle-ActivationPolicy: lazy
+Bundle-ClassPath: .
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Require-Bundle: org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.draw2d;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.jdt.core;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.jdt.ui;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.jface;bundle-version="[3.7.0,4.0.0)",
+ org.eclipse.jface.text;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.jpt.common.core;bundle-version="[1.0.0,2.0.0)",
+ org.eclipse.jpt.utility;bundle-version="[1.2.0,2.0.0)",
+ org.eclipse.jst.common.project.facet.core;bundle-version="[1.3.100,2.0.0)",
+ org.eclipse.jst.common.project.facet.ui;bundle-version="[1.3.100,2.0.0)",
+ org.eclipse.ui.navigator;bundle-version="[3.3.100,4.0.0)",
+ org.eclipse.ui.views.properties.tabbed;bundle-version="[3.4.0,4.0.0)",
+ org.eclipse.wst.common.project.facet.ui;bundle-version="[1.3.0,2.0.0)"
+Export-Package: org.eclipse.jpt.common.ui,
+ org.eclipse.jpt.common.ui.internal;x-friends:="org.eclipse.jpt.jaxb.ui,org.eclipse.jpt.ui",
+ org.eclipse.jpt.common.ui.internal.jface;x-friends:="org.eclipse.jpt.jaxb.ui,org.eclipse.jpt.ui",
+ org.eclipse.jpt.common.ui.internal.listeners;x-friends:="org.eclipse.jpt.jaxb.ui,org.eclipse.jpt.ui",
+ org.eclipse.jpt.common.ui.internal.properties,
+ org.eclipse.jpt.common.ui.internal.swt;x-friends:="org.eclipse.jpt.jaxb.ui,org.eclipse.jpt.ui",
+ org.eclipse.jpt.common.ui.internal.util;x-friends:="org.eclipse.jpt.jaxb.ui,org.eclipse.jpt.ui",
+ org.eclipse.jpt.common.ui.internal.utility;x-friends:="org.eclipse.jpt.jaxb.ui,org.eclipse.jpt.ui",
+ org.eclipse.jpt.common.ui.internal.utility.swt;x-friends:="org.eclipse.jpt.jaxb.ui,org.eclipse.jpt.ui",
+ org.eclipse.jpt.common.ui.internal.widgets;x-friends:="org.eclipse.jpt.jaxb.ui,org.eclipse.jpt.ui",
+ org.eclipse.jpt.common.ui.jface
+Import-Package: com.ibm.icu.text;version="4.0.1"
diff --git a/common/plugins/org.eclipse.jpt.common.ui/about.html b/common/plugins/org.eclipse.jpt.common.ui/about.html
new file mode 100644
index 0000000000..be534ba44f
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/about.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+
+<BODY lang="EN-US">
+
+<H3>About This Content</H3>
+
+<P>May 02, 2008</P>
+
+<H3>License</H3>
+
+<P>The Eclipse Foundation makes available all content in this plug-in
+("Content"). Unless otherwise indicated below, the Content is provided to you
+under the terms and conditions of the Eclipse Public License Version 1.0
+("EPL"). A copy of the EPL is available at
+<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>.
+For purposes of the EPL, "Program" will mean the Content.</P>
+
+<P>If you did not receive this Content directly from the Eclipse Foundation, the
+Content is being redistributed by another party ("Redistributor") and different
+terms and conditions may apply to your use of any object code in the Content.
+Check the Redistributor's license that was provided with the Content. If no such
+license exists, contact the Redistributor. Unless otherwise indicated below, the
+terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at
+<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
+
+</BODY>
+</HTML>
diff --git a/common/plugins/org.eclipse.jpt.common.ui/build.properties b/common/plugins/org.eclipse.jpt.common.ui/build.properties
new file mode 100644
index 0000000000..87792f2ef5
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/build.properties
@@ -0,0 +1,19 @@
+################################################################################
+# Copyright (c) 2011 Oracle. All rights reserved.
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v1.0, which accompanies this distribution
+# and is available at http://www.eclipse.org/legal/epl-v10.html.
+#
+# Contributors:
+# Oracle - initial API and implementation
+################################################################################
+javacSource = 1.5
+javacTarget = 1.5
+source.. = src/,\
+ property_files/
+output.. = bin/
+bin.includes = .,\
+ META-INF/,\
+ about.html,\
+ plugin.properties
+jars.compile.order = .
diff --git a/common/plugins/org.eclipse.jpt.common.ui/plugin.properties b/common/plugins/org.eclipse.jpt.common.ui/plugin.properties
new file mode 100644
index 0000000000..4caf90e773
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/plugin.properties
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2011 Oracle. All rights reserved.
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v1.0, which accompanies this distribution
+# and is available at http://www.eclipse.org/legal/epl-v10.html.
+#
+# Contributors:
+# Oracle - initial API and implementation
+###############################################################################
+
+# ====================================================================
+# To code developer:
+# Do NOT change the properties between this line and the
+# "%%% END OF TRANSLATED PROPERTIES %%%" line.
+# Make a new property name, append to the end of the file and change
+# the code to use the new property.
+# ====================================================================
+
+# ====================================================================
+# %%% END OF TRANSLATED PROPERTIES %%%
+# ====================================================================
+pluginName= Dali Java Persistence Tools - Common UI
+providerName=Eclipse Web Tools Platform
diff --git a/common/plugins/org.eclipse.jpt.common.ui/property_files/jpt_common_ui.properties b/common/plugins/org.eclipse.jpt.common.ui/property_files/jpt_common_ui.properties
new file mode 100644
index 0000000000..aee4769cae
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/property_files/jpt_common_ui.properties
@@ -0,0 +1,28 @@
+################################################################################
+# Copyright (c) 2011 Oracle. All rights reserved.
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v1.0, which accompanies this distribution
+# and is available at http://www.eclipse.org/legal/epl-v10.html.
+#
+# Contributors:
+# Oracle - initial API and implementation
+################################################################################
+
+Boolean_True=True
+Boolean_False=False
+
+NoneSelected=<None>
+DefaultEmpty=Default
+DefaultWithOneParam=Default ({0})
+
+AddRemovePane_AddButtonText=Add...
+AddRemovePane_RemoveButtonText=Remove
+ChooserPane_browseButton=Browse...
+ClassChooserPane_dialogMessage=&Enter type name prefix or pattern (*, ?, or camel case):
+ClassChooserPane_dialogTitle=Class Selection
+PackageChooserPane_dialogTitle=Package Selection
+PackageChooserPane_dialogMessage=&Enter package name prefix or pattern (* = any string, ? = any character):
+EnumComboViewer_default=Default ()
+EnumComboViewer_defaultWithDefault=Default ({0})
+NewNameStateObject_nameMustBeSpecified=A name must be specified.
+NewNameStateObject_nameAlreadyExists=A query with this name already exists.
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/JptCommonUiPlugin.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/JptCommonUiPlugin.java
new file mode 100644
index 0000000000..c249775143
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/JptCommonUiPlugin.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.ui;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+public class JptCommonUiPlugin
+ extends AbstractUIPlugin
+{
+
+ // ********** constants **********
+
+ /**
+ * The plug-in identifier of JPT Common UI support (value {@value}).
+ */
+ public static final String PLUGIN_ID = "org.eclipse.jpt.common.ui"; //$NON-NLS-1$
+ public static final String PLUGIN_ID_ = PLUGIN_ID + '.';
+
+ // ********** singleton **********
+
+ private static JptCommonUiPlugin INSTANCE;
+
+ /**
+ * Returns the singleton JPT UI plug-in.
+ */
+ public static JptCommonUiPlugin instance() {
+ return INSTANCE;
+ }
+
+
+ // ********** logging **********
+
+ public static void log(IStatus status) {
+ INSTANCE.getLog().log(status);
+ }
+
+ public static void log(String msg) {
+ log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, msg, null));
+ }
+
+ public static void log(Throwable throwable) {
+ log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, throwable.getLocalizedMessage(), throwable));
+ }
+
+
+ // ********** construction **********
+
+ public JptCommonUiPlugin() {
+ super();
+ if (INSTANCE != null) {
+ throw new IllegalStateException();
+ }
+ INSTANCE = this;
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/WidgetFactory.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/WidgetFactory.java
new file mode 100644
index 0000000000..4a7154aeee
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/WidgetFactory.java
@@ -0,0 +1,240 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.ui;
+
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DateTime;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Spinner;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.FormText;
+import org.eclipse.ui.forms.widgets.Hyperlink;
+import org.eclipse.ui.forms.widgets.Section;
+
+/**
+ * A widget factory is responsible for creating an SWT widget based on the right
+ * style. Some style shows the widgets differently, for instance, the flat style
+ * shows the widgets with less borders.
+ * <p>
+ * Provisional API: This interface is part of an interim API that is still under
+ * development and expected to change significantly before reaching stability.
+ * It is available at this early stage to solicit feedback from pioneering
+ * adopters on the understanding that any code that uses this API will almost
+ * certainly be broken (repeatedly) as the API evolves.
+ *
+ * @version 2.0
+ * @since 2.0
+ */
+public interface WidgetFactory {
+
+ /**
+ * Creates a new regular button.
+ *
+ * @param parent The parent container
+ * @param text The button's text
+ * @return A new <code>Button</code>
+ */
+ Button createButton(Composite parent, String text);
+
+ /**
+ * Creates a new non-editable custom <code>Combo</code>.
+ *
+ * @deprecated
+ * @param parent The parent container
+ * @return A new <code>CCombo</code>
+ */
+ @Deprecated
+ CCombo createCCombo(Composite parent);
+
+ /**
+ * Creates a new check box button.
+ *
+ * @param parent The parent container
+ * @param text The button's text
+ * @return A new <code>Button</code>
+ */
+ Button createCheckBox(Composite parent, String text);
+
+ /**
+ * Creates a new non-editable <code>Combo</code>.
+ *
+ * @param parent The parent container
+ * @return A new <code>Combo</code>
+ */
+ Combo createCombo(Composite parent);
+
+ /**
+ * Creates a new container.
+ *
+ * @param parent The parent container
+ * @return A new <code>Composite</code>
+ */
+ Composite createComposite(Composite parent);
+
+ /**
+ * Creates a new DateTime.
+ *
+ * @param container The parent container
+ * @param style The style is to tell the type of widget
+ * (<code>SWT.DATE</code> or <code>SWT.TIME</code> or <code>SWT.CALENDAR</code>)
+ * @return A new <code>DateTime</code>
+ */
+ DateTime createDateTime(Composite parent, int style);
+
+ /**
+ * Creates a new editable custom <code>CCombo</code>.
+ *
+ * @deprecated
+ * @param parent The parent container
+ * @return A new <code>CCombo</code>
+ */
+ @Deprecated
+ CCombo createEditableCCombo(Composite parent);
+
+ /**
+ * Creates a new editable <code>Combo</code>.
+ *
+ * @param parent The parent container
+ * @return A new <code>Combo</code>
+ */
+ Combo createEditableCombo(Composite parent);
+
+ /**
+ * Creates a new titled pane (group box).
+ *
+ * @param parent The parent container
+ * @param title The group pane's title
+ * @return A new <code>Group</code>
+ */
+ Group createGroup(Composite parent, String title);
+
+ /**
+ * Creates a new label that is shown as a hyperlink.
+ *
+ * @param parent The parent container
+ * @param text The label's text
+ * @return A new <code>Hyperlink</code>
+ */
+ Hyperlink createHyperlink(Composite parent, String text);
+
+ /**
+ * Creates a new label.
+ *
+ * @param container The parent container
+ * @param labelText The label's text
+ * @return A new <code>Label</code>
+ */
+ Label createLabel(Composite container, String labelText);
+
+ /**
+ * Creates a new list.
+ *
+ * @param container The parent container
+ * @param style The style is usually to tell what type of selection
+ * (<code>SWT.MULTI</code> or <code>SWT.SINGLE</code>)
+ * @return A new <code>Label</code>
+ */
+ List createList(Composite container, int style);
+
+ /**
+ * Creates a new label that can be wrapped on multiple lines.
+ *
+ * @param container The parent container
+ * @param labelText The label's text
+ * @return A new <code>FormText</code>
+ */
+ FormText createMultiLineLabel(Composite container, String labelText);
+
+ /**
+ * Creates a new editable text area.
+ *
+ * @param parent The parent container
+ * @param parent The number of lines the text area should display
+ * @return A new <code>Text</code>
+ */
+ Text createMultiLineText(Composite parent);
+
+ /**
+ * Creates a new editable text field that handles password.
+ *
+ * @param container The parent container
+ * @return A new <code>Text</code>
+ */
+ Text createPasswordText(Composite container);
+
+ /**
+ * Creates a new push button (toggle between selected and unselected).
+ *
+ * @param parent The parent container
+ * @param text The button's text
+ * @return A new <code>Button</code>
+ */
+ Button createPushButton(Composite parent, String text);
+
+ /**
+ * Creates a new radio button.
+ *
+ * @param parent The parent container
+ * @param text The button's text
+ * @return A new <code>Button</code>
+ */
+ Button createRadioButton(Composite parent, String text);
+
+ /**
+ * Creates a new section, which is a collapsable pane with a title bar.
+ *
+ * @param parent The parent container
+ * @param style The style of the title bar, which can be
+ * <code>ExpandableComposite.TWISTIE</code> and
+ * <code>ExpandableComposite.TITLE_BAR</code>
+ * @return A new <code>Section</code>
+ */
+ Section createSection(Composite parent, int style);
+
+ /**
+ * Creates a new spinner.
+ *
+ * @param parent The parent container
+ * @return A new <code>Spinner</code>
+ */
+ Spinner createSpinner(Composite parent);
+
+ /**
+ * Creates a new table.
+ *
+ * @param container The parent container
+ * @param style The style to apply to the table
+ * @return A new <code>Table</code>
+ */
+ Table createTable(Composite parent, int style);
+
+ /**
+ * Creates a new editable text field.
+ *
+ * @param container The parent container
+ * @return A new <code>Text</code>
+ */
+ Text createText(Composite parent);
+
+ /**
+ * Creates a new tri-state check box.
+ *
+ * @param parent The parent container
+ * @param text The button's text
+ * @return A new <code>Button</code> that has 3 selection states
+ */
+ Button createTriStateCheckBox(Composite parent, String text);
+} \ No newline at end of file
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/JptCommonUiMessages.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/JptCommonUiMessages.java
new file mode 100644
index 0000000000..31a1080af3
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/JptCommonUiMessages.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.ui.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Localized messages used by Dali UI.
+ *
+ * @version 3.0
+ * @since 1.0
+ */
+public class JptCommonUiMessages {
+
+
+ public static String Boolean_True;
+ public static String Boolean_False;
+
+ public static String DefaultEmpty;
+ public static String DefaultWithOneParam;
+ public static String NoneSelected;
+
+ public static String AddRemovePane_AddButtonText;
+ public static String AddRemovePane_RemoveButtonText;
+
+ public static String ChooserPane_browseButton;
+ public static String ClassChooserPane_dialogMessage;
+ public static String ClassChooserPane_dialogTitle;
+ public static String PackageChooserPane_dialogMessage;
+ public static String PackageChooserPane_dialogTitle;
+ public static String EnumComboViewer_default;
+ public static String EnumComboViewer_defaultWithDefault;
+ public static String NewNameStateObject_nameAlreadyExists;
+ public static String NewNameStateObject_nameMustBeSpecified;
+
+ private static final String BUNDLE_NAME = "jpt_common_ui"; //$NON-NLS-1$
+ private static final Class<?> BUNDLE_CLASS = JptCommonUiMessages.class;
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS);
+ }
+
+ private JptCommonUiMessages() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/Tracing.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/Tracing.java
new file mode 100644
index 0000000000..7826015d18
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/Tracing.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.ui.internal;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jpt.common.ui.JptCommonUiPlugin;
+
+/**
+ * This tracing class manages to convert the string value into boolean values or
+ * integer values that are associated with the tracing debug flags. Those flags
+ * are specified in the .options file. The supported keys are defined here as
+ * constants for quick reference.
+ *
+ * @version 2.0
+ * @since 2.0
+ */
+@SuppressWarnings("nls")
+public final class Tracing
+{
+ /**
+ * A constant used to retrieve the value associated with "/debug".
+ */
+ public static final String DEBUG = "/debug";
+
+ /**
+ * A constant used to retrieve the value associated with "/debug/ui/db".
+ */
+ public static final String UI_DB = "/debug/ui/db";
+
+ /**
+ * A constant used to retrieve the value associated with "/debug/ui/detailsView".
+ */
+ public static final String UI_DETAILS_VIEW = "/debug/ui/detailsView";
+
+ /**
+ * A constant used to retrieve the value associated with "/debug/ui/layout".
+ */
+ public static final String UI_LAYOUT = "/debug/ui/layout";
+
+ /**
+ * A constant used to retrieve the value associated with "/unit-tests".
+ */
+ public static final String UNIT_TESTS = "/unit-tests";
+
+ /**
+ * Can't instantiate this <code>Tracing</code> class.
+ */
+ private Tracing()
+ {
+ super();
+ throw new UnsupportedOperationException("Tracing cannot be instantiated");
+ }
+
+ /**
+ * Retrieves the debug value associated with the given flag. The default
+ * value is <code>false</code>.
+ *
+ * @param flag The flag to retrieve the debug value, which should be
+ * contained in the .options file, the flag should start with "/"
+ * @return <code>true</code> if the given flag is active; <code>false</code>
+ * otherwise
+ */
+ public static boolean booleanDebugOption(String flag)
+ {
+ return booleanDebugOption(flag, false);
+ }
+
+ /**
+ * Retrieves the debug value associated with the given flag.
+ *
+ * @param flag The flag to retrieve the debug value, which should be
+ * contained in the .options file, the flag should start with "/"
+ * @param defaultValue The default value if the value associated with the
+ * given flag could not be found
+ * @return <code>true</code> if the given flag is active; <code>false</code>
+ * otherwise
+ */
+ public static boolean booleanDebugOption(String flag, boolean defaultValue)
+ {
+ String string = Platform.getDebugOption(JptCommonUiPlugin.PLUGIN_ID + flag);
+ return (string == null) ? defaultValue : Boolean.parseBoolean(string.trim());
+ }
+
+ /**
+ * Retrieves the debug value associated with the given flag. The default value
+ * is 0.
+ *
+ * @param flag The flag to retrieve the debug value, which should be
+ * contained in the .options file, the flag should start with "/"
+ * @return The value associated with the given flag, or the given default
+ * value
+ */
+ public static int intDebugOption(String flag)
+ {
+ return intDebugOption(flag, 0);
+ }
+
+ /**
+ * Retrieves the debug value associated with the given flag.
+ *
+ * @param flag The flag to retrieve the debug value, which should be
+ * contained in the .options file, the flag should start with "/"
+ * @param defaultValue The default value if the value associated with the
+ * given flag could not be found
+ * @return The value associated with the given flag, or the given default
+ * value
+ */
+ public static int intDebugOption(String flag, int defaultValue)
+ {
+ String string = Platform.getDebugOption(JptCommonUiPlugin.PLUGIN_ID + flag);
+ return (string == null) ? defaultValue : Integer.parseInt(string);
+ }
+
+ /**
+ * Logs the given messages, appends it with this plug-in id.
+ *
+ * @param message The message to be logged
+ */
+ public static void log(String message)
+ {
+ System.out.print("[" + JptCommonUiPlugin.PLUGIN_ID + "] ");
+ System.out.println(message);
+ }
+
+ /**
+ * Retrieves the debug value associated with the given flag. The default value
+ * is an empty string.
+ *
+ * @param flag The flag to retrieve the debug value, which should be
+ * contained in the .options file, the flag should start with "/"
+ * @return The value associated with the given flag, or the given default
+ * value
+ */
+ public static String stringDebugOption(String flag)
+ {
+ return stringDebugOption(flag, "");
+ }
+
+ /**
+ * Retrieves the debug value associated with the given flag.
+ *
+ * @param flag The flag to retrieve the debug value, which should be
+ * contained in the .options file, the flag should start with "/"
+ * @param defaultValue The default value if the value associated with the
+ * given flag could not be found
+ * @return The value associated with the given flag, or the given default
+ * value
+ */
+ public static String stringDebugOption(String flag, String defaultValue)
+ {
+ String string = Platform.getDebugOption(JptCommonUiPlugin.PLUGIN_ID + flag);
+ return (string != null) ? string : defaultValue;
+ }
+}
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/AbstractItemLabelProvider.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/AbstractItemLabelProvider.java
new file mode 100644
index 0000000000..abcaa7bc48
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/jface/AbstractItemLabelProvider.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Contributors:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.ui.internal.jface;
+
+import org.eclipse.jpt.common.ui.jface.DelegatingContentAndLabelProvider;
+import org.eclipse.jpt.common.ui.jface.ItemLabelProvider;
+import org.eclipse.jpt.utility.model.Model;
+import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
+import org.eclipse.jpt.utility.model.listener.PropertyChangeListener;
+import org.eclipse.jpt.utility.model.value.PropertyValueModel;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Implementation of {@link ItemLabelProvider} that provides updating
+ * label information for a Model object.
+ *
+ * The typical subclass will override the following methods:
+ * #buildImageModel()
+ * return a {@link PropertyValueModel} that represents the image for the
+ * represented model object
+ * #buildTextModel()
+ * return a {@link PropertyValueModel} that represents the text for the
+ * represented model object.
+ * #buildDescriptionModel()
+ * return a {@link PropertyValueModel} that represents the description for
+ * the represented model object
+ *
+ * Other methods may be overridden, but take care to preserve the logic provided
+ * by this class.
+ */
+public abstract class AbstractItemLabelProvider implements ItemLabelProvider
+{
+ private DelegatingContentAndLabelProvider labelProvider;
+
+ private Model model;
+
+ private PropertyValueModel<Image> imageModel;
+
+ private PropertyValueModel<String> textModel;
+
+ private PropertyValueModel<String> descriptionModel;
+
+ private PropertyChangeListener labelChangeListener;
+
+
+ protected AbstractItemLabelProvider(
+ Model model, DelegatingContentAndLabelProvider labelProvider) {
+ this.model = model;
+ this.labelProvider = labelProvider;
+ this.labelChangeListener = buildLabelChangeListener();
+ }
+
+
+ /**
+ * Construct a listener to update the viewer (through the label provider)
+ * if the text or image changes
+ */
+ protected PropertyChangeListener buildLabelChangeListener() {
+ return new PropertyChangeListener() {
+ public void propertyChanged(PropertyChangeEvent event) {
+ labelProvider().updateLabel(model());
+ }
+ };
+ }
+
+ /**
+ * Return the image value model
+ * (lazy and just-in-time initialized)
+ */
+ protected synchronized PropertyValueModel<Image> imageModel() {
+ if (this.imageModel == null) {
+ this.imageModel = buildImageModel();
+ engageImageModel();
+ }
+ return this.imageModel;
+ }
+
+ /**
+ * Construct an image model
+ */
+ protected abstract PropertyValueModel<Image> buildImageModel();
+
+ /**
+ * Should only be overridden with a call to super.engageImageModel() before
+ * subclass logic
+ */
+ protected void engageImageModel() {
+ this.imageModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.labelChangeListener);
+ }
+
+ /**
+ * Should only be overridden with a call to super.disengageImageModel() after
+ * subclass logic
+ */
+ protected void disengageImageModel() {
+ this.imageModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.labelChangeListener);
+ }
+
+ /**
+ * Return the text value model
+ * (lazy and just-in-time initialized)
+ */
+ protected synchronized PropertyValueModel<String> textModel() {
+ if (this.textModel == null) {
+ this.textModel = buildTextModel();
+ engageTextModel();
+ }
+ return this.textModel;
+ }
+
+ /**
+ * Construct a text value model
+ */
+ protected abstract PropertyValueModel<String> buildTextModel();
+
+ /**
+ * Should only be overridden with a call to super.engageTextModel() before
+ * subclass logic
+ */
+ protected void engageTextModel() {
+ this.textModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.labelChangeListener);
+ }
+
+ /**
+ * Should only be overridden with a call to super.disengageTextModel() after
+ * subclass logic
+ */
+ protected void disengageTextModel() {
+ this.textModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.labelChangeListener);
+ }
+
+ /**
+ * Return the description value model
+ * (lazy and just-in-time initialized)
+ */
+ protected synchronized PropertyValueModel<String> descriptionModel() {
+ if (this.descriptionModel == null) {
+ this.descriptionModel = buildDescriptionModel();
+ engageDescriptionModel();
+ }
+ return this.descriptionModel;
+ }
+
+ /**
+ * Construct a description value model
+ */
+ protected abstract PropertyValueModel<String> buildDescriptionModel();
+
+ /**
+ * Should only be overridden with a call to super.engageDescriptionModel() before
+ * subclass logic
+ */
+ protected void engageDescriptionModel() {
+ this.descriptionModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.labelChangeListener);
+ }
+
+ /**
+ * Should only be overridden with a call to super.disengageDescriptionModel() after
+ * subclass logic
+ */
+ protected void disengageDescriptionModel() {
+ this.descriptionModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.labelChangeListener);
+ }
+
+ /**
+ * Return the model object represented by this item
+ */
+ public Model model() {
+ return this.model;
+ }
+
+ /**
+ * Return the label provider that delegates to this item
+ */
+ public DelegatingContentAndLabelProvider labelProvider() {
+ return this.labelProvider;
+ }
+
+ public Image getImage() {
+ return imageModel().getValue();
+ }
+
+ public String getText() {
+ return textModel().getValue();
+ }
+
+ public String getDescription() {
+ return descriptionModel().getValue();
+ }
+
+ public void dispose() {
+ disposeTextModel();
+ disposeImageModel();
+ disposeDescriptionModel();
+ }
+
+ protected synchronized void disposeTextModel() {
+ if (this.textModel != null) {
+ disengageTextModel();
+ this.textModel = null;
+ }
+ }
+
+ protected synchronized void disposeImageModel() {
+ if (this.imageModel != null) {
+ disengageImageModel();
+ this.imageModel = null;
+ }
+ }<