Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.wst.xml.core/.classpath7
-rw-r--r--bundles/org.eclipse.wst.xml.core/.compatibility2
-rw-r--r--bundles/org.eclipse.wst.xml.core/.cvsignore7
-rw-r--r--bundles/org.eclipse.wst.xml.core/.options2
-rw-r--r--bundles/org.eclipse.wst.xml.core/build.properties24
-rw-r--r--bundles/org.eclipse.wst.xml.core/plugin.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.core/plugin.xml116
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/.cvsignore1
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/Logger.java153
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/NameValidator.java29
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/XMLModelPlugin.java118
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/XMLPreferenceNames.java51
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/builder/delegates/XMLTaskTagSeeker.java41
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/builder/participants/XMLTaskTagParticipant.java25
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/CleanupProcessorXML.java90
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/ElementNodeCleanupHandler.java556
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/NodeCleanupHandler.java70
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/XMLCleanupPreferences.java54
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/XMLCleanupPreferencesImpl.java150
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/CommentElementAdapter.java123
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/CommentElementHandler.java107
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/BasicCommentElementHandler.java153
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/CommentElementConfiguration.java226
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/CommentElementRegistry.java84
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/util/CommentElementFactory.java65
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/util/TagScanner.java196
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/ContentDescriberForXML.java25
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLHeadTokenizer.java1226
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLHeadTokenizerConstants.java23
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLResourceEncodingDetector.java102
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/DocumentLoaderForXML.java131
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/DocumentTypeAdapter.java51
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/InvalidCharacterException.java63
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/JSPTag.java34
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/TagAdapter.java34
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLAttr.java65
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLCharEntity.java37
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLDocument.java66
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLDocumentType.java32
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLElement.java107
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLGenerator.java154
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLModel.java36
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLModelNotifier.java103
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLNamespace.java25
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLNode.java124
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLText.java40
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/encoding/XMLDocumentCharsetDetector.java37
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/encoding/XMLDocumentLoader.java78
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/CommentNodeFormatter.java99
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/DocumentNodeFormatter.java53
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/ElementNodeFormatter.java357
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/FormatProcessorXML.java116
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/IStructuredFormatPreferencesXML.java21
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/NodeFormatter.java775
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/StructuredFormatPreferencesXML.java27
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/TextNodeFormatter.java198
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/DebugAdapterFactory.java81
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/EveryNodeDebugAdapter.java274
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/IDebugAdapter.java19
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ByteReader.java107
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/EncodingParserConstants.java30
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/HeadParserToken.java44
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/IntStack.java99
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLDeclDetector.java156
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizer.java1222
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizerConstants.java22
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/AttrImpl.java756
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CDATASectionImpl.java140
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CMNodeUtil.java42
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterDataImpl.java353
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CommentImpl.java183
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentFragmentImpl.java74
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentImpl.java1073
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapterImpl.java120
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeImpl.java222
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ElementImpl.java1421
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityImpl.java227
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityReferenceImpl.java89
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ModelParserAdapter.java55
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeContainer.java514
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeImpl.java809
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeIteratorImpl.java257
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeListImpl.java111
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NotationImpl.java138
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ProcessingInstructionImpl.java227
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/RangeImpl.java630
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ReadOnlyController.java334
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/SourceValidator.java351
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionChecker.java143
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionContainer.java605
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionManagementException.java29
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionProxy.java548
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionUtil.java167
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TextImpl.java1107
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLGeneratorImpl.java738
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelContext.java237
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelImpl.java875
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifierImpl.java469
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java2365
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelUpdater.java1647
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/filebuffers/DocumentFactoryForXML.java39
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/filebuffers/SetupParticipantForXML.java40
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/BlockStructuredDocumentRegion.java46
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/ContextRegionContainer.java386
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/IntStack.java97
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/RegionFactory.java49
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XML10Names.java541
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLRegionContexts.java21
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLSourceParser.java595
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredDocumentReParser.java125
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredRegionFactory.java42
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLTokenizer.java1699
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeEqualsRegion.java92
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeNameRegion.java170
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeValueRegion.java167
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/BlockTextRegion.java36
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/GenericTemplateRegion.java105
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionToStringUtil.java36
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionUpdateRule.java205
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagCloseRegion.java95
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagNameRegion.java98
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java98
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/WhiteSpaceOnlyRegion.java190
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLCDataTextRegion.java179
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLContentRegion.java179
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserFactory.java25
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserRegion.java111
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java86
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterFactoryImpl.java113
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterImpl.java168
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/XMLStructuredDocumentRegion.java36
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/util/DebugDocument.java104
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/AbstractPropagatingValidator.java45
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/Propagator.java51
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/ValidationComponent.java50
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/jsp/model/parser/temp/XMLJSPRegionContexts.java59
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/jsp/model/parser/temp/package.html8
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/EmbeddedXML.java89
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/ModelHandlerForXML.java63
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/XMLModelLoader.java95
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryAdapterFactoryForEmbeddedXML.java55
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryAdapterFactoryForXML.java161
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryUtil.java64
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLCatalogIdResolver.java89
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLModelQueryAssociationProvider.java37
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLModelQueryImpl.java38
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/parser/XMLRegionContext.java69
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/text/rules/StructuredTextPartitionerForXML.java139
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/COPYRIGHT.html100
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/DocumentRange.java39
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/Range.java434
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/RangeException.java46
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/package.html3
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/COPYRIGHT.html100
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/DocumentTraversal.java101
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/NodeFilter.java151
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/NodeIterator.java113
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/TreeWalker.java185
-rw-r--r--bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/package.html3
-rw-r--r--bundles/org.eclipse.wst.xml.ui/.classpath8
-rw-r--r--bundles/org.eclipse.wst.xml.ui/.compatibility2
-rw-r--r--bundles/org.eclipse.wst.xml.ui/.cvsignore7
-rw-r--r--bundles/org.eclipse.wst.xml.ui/build.properties24
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse.gifbin0 -> 146 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse_all.gifbin0 -> 155 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainoff.gifbin0 -> 216 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainon.gifbin0 -> 210 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand.gifbin0 -> 153 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand_all.gifbin0 -> 164 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/new_xml.gifbin0 -> 239 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/rldgrmr.gifbin0 -> 245 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/validate.gifbin0 -> 334 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse.gifbin0 -> 146 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse_all.gifbin0 -> 157 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainoff.gifbin0 -> 348 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainon.gifbin0 -> 333 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand.gifbin0 -> 153 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand_all.gifbin0 -> 164 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/etool16/new_xml.gifbin0 -> 370 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/etool16/rldgrmr.gifbin0 -> 368 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/etool16/validate.gifbin0 -> 558 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/XSDFile.gifbin0 -> 574 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/add_correction.gifbin0 -> 318 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/att_req_obj.gifbin0 -> 221 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/attribute_obj.gifbin0 -> 167 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/cdatasection.gifbin0 -> 359 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/choice.gifbin0 -> 145 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/comment_obj.gifbin0 -> 196 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/correction_change.gifbin0 -> 197 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/doctype.gifbin0 -> 594 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/dtdfile.gifbin0 -> 351 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/element_obj.gifbin0 -> 351 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity.gifbin0 -> 124 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity_reference.gifbin0 -> 316 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/enum.gifbin0 -> 80 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/error-overlay.gifbin0 -> 82 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/localvariable_obj.gifbin0 -> 152 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/notation.gifbin0 -> 177 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/occurone_obj.gifbin0 -> 139 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/proinst_obj.gifbin0 -> 138 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-generic.gifbin0 -> 98 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-macro.gifbin0 -> 205 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/text.gifbin0 -> 349 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/txtext.gifbin0 -> 354 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/obj16/warning_obj.gifbin0 -> 337 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/error_ovr.gifbin0 -> 82 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/stale_error_ovr.gifbin0 -> 77 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/warn_ovr.gifbin0 -> 162 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/full/view16/attibute.gifbin0 -> 167 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/sourceEditor.gifbin0 -> 353 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/icons/xmldoc.gifbin0 -> 564 bytes
-rw-r--r--bundles/org.eclipse.wst.xml.ui/plugin.properties40
-rw-r--r--bundles/org.eclipse.wst.xml.ui/plugin.xml248
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/IDesignViewer.java26
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/IDesignViewerActionBarContributor.java19
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/SourceEditorActionBarContributor.java211
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/SourcePageActionContributor.java62
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorActionDefinitionIds.java30
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginHOLD_OLD.java127
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginImageHelper.java152
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginImages.java27
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLMultiPageEditorActionBarContributor.java89
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLMultiPageEditorPart.java773
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/DOMPropertyDescriptorFactory.java138
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java431
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeExtension.java512
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/ViewerExpandCollapseAction.java69
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeActionBarContributor.java325
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeContentProvider.java367
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeHelpContextIds.java29
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreePropertyDescriptorFactory.java97
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java334
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java184
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/nls2/ResourceHandler.java64
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/EditingXML.properties230
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/DOMObserver.java190
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/JobStatusLineHelper.java103
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/Logger.java155
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextEditorXML.java78
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextViewerConfigurationXML.java295
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/XMLEditorPlugin.java236
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/XMLSpellCheckTarget.java41
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/AbstractNodeActionManager.java657
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ActionContributorXML.java205
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/AddBlockCommentActionXML.java67
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/BaseNodeActionManager.java518
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CleanupActionXML.java45
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CleanupDialogXML.java198
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CommentActionXML.java207
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditAttributeAction.java84
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditDoctypeAction.java191
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditElementAction.java119
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditProcessingInstructionAction.java95
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditSchemaInfoAction.java167
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/MenuBuilder.java145
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/NodeAction.java26
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/RemoveBlockCommentActionXML.java71
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ReplacePrefixAction.java79
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ToggleCommentActionXML.java59
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/UncommentActionXML.java61
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractContentAssistProcessor.java2209
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractContentModelGenerator.java86
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractTemplateCompletionProcessor.java118
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformation.java114
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformationPresenter.java112
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformationProvider.java208
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ContentAssistRequest.java277
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ContextInfoModelUtil.java60
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/CustomTemplateProposal.java60
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/NoRegionContentAssistProcessor.java264
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/NonValidatingModelQueryAction.java159
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ProposalComparator.java48
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/SimpleCMElementDeclaration.java170
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/SourceEditorImageHelper.java48
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentAssistProcessor.java86
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentAssistUtilities.java473
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentModelGenerator.java126
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLRelevanceConstants.java51
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLTemplateCompletionProcessor.java63
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditAttributeDialog.java175
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditDoctypeDialog.java241
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditElementDialog.java148
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditEntityHelper.java75
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditNamespaceInfoDialog.java255
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditProcessingInstructionDialog.java124
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditSchemaInfoDialog.java78
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/NamespaceInfoErrorHelper.java101
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/NamespaceInfoTable.java391
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectFileOrXMLCatalogIdDialog.java87
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectFileOrXMLCatalogIdPanel.java182
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectXMLCatalogIdDialog.java111
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectXMLCatalogIdPanel.java132
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/UpdateListener.java20
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/XMLCatalogTableViewer.java198
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dnd/DragNodeCommand.java229
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dnd/XMLDragAndDropManager.java48
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/doubleclick/XMLDoubleClickStrategy.java292
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extension/IDesignViewerSelectionManager.java33
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extension/IExtendedDesignEditor.java34
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extensions/XMLSourceEditingTextTools.java143
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/StructuredAutoEditStrategyXML.java122
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionProcessorXML.java42
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/InsertRequiredAttrsQuickAssistProposal.java175
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/ProblemIDsXML.java31
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickAssistProcessorXML.java169
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickFixProcessorXML.java148
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RemoveUnknownElementQuickFixProposal.java162
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RenameInFileQuickAssistProposal.java183
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/SurroundWithNewElementQuickAssistProposal.java108
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/IHelpContextIds.java43
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImageHelper.java155
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java53
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesAction.java57
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nls/ResourceHandler.java68
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonAddNamespacesControl.java267
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonAddNamespacesDialog.java188
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonEditNamespacesDialog.java320
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonEditNamespacesTargetFieldDialog.java105
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonNamespaceInfoTable.java341
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/openon/DefaultOpenOnXML.java342
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/EncodingSettings.java357
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/WorkbenchDefaultEncodingSettings.java147
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLColorPage.java230
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLFilesPreferencePage.java206
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLSourcePreferencePage.java250
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLTemplatePreferencePage.java68
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/AbstractReconcileStepAdapter.java158
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepAdapterForXML.java720
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepForContentModel.java234
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepForMarkup.java572
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcilerAdapterFactoryForXML.java94
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/StructuredTextReconcilingStrategyForContentModel.java41
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/StructuredTextReconcilingStrategyForMarkup.java34
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/registry/AdapterFactoryProviderForEmbeddedXML.java40
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/registry/AdapterFactoryProviderForXML.java143
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/style/IStyleConstantsXML.java41
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/style/LineStyleProviderForXML.java181
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/MarkupTagInfoProvider.java201
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLBestMatchHoverProcessor.java39
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLInformationProvider.java64
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLTagInfoHoverProcessor.java343
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeIds.java24
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXML.java56
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLAttribute.java26
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLAttributeValue.java26
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLTag.java25
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/text/XMLDocumentRegionEdgeMatcher.java28
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/SharedXMLEditorPluginImageHelper.java72
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/XMLCommonResources.java98
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/XMLCommonUIContextIds.java64
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeAdapter.java345
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeAdapterFactory.java104
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeContentProvider.java104
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeLabelProvider.java140
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/RefreshOutlineJob.java90
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/RefreshPropertySheetJob.java62
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java232
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLNodeActionManager.java52
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/ProcessingInstructionPropertySourceAdapter.java167
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySheetConfiguration.java88
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySourceAdapter.java680
-rw-r--r--bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySourceAdapterFactory.java43
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.xml5
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_de.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_es.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_fr.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_it.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_ja.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_ko.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_pt_BR.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_zh_CN.properties14
-rw-r--r--bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_zh_TW.properties14
373 files changed, 60632 insertions, 0 deletions
diff --git a/bundles/org.eclipse.wst.xml.core/.classpath b/bundles/org.eclipse.wst.xml.core/.classpath
new file mode 100644
index 0000000000..df094ee4a7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.wst.xml.core/.compatibility b/bundles/org.eclipse.wst.xml.core/.compatibility
new file mode 100644
index 0000000000..750d7ddfe6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.compatibility
@@ -0,0 +1,2 @@
+#Wed Mar 24 13:53:52 EST 2004
+.project=12259
diff --git a/bundles/org.eclipse.wst.xml.core/.cvsignore b/bundles/org.eclipse.wst.xml.core/.cvsignore
new file mode 100644
index 0000000000..e19f198e8f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.cvsignore
@@ -0,0 +1,7 @@
+bin
+temp.folder
+xmlmodel.jar
+.project
+org.eclipse.wst.xml.core_6.0.0.jar
+dev.properties
+build.xml
diff --git a/bundles/org.eclipse.wst.xml.core/.options b/bundles/org.eclipse.wst.xml.core/.options
new file mode 100644
index 0000000000..e80df84bc6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/.options
@@ -0,0 +1,2 @@
+org.eclipse.wst.xml.core/debug=true
+org.eclipse.wst.xml.core/debug/tracefilter=
diff --git a/bundles/org.eclipse.wst.xml.core/build.properties b/bundles/org.eclipse.wst.xml.core/build.properties
new file mode 100644
index 0000000000..8441d64567
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/build.properties
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+bin.includes = plugin.xml,\
+ *.jar,\
+ xml.jar,\
+ .options,\
+ extensions.xml,\
+ plugin.properties
+src.includes = plugin.xml,\
+ plugin.properties,\
+ extensions.xml,\
+ build.xml,\
+ .options
+source.xmlmodel.jar = src/
diff --git a/bundles/org.eclipse.wst.xml.core/plugin.properties b/bundles/org.eclipse.wst.xml.core/plugin.properties
new file mode 100644
index 0000000000..6f5d373732
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/plugin.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Structured_Source_XML_Model.name=Structured Source XML Model
+Structured_Source_XML_Model_NL_Support.name=Structured Source XML Model NL Support
diff --git a/bundles/org.eclipse.wst.xml.core/plugin.xml b/bundles/org.eclipse.wst.xml.core/plugin.xml
new file mode 100644
index 0000000000..f172ba456c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/plugin.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+ id="org.eclipse.wst.xml.core"
+ name="%Structured_Source_XML_Model.name"
+ version="1.0.0"
+ provider-name="IBM"
+ class="org.eclipse.wst.xml.core.XMLModelPlugin">
+
+ <runtime>
+ <library name="xmlmodel.jar">
+ <export name="*"/>
+ </library>
+ </runtime>
+ <requires>
+ <import plugin="org.eclipse.core.runtime.compatibility"/>
+ <import plugin="org.eclipse.wst.common.encoding"/>
+ <import plugin="org.eclipse.wst.sse.core"/>
+ <import plugin="org.eclipse.wst.common.contentmodel"/>
+ <import plugin="org.eclipse.core.resources"/>
+ <import plugin="org.eclipse.core.runtime"/>
+ <import plugin="org.eclipse.core.filebuffers"/>
+ <import plugin="org.eclipse.text"/>
+ <import plugin="org.eclipse.wst.xml.uriresolver.ui"/>
+ <import plugin="org.eclipse.wst.xml.uriresolver"/>
+ </requires>
+
+
+ <extension
+ point="org.eclipse.wst.sse.core.modelHandler">
+ <modelHandler
+ default="true"
+ class="org.eclipse.wst.xml.core.modelhandler.ModelHandlerForXML"
+ associatedContentTypeId="org.eclipse.core.runtime.xml"
+ id="org.eclipse.wst.sse.core.handler.xml">
+ </modelHandler>
+ </extension>
+ <extension
+ point="org.eclipse.wst.sse.core.embeddedTypeHandler">
+ <embeddedTypeHandler
+ class="org.eclipse.wst.xml.core.modelhandler.EmbeddedXML">
+ </embeddedTypeHandler>
+ </extension>
+
+ <extension
+ id="org.eclipse.wst.xml.core.builderdelegate.todo"
+ point="org.eclipse.wst.sse.core.builderdelegate">
+ <participant
+ class="org.eclipse.wst.xml.core.builder.delegates.XMLTaskTagSeeker"
+ contentType="org.eclipse.core.runtime.xml,org.eclipse.wst.xml.core.xmlsource">
+ </participant>
+ </extension>
+
+ <extension point="org.eclipse.core.filebuffers.documentCreation"
+ id="org.eclipse.wst.xml.core.documentfactories"
+ name="Structured XML Document Factory">
+ <factory
+ contentTypeId="org.eclipse.core.runtime.xml"
+ class="org.eclipse.wst.sse.core.filebuffers.BasicStructuredDocumentFactory:org.eclipse.core.runtime.xml"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.team.core.fileTypes">
+ <fileTypes
+ type="text"
+ extension="xsl">
+ </fileTypes>
+ <fileTypes
+ type="text"
+ extension="xslt">
+ </fileTypes>
+ <fileTypes
+ type="text"
+ extension="dadx">
+ </fileTypes>
+ <fileTypes
+ type="text"
+ extension="wsdl">
+ </fileTypes>
+ <fileTypes
+ type="text"
+ extension="nst">
+ </fileTypes>
+ <fileTypes
+ type="text"
+ extension="xmi">
+ </fileTypes>
+ <fileTypes
+ type="text"
+ extension="xsd">
+ </fileTypes>
+ </extension>
+ <extension
+ point="org.eclipse.wst.sse.core.formatProcessors">
+ <processor
+ class="org.eclipse.wst.xml.core.format.FormatProcessorXML"
+ contentTypeId="org.eclipse.core.runtime.xml">
+ </processor>
+ </extension>
+
+ <extension
+ point="org.eclipse.core.runtime.contentTypes">
+ <content-type
+ priority="high"
+ name="XML Content Type"
+ id="xmlsource"
+ base-type="org.eclipse.core.runtime.xml"
+ default-charset="UTF-8">
+ <describer class="org.eclipse.wst.xml.core.contenttype.ContentDescriberForXML"/>
+ </content-type>
+ <file-association
+ content-type="org.eclipse.core.runtime.xml"
+ file-extensions="xsl,xslt,dadx,wsdl,nst,xmi,xsd,exsd"/>
+ </extension>
+
+</plugin>
diff --git a/bundles/org.eclipse.wst.xml.core/src/.cvsignore b/bundles/org.eclipse.wst.xml.core/src/.cvsignore
new file mode 100644
index 0000000000..101c29e19d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/.cvsignore
@@ -0,0 +1 @@
+notebook.jpage
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/Logger.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/Logger.java
new file mode 100644
index 0000000000..0e727bc4b3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/Logger.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core;
+
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if
+ * desired, the console. This class should only be used by classes in this
+ * plugin. Other plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+ public static final int ERROR = IStatus.ERROR; // 4
+ public static final int ERROR_DEBUG = 200 + ERROR;
+ private static Plugin fPlugin = XMLModelPlugin.getDefault();
+ private static final String fPluginId = fPlugin.getDescriptor().getUniqueIdentifier();
+ public static final int INFO = IStatus.INFO; // 1
+ public static final int INFO_DEBUG = 200 + INFO;
+
+ public static final int OK = IStatus.OK; // 0
+
+ public static final int OK_DEBUG = 200 + OK;
+
+ private static final String TRACEFILTER_LOCATION = "/debug/tracefilter"; //$NON-NLS-1$
+ public static final int WARNING = IStatus.WARNING; // 2
+ public static final int WARNING_DEBUG = 200 + WARNING;
+
+ /**
+ * Adds message to log.
+ *
+ * @param level
+ * severity level of the message (OK, INFO, WARNING, ERROR,
+ * OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG)
+ * @param message
+ * text to add to the log
+ * @param exception
+ * exception thrown
+ */
+ protected static void _log(int level, String message, Throwable exception) {
+ if (level == OK_DEBUG || level == INFO_DEBUG || level == WARNING_DEBUG || level == ERROR_DEBUG) {
+ if (!isDebugging())
+ return;
+ }
+
+ int severity = IStatus.OK;
+ switch (level) {
+ case INFO_DEBUG :
+ case INFO :
+ severity = IStatus.INFO;
+ break;
+ case WARNING_DEBUG :
+ case WARNING :
+ severity = IStatus.WARNING;
+ break;
+ case ERROR_DEBUG :
+ case ERROR :
+ severity = IStatus.ERROR;
+ }
+ message = (message != null) ? message : "null"; //$NON-NLS-1$
+ Status statusObj = new Status(severity, fPluginId, severity, message, exception);
+ fPlugin.getLog().log(statusObj);
+ }
+
+ /**
+ * Prints message to log if category matches /debug/tracefilter option.
+ *
+ * @param message
+ * text to print
+ * @param category
+ * category of the message, to be compared with
+ * /debug/tracefilter
+ */
+ protected static void _trace(String category, String message, Throwable exception) {
+ if (isTracing(category)) {
+ message = (message != null) ? message : "null"; //$NON-NLS-1$
+ Status statusObj = new Status(IStatus.OK, fPluginId, IStatus.OK, message, exception);
+ fPlugin.getLog().log(statusObj);
+ }
+ }
+
+ /**
+ * @return true if the plugin for this logger is debugging
+ */
+ public static boolean isDebugging() {
+ return fPlugin.isDebugging();
+ }
+
+ /**
+ * Determines if currently tracing a category
+ *
+ * @param category
+ * @return true if tracing category, false otherwise
+ */
+ public static boolean isTracing(String category) {
+ if (!isDebugging())
+ return false;
+
+ String traceFilter = Platform.getDebugOption(fPluginId + TRACEFILTER_LOCATION);
+ if (traceFilter != null) {
+ StringTokenizer tokenizer = new StringTokenizer(traceFilter, ","); //$NON-NLS-1$
+ while (tokenizer.hasMoreTokens()) {
+ String cat = tokenizer.nextToken().trim();
+ if (category.equals(cat)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static void log(int level, String message) {
+ _log(level, message, null);
+ }
+
+ public static void log(int level, String message, Throwable exception) {
+ _log(level, message, exception);
+ }
+
+ public static void logException(String message, Throwable exception) {
+ _log(ERROR, message, exception);
+ }
+
+ public static void logException(Throwable exception) {
+ _log(ERROR, exception.getMessage(), exception);
+ }
+
+ public static void trace(String category, String message) {
+ _trace(category, message, null);
+ }
+
+ public static void traceException(String category, String message, Throwable exception) {
+ _trace(category, message, exception);
+ }
+
+ public static void traceException(String category, Throwable exception) {
+ _trace(category, exception.getMessage(), exception);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/NameValidator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/NameValidator.java
new file mode 100644
index 0000000000..a0d564be80
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/NameValidator.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core;
+
+import java.io.Reader;
+
+import org.eclipse.wst.xml.core.internal.parser.XML10Names;
+
+
+
+public final class NameValidator {
+
+ private static XML10Names charChecker = new XML10Names((Reader) null);
+
+ public synchronized static final boolean isValid(String name) {
+
+ return charChecker.isValidXML10Name(name);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/XMLModelPlugin.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/XMLModelPlugin.java
new file mode 100644
index 0000000000..c531d0baf7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/XMLModelPlugin.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPluginDescriptor;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.common.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.preferences.CommonModelPreferenceNames;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class XMLModelPlugin extends Plugin {
+ //The shared instance.
+ private static XMLModelPlugin plugin;
+
+ /**
+ * Returns the shared instance.
+ */
+ public static XMLModelPlugin getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns the string from the plugin's resource bundle, or 'key' if not
+ * found.
+ */
+ public static String getResourceString(String key) {
+ ResourceBundle bundle = XMLModelPlugin.getDefault().getResourceBundle();
+ try {
+ return bundle.getString(key);
+ } catch (MissingResourceException e) {
+ return key;
+ }
+ }
+
+ /**
+ * Returns the workspace instance.
+ */
+ public static IWorkspace getWorkspace() {
+ return ResourcesPlugin.getWorkspace();
+ }
+
+ //Resource bundle.
+ private ResourceBundle resourceBundle;
+
+ /**
+ * The constructor.
+ */
+ public XMLModelPlugin(IPluginDescriptor descriptor) {
+ super(descriptor);
+ plugin = this;
+ try {
+ resourceBundle = ResourceBundle.getBundle("org.eclipse.wst.xml.core.XmlPluginResources"); //$NON-NLS-1$
+ } catch (MissingResourceException x) {
+ resourceBundle = null;
+ }
+ }
+
+ /**
+ * Returns the plugin's resource bundle,
+ */
+ public ResourceBundle getResourceBundle() {
+ return resourceBundle;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.Plugin#initializeDefaultPluginPreferences()
+ */
+ protected void initializeDefaultPluginPreferences() {
+ super.initializeDefaultPluginPreferences();
+ Preferences prefs = getDefault().getPluginPreferences();
+ // set model preference defaults
+ prefs.setDefault(CommonModelPreferenceNames.CLEANUP_TAG_NAME_CASE, CommonModelPreferenceNames.ASIS);
+ prefs.setDefault(CommonModelPreferenceNames.CLEANUP_ATTR_NAME_CASE, CommonModelPreferenceNames.ASIS);
+ prefs.setDefault(CommonModelPreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS, true);
+ prefs.setDefault(CommonModelPreferenceNames.INSERT_REQUIRED_ATTRS, true);
+ prefs.setDefault(CommonModelPreferenceNames.INSERT_MISSING_TAGS, true);
+ prefs.setDefault(CommonModelPreferenceNames.QUOTE_ATTR_VALUES, true);
+ prefs.setDefault(CommonModelPreferenceNames.FORMAT_SOURCE, true);
+ prefs.setDefault(CommonModelPreferenceNames.CONVERT_EOL_CODES, false);
+
+ prefs.setDefault(CommonEncodingPreferenceNames.INPUT_CODESET, ""); //$NON-NLS-1$
+ prefs.setDefault(CommonEncodingPreferenceNames.OUTPUT_CODESET, CommonModelPreferenceNames.UTF_8);
+ prefs.setDefault(CommonEncodingPreferenceNames.END_OF_LINE_CODE, ""); //$NON-NLS-1$
+
+ prefs.setDefault(CommonModelPreferenceNames.TAB_WIDTH, 4);
+
+ prefs.setDefault(CommonModelPreferenceNames.FORMATTING_SUPPORTED, true);
+ prefs.setDefault(CommonModelPreferenceNames.LINE_WIDTH, 72);
+ prefs.setDefault(CommonModelPreferenceNames.SPLIT_MULTI_ATTRS, false);
+ prefs.setDefault(CommonModelPreferenceNames.INDENT_USING_TABS, true);
+ prefs.setDefault(CommonModelPreferenceNames.CLEAR_ALL_BLANK_LINES, false);
+
+ prefs.setDefault(CommonModelPreferenceNames.PREFERRED_MARKUP_CASE_SUPPORTED, false);
+ prefs.setDefault(CommonModelPreferenceNames.TAG_NAME_CASE, CommonModelPreferenceNames.LOWER);
+ prefs.setDefault(CommonModelPreferenceNames.ATTR_NAME_CASE, CommonModelPreferenceNames.LOWER);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/XMLPreferenceNames.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/XMLPreferenceNames.java
new file mode 100644
index 0000000000..4df06f069f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/XMLPreferenceNames.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core;
+
+
+
+public interface XMLPreferenceNames {
+ String CLEANUP_ATTR_NAME_CASE = "cleanupAttrNameCase";//$NON-NLS-1$
+ String CLEANUP_EOL_CODE = "cleanupEOLCode";//$NON-NLS-1$
+ // cleanup preference names
+ String CLEANUP_TAG_NAME_CASE = "cleanupTagNameCase";//$NON-NLS-1$
+ String CONVERT_EOL_CODES = "convertEOLCodes";//$NON-NLS-1$
+ String FORMAT_SOURCE = "formatSource";//$NON-NLS-1$
+ String INSERT_MISSING_TAGS = "insertMissingTags";//$NON-NLS-1$
+
+ // others
+ String LAST_ACTIVE_PAGE = "lastActivePage";//$NON-NLS-1$
+ String QUOTE_ATTR_VALUES = "quoteAttrValues";//$NON-NLS-1$
+
+ /*
+ * not used for now // highlighting types String COMMENT_BORDER =
+ * "commentBorder";//$NON-NLS-1$ String COMMENT_TEXT =
+ * "commentText";//$NON-NLS-1$ String CDATA_BORDER =
+ * "cdataBorder";//$NON-NLS-1$ String CDATA_TEXT =
+ * "cdataText";//$NON-NLS-1$ String PI_BORDER = "piBorder";//$NON-NLS-1$
+ * String PI_CONTENT = "piContent";//$NON-NLS-1$ String TAG_BORDER =
+ * "tagBorder";//$NON-NLS-1$ String TAG_NAME = "tagName";//$NON-NLS-1$
+ * String TAG_ATTRIBUTE_NAME = "tagAttributeName";//$NON-NLS-1$ String
+ * TAG_ATTRIBUTE_VALUE = "tagAttributeValue";//$NON-NLS-1$ String
+ * DECL_BORDER = "declBoder";//$NON-NLS-1$ String DOCTYPE_NAME =
+ * "doctypeName";//$NON-NLS-1$ String DOCTYPE_EXTERNAL_ID =
+ * "doctypeExternalId";//$NON-NLS-1$ String DOCTYPE_EXTERNAL_ID_PUBREF =
+ * "doctypeExternalPubref";//$NON-NLS-1$ String DOCTYPE_EXTERNAL_ID_SYSREF =
+ * "doctypeExtrenalSysref";//$NON-NLS-1$ String XML_CONTENT =
+ * "xmlContent";//$NON-NLS-1$ // highlighting preferences String COMMA =
+ * ",";//$NON-NLS-1$ String COLOR = "color";//$NON-NLS-1$ String NAME =
+ * "name";//$NON-NLS-1$ String FOREGROUND = "foreground";//$NON-NLS-1$
+ * String BACKGROUND = "background";//$NON-NLS-1$ String BOLD =
+ * "bold";//$NON-NLS-1$ String ITALIC = "italic";//$NON-NLS-1$
+ */
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/builder/delegates/XMLTaskTagSeeker.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/builder/delegates/XMLTaskTagSeeker.java
new file mode 100644
index 0000000000..a9bba3b35f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/builder/delegates/XMLTaskTagSeeker.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.builder.delegates;
+
+import org.eclipse.wst.sse.core.participants.TaskTagSeeker;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class XMLTaskTagSeeker extends TaskTagSeeker {
+
+ /**
+ *
+ */
+ public XMLTaskTagSeeker() {
+ super();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.participants.TaskTagSeeker#isCommentRegion(org.eclipse.wst.sse.core.text.IStructuredDocumentRegion,
+ * org.eclipse.wst.sse.core.text.ITextRegion)
+ */
+ protected boolean isCommentRegion(IStructuredDocumentRegion region, ITextRegion textRegion) {
+ return textRegion.getType().equals(XMLRegionContext.XML_COMMENT_TEXT);
+
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/builder/participants/XMLTaskTagParticipant.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/builder/participants/XMLTaskTagParticipant.java
new file mode 100644
index 0000000000..0c7774ddd9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/builder/participants/XMLTaskTagParticipant.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.builder.participants;
+
+import org.eclipse.wst.sse.core.participants.TaskTagParticipant;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class XMLTaskTagParticipant extends TaskTagParticipant {
+ protected boolean isCommentRegion(IStructuredDocumentRegion region, ITextRegion textRegion) {
+ return textRegion.getType().equals(XMLRegionContext.XML_COMMENT_TEXT);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/CleanupProcessorXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/CleanupProcessorXML.java
new file mode 100644
index 0000000000..6e69a59cde
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/CleanupProcessorXML.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.cleanup;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.core.cleanup.AbstractStructuredCleanupProcessor;
+import org.eclipse.wst.sse.core.cleanup.IStructuredCleanupHandler;
+import org.eclipse.wst.sse.core.cleanup.IStructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.cleanup.StructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.format.IStructuredFormatProcessor;
+import org.eclipse.wst.sse.core.preferences.CommonModelPreferenceNames;
+import org.eclipse.wst.xml.core.XMLModelPlugin;
+import org.eclipse.wst.xml.core.format.FormatProcessorXML;
+import org.w3c.dom.Node;
+
+
+public class CleanupProcessorXML extends AbstractStructuredCleanupProcessor {
+ protected IStructuredCleanupPreferences fCleanupPreferences = null;
+
+ protected IStructuredCleanupHandler getCleanupHandler(Node node) {
+ short nodeType = node.getNodeType();
+ IStructuredCleanupHandler cleanupHandler = null;
+ switch (nodeType) {
+ case Node.ELEMENT_NODE : {
+ cleanupHandler = new ElementNodeCleanupHandler();
+ break;
+ }
+ case Node.TEXT_NODE : {
+ cleanupHandler = new NodeCleanupHandler();
+ break;
+ }
+ default : {
+ cleanupHandler = new NodeCleanupHandler();
+ }
+ }
+
+ // init CleanupPreferences
+ cleanupHandler.setCleanupPreferences(getCleanupPreferences());
+
+ return cleanupHandler;
+ }
+
+ public IStructuredCleanupPreferences getCleanupPreferences() {
+ if (fCleanupPreferences == null) {
+ fCleanupPreferences = new StructuredCleanupPreferences();
+
+ Preferences preferences = getModelPreferences();
+ if (preferences != null) {
+ fCleanupPreferences.setTagNameCase(preferences.getInt(CommonModelPreferenceNames.CLEANUP_TAG_NAME_CASE));
+ fCleanupPreferences.setAttrNameCase(preferences.getInt(CommonModelPreferenceNames.CLEANUP_ATTR_NAME_CASE));
+ fCleanupPreferences.setCompressEmptyElementTags(preferences.getBoolean(CommonModelPreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS));
+ fCleanupPreferences.setInsertRequiredAttrs(preferences.getBoolean(CommonModelPreferenceNames.INSERT_REQUIRED_ATTRS));
+ fCleanupPreferences.setInsertMissingTags(preferences.getBoolean(CommonModelPreferenceNames.INSERT_MISSING_TAGS));
+ fCleanupPreferences.setQuoteAttrValues(preferences.getBoolean(CommonModelPreferenceNames.QUOTE_ATTR_VALUES));
+ fCleanupPreferences.setFormatSource(preferences.getBoolean(CommonModelPreferenceNames.FORMAT_SOURCE));
+ fCleanupPreferences.setConvertEOLCodes(preferences.getBoolean(CommonModelPreferenceNames.CONVERT_EOL_CODES));
+ fCleanupPreferences.setEOLCode(preferences.getString(CommonModelPreferenceNames.CLEANUP_EOL_CODE));
+ }
+ }
+
+ return fCleanupPreferences;
+ }
+
+ protected String getContentType() {
+ return IContentTypeIdentifier.ContentTypeID_SSEXML;
+ }
+
+ protected IStructuredFormatProcessor getFormatProcessor() {
+ return new FormatProcessorXML();
+ }
+
+ protected Preferences getModelPreferences() {
+ return XMLModelPlugin.getDefault().getPluginPreferences();
+ }
+
+ protected void refreshCleanupPreferences() {
+ fCleanupPreferences = null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/ElementNodeCleanupHandler.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/ElementNodeCleanupHandler.java
new file mode 100644
index 0000000000..39f4e31b3a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/ElementNodeCleanupHandler.java
@@ -0,0 +1,556 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.cleanup;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.core.cleanup.IStructuredCleanupHandler;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.xml.core.document.XMLAttr;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLGenerator;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class ElementNodeCleanupHandler extends NodeCleanupHandler {
+ protected static final char DOUBLE_QUOTE = '\"'; //$NON-NLS-1$
+ protected static final String DOUBLE_QUOTES = "\"\""; //$NON-NLS-1$
+ protected static final String EMPTY_TAG_CLOSE = "/>"; //$NON-NLS-1$
+ protected static final String END_TAG_OPEN = "</"; //$NON-NLS-1$
+ protected static final char SINGLE_QUOTE = '\''; //$NON-NLS-1$
+ protected static final String SINGLE_QUOTES = "''"; //$NON-NLS-1$
+
+ /** Non-NLS strings */
+ protected static final String START_TAG_OPEN = "<"; //$NON-NLS-1$
+ protected static final String TAG_CLOSE = ">"; //$NON-NLS-1$
+
+ public Node cleanup(Node node) {
+ Node newNode = cleanupChildren(node);
+ XMLNode renamedNode = newNode instanceof XMLNode ? (XMLNode) newNode : null;
+
+ // call quoteAttrValue() first so it will close any unclosed attr
+ // quoteAttrValue() will return the new start tag if there is a
+ // structure change
+ renamedNode = quoteAttrValue(renamedNode);
+
+ // insert tag close if missing
+ // if node is not comment tag
+ // and not implicit tag
+ if (!isCommentTag(renamedNode) && !isImplicitTag(renamedNode)) {
+ XMLModel structuredModel = renamedNode.getModel();
+
+ // save start offset before insertTagClose()
+ // or else renamedNode.getStartOffset() will be zero if
+ // renamedNode replaced by insertTagClose()
+ int startTagStartOffset = renamedNode.getStartOffset();
+
+ // for start tag
+ IStructuredDocumentRegion startTagStructuredDocumentRegion = renamedNode.getStartStructuredDocumentRegion();
+ insertTagClose(structuredModel, startTagStructuredDocumentRegion);
+
+ // update renamedNode and startTagStructuredDocumentRegion after
+ // insertTagClose()
+ renamedNode = (XMLNode) structuredModel.getIndexedRegion(startTagStartOffset);
+ startTagStructuredDocumentRegion = renamedNode.getStartStructuredDocumentRegion();
+
+ // for end tag
+ IStructuredDocumentRegion endTagStructuredDocumentRegion = renamedNode.getEndStructuredDocumentRegion();
+ if (endTagStructuredDocumentRegion != startTagStructuredDocumentRegion)
+ insertTagClose(structuredModel, endTagStructuredDocumentRegion);
+ }
+
+ // call insertMissingTags() next, it will generate implicit tags if
+ // there are any
+ // insertMissingTags() will return the new missing start tag if one is
+ // missing
+ renamedNode = insertMissingTags(renamedNode);
+
+ renamedNode = compressEmptyElementTag(renamedNode);
+
+ renamedNode = insertRequiredAttrs(renamedNode);
+
+ return renamedNode;
+ }
+
+ protected Node cleanupChildren(Node node) {
+ Node parentNode = node;
+
+ if (node != null) {
+ Node childNode = node.getFirstChild();
+ while (childNode != null) {
+ // get cleanup handler
+ IStructuredCleanupHandler cleanupHandler = getCleanupHandler(childNode);
+
+ // cleanup each child
+ childNode = cleanupHandler.cleanup(childNode);
+
+ // get new parent node
+ parentNode = (XMLNode) childNode.getParentNode();
+
+ // get next child node
+ childNode = (XMLNode) childNode.getNextSibling();
+ }
+ }
+
+ return parentNode;
+ }
+
+ private XMLNode compressEmptyElementTag(XMLNode node) {
+ boolean compressEmptyElementTags = getCleanupPreferences().getCompressEmptyElementTags();
+ XMLNode newNode = node;
+
+ IStructuredDocumentRegion startTagStructuredDocumentRegion = newNode.getFirstStructuredDocumentRegion();
+ IStructuredDocumentRegion endTagStructuredDocumentRegion = newNode.getLastStructuredDocumentRegion();
+
+ if (compressEmptyElementTags && startTagStructuredDocumentRegion != endTagStructuredDocumentRegion && startTagStructuredDocumentRegion != null) {
+ ITextRegionList regions = startTagStructuredDocumentRegion.getRegions();
+ ITextRegion lastRegion = regions.get(regions.size() - 1);
+ // format children and end tag if not empty element tag
+ if (lastRegion.getType() != XMLRegionContext.XML_EMPTY_TAG_CLOSE) {
+ NodeList childNodes = newNode.getChildNodes();
+ if (childNodes == null || childNodes.getLength() == 0 || (childNodes.getLength() == 1 && (childNodes.item(0)).getNodeType() == Node.TEXT_NODE && ((childNodes.item(0)).getNodeValue().trim().length() == 0))) {
+ XMLModel structuredModel = newNode.getModel();
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+ int startTagStartOffset = newNode.getStartOffset();
+ int offset = endTagStructuredDocumentRegion.getStart();
+ int length = endTagStructuredDocumentRegion.getLength();
+ structuredDocument.replaceText(structuredDocument, offset, length, ""); //$NON-NLS-1$
+ newNode = (XMLNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+
+ offset = startTagStructuredDocumentRegion.getStart() + lastRegion.getStart();
+ structuredDocument.replaceText(structuredDocument, offset, 0, "/"); //$NON-NLS-1$
+ newNode = (XMLNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+ }
+ }
+ }
+
+ return newNode;
+ }
+
+ protected IStructuredCleanupHandler getCleanupHandler(Node node) {
+ short nodeType = node.getNodeType();
+ IStructuredCleanupHandler cleanupHandler = null;
+ switch (nodeType) {
+ case org.w3c.dom.Node.ELEMENT_NODE : {
+ cleanupHandler = new ElementNodeCleanupHandler();
+ break;
+ }
+ case org.w3c.dom.Node.TEXT_NODE : {
+ cleanupHandler = new NodeCleanupHandler();
+ break;
+ }
+ default : {
+ cleanupHandler = new NodeCleanupHandler();
+ }
+ }
+
+ // init CleanupPreferences
+ cleanupHandler.setCleanupPreferences(getCleanupPreferences());
+
+ return cleanupHandler;
+ }
+
+
+ protected ModelQuery getModelQuery(Node node) {
+ if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ return ModelQueryUtil.getModelQuery((Document) node);
+ } else {
+ return ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+ }
+ }
+
+ protected List getRequiredAttrs(Node node) {
+ List result = new ArrayList();
+
+ ModelQuery modelQuery = getModelQuery(node);
+ if (modelQuery != null) {
+ CMElementDeclaration elementDecl = modelQuery.getCMElementDeclaration((Element) node);
+ if (elementDecl != null) {
+ CMNamedNodeMap attrMap = elementDecl.getAttributes();
+ Iterator it = attrMap.iterator();
+ CMAttributeDeclaration attr = null;
+ while (it.hasNext()) {
+ attr = (CMAttributeDeclaration) it.next();
+ if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
+ result.add(attr);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private XMLNode insertEndTag(XMLNode node) {
+ XMLNode newNode = node;
+ XMLElement element = (XMLElement) node;
+ if (element.isCommentTag())
+ return node; // do nothing
+
+ int startTagStartOffset = node.getStartOffset();
+ XMLModel structuredModel = node.getModel();
+
+ if (isEmptyElement(element)) {
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+ IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+ ITextRegionList regions = startStructuredDocumentRegion.getRegions();
+ ITextRegion lastRegion = regions.get(regions.size() - 1);
+ structuredDocument.replaceText(structuredDocument, startStructuredDocumentRegion.getStartOffset(lastRegion), lastRegion.getLength(), EMPTY_TAG_CLOSE);
+
+ if (regions.size() > 1) {
+ ITextRegion regionBeforeTagClose = regions.get(regions.size() - 1 - 1);
+
+ // insert a space separator before tag close if the previous
+ // region does not have extra spaces
+ if (regionBeforeTagClose.getTextLength() == regionBeforeTagClose.getLength())
+ structuredDocument.replaceText(structuredDocument, startStructuredDocumentRegion.getStartOffset(lastRegion), 0, " "); //$NON-NLS-1$
+ }
+ } else {
+ String tagName = node.getNodeName();
+ String endTag = END_TAG_OPEN.concat(tagName).concat(TAG_CLOSE);
+
+ XMLNode lastChild = (XMLNode) node.getLastChild();
+ int endTagStartOffset = 0;
+ if (lastChild != null)
+ // if this node has children, insert the end tag after the
+ // last child
+ endTagStartOffset = lastChild.getEndOffset();
+ else
+ // if this node does not has children, insert the end tag
+ // after the start tag
+ endTagStartOffset = node.getEndOffset();
+
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+ structuredDocument.replaceText(structuredDocument, endTagStartOffset, 0, endTag);
+ }
+
+ newNode = (XMLNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+ // new
+ // node
+
+ return newNode;
+ }
+
+ private XMLNode insertMissingTags(XMLNode node) {
+ boolean insertMissingTags = getCleanupPreferences().getInsertMissingTags();
+ XMLNode newNode = node;
+
+ if (insertMissingTags) {
+ IStructuredDocumentRegion startTagStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+ if (startTagStructuredDocumentRegion == null) {
+ // implicit start tag; generate tag for it
+ newNode = insertStartTag(node);
+ startTagStructuredDocumentRegion = newNode.getStartStructuredDocumentRegion();
+ }
+
+ IStructuredDocumentRegion endTagStructuredDocumentRegion = newNode.getEndStructuredDocumentRegion();
+ ITextRegionList startStructuredDocumentRegionRegions = startTagStructuredDocumentRegion.getRegions();
+ if (startTagStructuredDocumentRegion != null && startStructuredDocumentRegionRegions != null && (startStructuredDocumentRegionRegions.get(startStructuredDocumentRegionRegions.size() - 1)).getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE) {
+
+ } else {
+ if (startTagStructuredDocumentRegion == null) {
+ // start tag missing
+ if (isStartTagRequired(newNode))
+ newNode = insertStartTag(newNode);
+ } else if (endTagStructuredDocumentRegion == null) {
+ // end tag missing
+ if (isEndTagRequired(newNode))
+ newNode = insertEndTag(newNode);
+ }
+ }
+ }
+
+ return newNode;
+ }
+
+ private XMLNode insertRequiredAttrs(XMLNode node) {
+ boolean insertRequiredAttrs = getCleanupPreferences().getInsertRequiredAttrs();
+ XMLNode newNode = node;
+
+ if (insertRequiredAttrs) {
+ List requiredAttrs = getRequiredAttrs(newNode);
+ if (requiredAttrs.size() > 0) {
+ NamedNodeMap currentAttrs = node.getAttributes();
+ List insertAttrs = new ArrayList();
+ if (currentAttrs.getLength() == 0)
+ insertAttrs.addAll(requiredAttrs);
+ else {
+ for (int i = 0; i < requiredAttrs.size(); i++) {
+ String requiredAttrName = ((CMAttributeDeclaration) requiredAttrs.get(i)).getAttrName();
+ boolean found = false;
+ for (int j = 0; j < currentAttrs.getLength(); j++) {
+ String currentAttrName = currentAttrs.item(j).getNodeName();
+ if (requiredAttrName.compareToIgnoreCase(currentAttrName) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ insertAttrs.add(requiredAttrs.get(i));
+ }
+ }
+ if (insertAttrs.size() > 0) {
+ IStructuredDocumentRegion startStructuredDocumentRegion = newNode.getStartStructuredDocumentRegion();
+ int index = startStructuredDocumentRegion.getEndOffset();
+ ITextRegion lastRegion = startStructuredDocumentRegion.getLastRegion();
+ if (lastRegion.getType() == XMLRegionContext.XML_TAG_CLOSE) {
+ index--;
+ lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+ } else if (lastRegion.getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE) {
+ index = index - 2;
+ lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+ }
+ MultiTextEdit multiTextEdit = new MultiTextEdit();
+ try {
+ for (int i = insertAttrs.size() - 1; i >= 0; i--) {
+ CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) insertAttrs.get(i);
+ String requiredAttributeName = attrDecl.getAttrName();
+ String defaultValue = attrDecl.getDefaultValue();
+ if (defaultValue == null)
+ defaultValue = ""; //$NON-NLS-1$
+ String nameAndDefaultValue = " "; //$NON-NLS-1$
+ if (i == 0 && lastRegion.getLength() > lastRegion.getTextLength())
+ nameAndDefaultValue = ""; //$NON-NLS-1$
+ nameAndDefaultValue += requiredAttributeName + "=\"" + defaultValue + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+ multiTextEdit.addChild(new InsertEdit(index, nameAndDefaultValue));
+ // BUG3381: MultiTextEdit applies all child
+ // TextEdit's basing on offsets
+ // in the document before the first TextEdit, not
+ // after each
+ // child TextEdit. Therefore, do not need to
+ // advance the index.
+ //index += nameAndDefaultValue.length();
+ }
+ multiTextEdit.apply(newNode.getStructuredDocument());
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException(e);
+ }
+ }
+ }
+ }
+
+ return newNode;
+ }
+
+ private XMLNode insertStartTag(XMLNode node) {
+ XMLNode newNode = node;
+
+ if (isCommentTag(node))
+ return node; // do nothing
+
+ String tagName = node.getNodeName();
+ String startTag = START_TAG_OPEN.concat(tagName).concat(TAG_CLOSE);
+ int startTagStartOffset = node.getStartOffset();
+
+ XMLModel structuredModel = node.getModel();
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+ structuredDocument.replaceText(structuredDocument, startTagStartOffset, 0, startTag);
+ newNode = (XMLNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+ // new
+ // node
+
+ return newNode;
+ }
+
+ private void insertTagClose(XMLModel structuredModel, IStructuredDocumentRegion flatNode) {
+ if (flatNode != null) {
+ ITextRegionList flatnodeRegions = flatNode.getRegions();
+ if (flatnodeRegions != null) {
+ ITextRegion lastRegion = flatnodeRegions.get(flatnodeRegions.size() - 1);
+ if (lastRegion != null) {
+ String regionType = lastRegion.getType();
+ if ((regionType != XMLRegionContext.XML_EMPTY_TAG_CLOSE) && (regionType != XMLRegionContext.XML_TAG_CLOSE)) {
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+ // insert ">" after lastRegion of flatNode
+ // as in "<a</a>" if flatNode is for start tag, or in
+ // "<a></a" if flatNode is for end tag
+ structuredDocument.replaceText(structuredDocument, flatNode.getTextEndOffset(lastRegion), 0, ">"); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @param renamedNode
+ * @return
+ */
+ private boolean isCommentTag(Node renamedNode) {
+ boolean result = false;
+ if (renamedNode instanceof XMLElement) {
+ XMLElement element = (XMLElement) renamedNode;
+ result = element.isCommentTag();
+ }
+ return result;
+ }
+
+ private boolean isEmptyElement(XMLElement element) {
+ Document document = element.getOwnerDocument();
+ if (document == null)
+ // undefined tag, return default
+ return false;
+
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+ if (modelQuery == null)
+ // undefined tag, return default
+ return false;
+
+ CMElementDeclaration decl = modelQuery.getCMElementDeclaration(element);
+ if (decl == null)
+ // undefined tag, return default
+ return false;
+
+ return (decl.getContentType() == CMElementDeclaration.EMPTY);
+ }
+
+ private boolean isEndTagRequired(XMLNode node) {
+ if (node == null)
+ return false;
+ return node.isContainer();
+ }
+
+ /**
+ * A tag is implicit if it has not corresponding region in document.
+ *
+ * @param renamedNode
+ * @return
+ */
+ private boolean isImplicitTag(XMLNode renamedNode) {
+ return renamedNode.getStartStructuredDocumentRegion() == null;
+ }
+
+ /**
+ * The end tags of HTML EMPTY content type, such as IMG, and HTML
+ * undefined tags are parsed separately from the start tags. So inserting
+ * the missing start tag is useless and even harmful.
+ */
+ private boolean isStartTagRequired(XMLNode node) {
+ if (node == null)
+ return false;
+ return node.isContainer();
+ }
+
+ private boolean isXMLType(XMLModel structuredModel) {
+ boolean result = false;
+
+ if (structuredModel != null && structuredModel != null) {
+ XMLDocument document = structuredModel.getDocument();
+
+ if (document != null)
+ result = document.isXMLType();
+ }
+
+ return result;
+ }
+
+ private XMLNode quoteAttrValue(XMLNode node) {
+ XMLNode newNode = node;
+ //XMLElement element = (XMLElement) node;
+ if (isCommentTag(node))
+ return node; // do nothing
+
+ boolean quoteAttrValues = getCleanupPreferences().getQuoteAttrValues();
+
+ if (quoteAttrValues) {
+ NamedNodeMap attributes = newNode.getAttributes();
+ if (attributes != null) {
+ int attributesLength = attributes.getLength();
+ XMLGenerator generator = node.getModel().getGenerator();
+
+ for (int i = 0; i < attributesLength; i++) {
+ attributes = newNode.getAttributes();
+ attributesLength = attributes.getLength();
+ XMLAttr eachAttr = (XMLAttr) attributes.item(i);
+ //ITextRegion oldAttrValueRegion =
+ // eachAttr.getValueRegion();
+ String oldAttrValue = eachAttr.getValueRegionText();
+ if (oldAttrValue == null) {
+ XMLModel structuredModel = node.getModel();
+ if (isXMLType(structuredModel)) {
+ String newAttrValue = "\"" + eachAttr.getNameRegionText() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+ if (eachAttr.getEqualRegion() != null)
+ // equal region exists
+ structuredDocument.replaceText(structuredDocument, eachAttr.getEndOffset(), 0, newAttrValue);
+ else
+ // no equal region
+ structuredDocument.replaceText(structuredDocument, eachAttr.getNameRegionTextEndOffset(), 0, "=".concat(newAttrValue)); //$NON-NLS-1$
+ newNode = (XMLNode) structuredModel.getIndexedRegion(node.getStartOffset()); // save
+ // new
+ // node
+ }
+ } else {
+ //String oldAttrValue = oldAttrValueRegion.getText();
+ char quote = StringUtils.isQuoted(oldAttrValue) ? oldAttrValue.charAt(0) : DOUBLE_QUOTE;
+ String newAttrValue = generator.generateAttrValue(eachAttr, quote);
+
+ // There is a problem in
+ // StructuredDocumentRegionUtil.getAttrValue(ITextRegion)
+ // when the region is instanceof ContextRegion.
+ // Workaround for now...
+ if (oldAttrValue.length() == 1) {
+ char firstChar = oldAttrValue.charAt(0);
+ if (firstChar == SINGLE_QUOTE)
+ newAttrValue = SINGLE_QUOTES;
+ else if (firstChar == DOUBLE_QUOTE)
+ newAttrValue = DOUBLE_QUOTES;
+ }
+
+ if (newAttrValue != null) {
+ if (newAttrValue.compareTo(oldAttrValue) != 0) {
+ int attrValueStartOffset = eachAttr.getValueRegionStartOffset();
+ int attrValueLength = oldAttrValue.length();
+ int startTagStartOffset = node.getStartOffset();
+
+ XMLModel structuredModel = node.getModel();
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+ structuredDocument.replaceText(structuredDocument, attrValueStartOffset, attrValueLength, newAttrValue);
+ newNode = (XMLNode) structuredModel.getIndexedRegion(startTagStartOffset); // save
+ // new
+ // node
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return newNode;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/NodeCleanupHandler.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/NodeCleanupHandler.java
new file mode 100644
index 0000000000..ffdb1977d4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/NodeCleanupHandler.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.cleanup;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.cleanup.IStructuredCleanupHandler;
+import org.eclipse.wst.sse.core.cleanup.IStructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.cleanup.StructuredCleanupPreferences;
+import org.eclipse.wst.sse.core.preferences.CommonModelPreferenceNames;
+import org.eclipse.wst.xml.core.XMLModelPlugin;
+import org.w3c.dom.Node;
+
+
+public class NodeCleanupHandler implements IStructuredCleanupHandler {
+
+ protected IStructuredCleanupPreferences fCleanupPreferences = null;
+ protected IProgressMonitor fProgressMonitor = null;
+
+ /**
+ * @see com.ibm.sed.partitionCleanup.CleanupHandler#cleanup(com.ibm.sed.model.xml.XMLNode)
+ */
+ public Node cleanup(Node node) {
+
+ return node;
+ }
+
+ /**
+ * @see com.ibm.sed.partitionCleanup.CleanupHandler#getCleanupPreferences()
+ */
+ public IStructuredCleanupPreferences getCleanupPreferences() {
+ if (fCleanupPreferences == null) {
+ fCleanupPreferences = new StructuredCleanupPreferences();
+
+ Preferences preferences = getModelPreferences();
+ if (preferences != null) {
+ fCleanupPreferences.setTagNameCase(preferences.getInt(CommonModelPreferenceNames.CLEANUP_TAG_NAME_CASE));
+ fCleanupPreferences.setAttrNameCase(preferences.getInt(CommonModelPreferenceNames.CLEANUP_ATTR_NAME_CASE));
+ fCleanupPreferences.setCompressEmptyElementTags(preferences.getBoolean(CommonModelPreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS));
+ fCleanupPreferences.setInsertRequiredAttrs(preferences.getBoolean(CommonModelPreferenceNames.INSERT_REQUIRED_ATTRS));
+ fCleanupPreferences.setInsertMissingTags(preferences.getBoolean(CommonModelPreferenceNames.INSERT_MISSING_TAGS));
+ fCleanupPreferences.setQuoteAttrValues(preferences.getBoolean(CommonModelPreferenceNames.QUOTE_ATTR_VALUES));
+ fCleanupPreferences.setFormatSource(preferences.getBoolean(CommonModelPreferenceNames.FORMAT_SOURCE));
+ fCleanupPreferences.setConvertEOLCodes(preferences.getBoolean(CommonModelPreferenceNames.CONVERT_EOL_CODES));
+ fCleanupPreferences.setEOLCode(preferences.getString(CommonModelPreferenceNames.CLEANUP_EOL_CODE));
+ }
+ }
+
+ return fCleanupPreferences;
+ }
+
+ protected Preferences getModelPreferences() {
+ return XMLModelPlugin.getDefault().getPluginPreferences();
+ }
+
+ public void setCleanupPreferences(IStructuredCleanupPreferences cleanupPreferences) {
+
+ fCleanupPreferences = cleanupPreferences;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/XMLCleanupPreferences.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/XMLCleanupPreferences.java
new file mode 100644
index 0000000000..6bae47a150
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/XMLCleanupPreferences.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.cleanup;
+
+import org.eclipse.core.runtime.Preferences;
+
+/**
+ * @deprecated renamed to IStructuredCleanupPreferences
+ *
+ * TODO will delete in C5
+ */
+public interface XMLCleanupPreferences {
+
+ int getAttrNameCase();
+
+ boolean getConvertEOLCodes();
+
+ String getEOLCode();
+
+ boolean getFormatSource();
+
+ boolean getInsertMissingTags();
+
+ boolean getQuoteAttrValues();
+
+ int getTagNameCase();
+
+ void setAttrNameCase(int attrNameCase);
+
+ void setConvertEOLCodes(boolean convertEOLCodes);
+
+ void setEOLCode(String EOLCode);
+
+ void setFormatSource(boolean formatSource);
+
+ void setInsertMissingTags(boolean insertMissingTags);
+
+ //void setPreferenceStore(IPreferenceStore preferenceStore);
+ void setPreferences(Preferences preferences);
+
+ void setQuoteAttrValues(boolean quoteAttrValues);
+
+ void setTagNameCase(int tagNameCase);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/XMLCleanupPreferencesImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/XMLCleanupPreferencesImpl.java
new file mode 100644
index 0000000000..6dccbc1302
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/cleanup/XMLCleanupPreferencesImpl.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.cleanup;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.xml.core.XMLPreferenceNames;
+
+
+/**
+ * @deprecated renamed to StructuredCleanupPreferences
+ *
+ * TODO will delete in C5
+ */
+public class XMLCleanupPreferencesImpl implements XMLCleanupPreferences {
+
+ private static XMLCleanupPreferencesImpl fInstance;
+
+ public synchronized static XMLCleanupPreferencesImpl getInstance() {
+
+ // added for one method in CleanupDialog ... may be better way
+ if (fInstance == null) {
+ fInstance = new XMLCleanupPreferencesImpl();
+ }
+ return fInstance;
+ }
+
+ private int fAttrNameCase;
+ private boolean fConvertEOLCodes;
+ private String fEOLCode;
+ private boolean fFormatSource;
+ private boolean fInsertMissingTags;
+ //private IPreferenceStore fPreferenceStore = null;
+ private Preferences fPreferences = null;
+ private boolean fQuoteAttrValues;
+ private int fTagNameCase;
+
+ public int getAttrNameCase() {
+
+ return fAttrNameCase;
+ }
+
+ public boolean getConvertEOLCodes() {
+
+ return fConvertEOLCodes;
+ }
+
+ public String getEOLCode() {
+
+ return fEOLCode;
+ }
+
+ public boolean getFormatSource() {
+
+ return fFormatSource;
+ }
+
+ public boolean getInsertMissingTags() {
+
+ return fInsertMissingTags;
+ }
+
+ private IModelManagerPlugin getModelManagerPlugin() {
+
+ IModelManagerPlugin plugin = (IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID);
+ return plugin;
+ }
+
+ public Preferences getPreferences() {
+
+ if (fPreferences == null) {
+ fPreferences = getModelManagerPlugin().getPluginPreferences();
+ }
+ return fPreferences;
+ }
+
+ public boolean getQuoteAttrValues() {
+
+ return fQuoteAttrValues;
+ }
+
+ public int getTagNameCase() {
+
+ return fTagNameCase;
+ }
+
+ public void setAttrNameCase(int attrNameCase) {
+
+ fAttrNameCase = attrNameCase;
+ }
+
+ public void setConvertEOLCodes(boolean convertEOLCodes) {
+
+ fConvertEOLCodes = convertEOLCodes;
+ }
+
+ public void setEOLCode(String EOLCode) {
+
+ fEOLCode = EOLCode;
+ }
+
+ public void setFormatSource(boolean formatSource) {
+
+ fFormatSource = formatSource;
+ }
+
+ public void setInsertMissingTags(boolean insertMissingTags) {
+
+ fInsertMissingTags = insertMissingTags;
+ }
+
+ public void setPreferences(Preferences prefs) {
+
+ fPreferences = prefs;
+ updateOptions();
+ }
+
+ public void setQuoteAttrValues(boolean quoteAttrValues) {
+
+ fQuoteAttrValues = quoteAttrValues;
+ }
+
+ public void setTagNameCase(int tagNameCase) {
+
+ fTagNameCase = tagNameCase;
+ }
+
+ protected void updateOptions() {
+
+ Preferences p = getPreferences();
+ fTagNameCase = p.getInt(XMLPreferenceNames.CLEANUP_TAG_NAME_CASE);
+ fAttrNameCase = p.getInt(XMLPreferenceNames.CLEANUP_ATTR_NAME_CASE);
+ fInsertMissingTags = p.getBoolean(XMLPreferenceNames.INSERT_MISSING_TAGS);
+ fQuoteAttrValues = p.getBoolean(XMLPreferenceNames.QUOTE_ATTR_VALUES);
+ fFormatSource = p.getBoolean(XMLPreferenceNames.FORMAT_SOURCE);
+ fConvertEOLCodes = p.getBoolean(XMLPreferenceNames.CONVERT_EOL_CODES);
+ fEOLCode = p.getString(XMLPreferenceNames.CLEANUP_EOL_CODE);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/CommentElementAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/CommentElementAdapter.java
new file mode 100644
index 0000000000..ae18f47946
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/CommentElementAdapter.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.commentelement;
+
+
+
+import org.eclipse.core.runtime.IPluginDescriptor;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.xml.core.commentelement.impl.CommentElementConfiguration;
+import org.eclipse.wst.xml.core.document.TagAdapter;
+import org.eclipse.wst.xml.core.document.XMLElement;
+
+
+/**
+ */
+public class CommentElementAdapter implements TagAdapter {
+ private CommentElementConfiguration fConfiguration;
+
+ private boolean fEndTag;
+ private CommentElementHandler fHandler;
+
+ public CommentElementAdapter(boolean isEndTag, CommentElementHandler handler) {
+ fEndTag = isEndTag;
+ fHandler = handler;
+ }
+
+ private String generateCommentClose(XMLElement element) {
+ return (element.isJSPTag()) ? "--%>" : "-->"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ private String generateCommentOpen(XMLElement element) {
+ return (element.isJSPTag()) ? "<%--" : "<!--"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ private CommentElementConfiguration getConfiguration() {
+ return fConfiguration;
+ }
+
+ /**
+ * @see com.ibm.sed.model.xml.TagAdapter#getEndTag(XMLElement)
+ */
+ public String getEndTag(XMLElement element) {
+ String content = fHandler.generateEndTagContent(element);
+ if (content == null) {
+ return null;
+ }
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append(generateCommentOpen(element));
+ buffer.append(content);
+ buffer.append(generateCommentClose(element));
+
+ return buffer.toString();
+ }
+
+ public String getHandlerID() {
+ return getConfiguration().getHandlerID();
+ }
+
+ public IPluginDescriptor getHandlerPluginDescriptor() {
+ return fConfiguration.getHandlerPluginDescriptor();
+ }
+
+ public String getProperty(String name) {
+ return getConfiguration().getProperty(name);
+ }
+
+ /**
+ * @see com.ibm.sed.model.xml.TagAdapter#getStartTag(XMLElement)
+ */
+ public String getStartTag(XMLElement element) {
+ String content = fHandler.generateStartTagContent(element);
+ if (content == null) {
+ return null;
+ }
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append(generateCommentOpen(element));
+ buffer.append(content);
+ buffer.append(generateCommentClose(element));
+
+ return buffer.toString();
+ }
+
+ /**
+ * @see com.ibm.sed.model.INodeAdapter#isAdapterForType(Object)
+ */
+ public boolean isAdapterForType(Object type) {
+ return (type == CommentElementAdapter.class || type == TagAdapter.class);
+ }
+
+ public boolean isContainer() {
+ return (!fHandler.isEmpty());
+ }
+
+ /**
+ * @see com.ibm.sed.model.xml.TagAdapter#isEndTag()
+ */
+ public boolean isEndTag() {
+ return fEndTag;
+ }
+
+ /**
+ * @see com.ibm.sed.model.INodeAdapter#notifyChanged(INodeNotifier, int,
+ * Object, Object, Object, int)
+ */
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ }
+
+ public void setConfiguration(CommentElementConfiguration configuration) {
+ fConfiguration = configuration;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/CommentElementHandler.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/CommentElementHandler.java
new file mode 100644
index 0000000000..b5eae28068
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/CommentElementHandler.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.commentelement;
+
+
+
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ */
+public interface CommentElementHandler {
+ /**
+ * This method is called when the prefix of the comment content matches
+ * the string specified in &lt;startswith prefix=""/&gt; in plugin
+ * extension. Comment content is parsed and new DOM element is created in
+ * this method. Implementor has to do following:
+ * <li>For start tag :
+ * <ul>
+ * <li>parse comment content and create new element instance.</li>
+ * </ul>
+ * </li>
+ * <li>For end tag :
+ * <ul>
+ * <li>parse comment content and create new element instance.</li>
+ * <li>make isEndTag flag true.</li>
+ * <li>Parser framework searches mached start tag element instance after
+ * this createElement call, and new instance is just thrown away.</li>
+ * </ul>
+ * </li>
+ * <li>For empty tag :
+ * <ul>
+ * <li>parse comment content and create new element instance.</li>
+ * <li>make isEndTag flag true.</li>
+ * </ul>
+ * </li>
+ *
+ * @param document
+ * parent DOM document
+ * @param data
+ * comment content. comment prefix (&lt;!-- or &lt;%--), suffix
+ * (--&gt; or --%&gt;), and surrounding spaces are trimmed.
+ * @param isJSPTag
+ * true if the comment is JSP style comment. This information
+ * may be required by handler when the handler accepts both XML
+ * style and JSP style comment (namely,
+ * commenttype=&quot;both&quot; in plugin.xml).
+ * @return comment element instance if the comment content is rightly
+ * parsed. if parse failed, returns null.
+ */
+ Element createElement(Document document, String data, boolean isJSPTag);
+
+ /**
+ * This method generates the source text of the end tag for the passed
+ * element. Do not generate comment prefix (&lt;!-- or &lt;%--) and suffix
+ * (--&gt; or --%&gt;). XMLGenerator uses this method to generate XML/HTML
+ * source for a comment element.
+ *
+ * @param element
+ * the comment element
+ * @return generated tag string
+ */
+ String generateEndTagContent(XMLElement element);
+
+ /**
+ * This method generates the source text of the start tag for the passed
+ * element. Do not generate comment prefix (&lt;!-- or &lt;%--) and suffix
+ * (--&gt; or --%&gt;). XMLGenerator uses this method to generate XML/HTML
+ * source for a comment element.
+ *
+ * @param element
+ * the comment element
+ * @return generated tag string
+ */
+ String generateStartTagContent(XMLElement element);
+
+ /**
+ *
+ * @param element
+ * the element
+ * @return boolean whether the element is comment element or not
+ */
+ boolean isCommentElement(XMLElement element);
+
+ /**
+ *
+ * @return boolean whether this element can have children or not
+ */
+ boolean isEmpty();
+
+ /**
+ * @return String
+ */
+ // String getElementPrefix();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/BasicCommentElementHandler.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/BasicCommentElementHandler.java
new file mode 100644
index 0000000000..98efac0f7d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/BasicCommentElementHandler.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.commentelement.impl;
+
+
+
+import org.eclipse.wst.xml.core.commentelement.CommentElementHandler;
+import org.eclipse.wst.xml.core.commentelement.util.CommentElementFactory;
+import org.eclipse.wst.xml.core.commentelement.util.TagScanner;
+import org.eclipse.wst.xml.core.document.XMLAttr;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLGenerator;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+
+/**
+ */
+class BasicCommentElementHandler implements CommentElementHandler {
+
+ private String elementName;
+ private boolean isEmpty;
+
+ public BasicCommentElementHandler(String elementName, boolean isEmpty) {
+ super();
+ this.elementName = elementName;
+ this.isEmpty = isEmpty;
+ }
+
+ /**
+ * @see com.ibm.sed.model.commentelement.CommentElementHandler#createElement(Document,
+ * String, boolean)
+ */
+ public Element createElement(Document document, String data, boolean isJSPTag) {
+ Element element = null;
+ String str = data.trim();
+ CommentElementFactory factory = new CommentElementFactory(document, isJSPTag, this);
+ if (str.charAt(0) == '/') { // end tag
+ TagScanner scanner = new TagScanner(str, 1); // skip '/'
+ String name = scanner.nextName();
+ if (name.equals(elementName)) {
+ element = factory.create(name, CommentElementFactory.IS_END);
+ }
+ } else { // start tag
+ TagScanner scanner = new TagScanner(str, 0);
+ String name = scanner.nextName();
+ if (name.equals(elementName)) {
+ element = factory.create(name, (isEmpty) ? CommentElementFactory.IS_EMPTY : CommentElementFactory.IS_START);
+ // set attributes
+ String attrName = scanner.nextName();
+ while (attrName != null) {
+ String attrValue = scanner.nextValue();
+ Attr attr = document.createAttribute(attrName);
+ if (attr != null) {
+ if (attrValue != null)
+ ((XMLAttr) attr).setValueSource(attrValue);
+ element.setAttributeNode(attr);
+ }
+ attrName = scanner.nextName();
+ }
+ }
+ }
+ return element;
+ }
+
+ /**
+ * @see com.ibm.sed.model.commentelement.CommentElementHandler#getEndTag(XMLElement)
+ */
+ public String generateEndTagContent(XMLElement element) {
+ if (isEmpty) {
+ return null;
+ }
+ XMLGenerator generator = element.getModel().getGenerator();
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append(" /"); //$NON-NLS-1$
+ String tagName = generator.generateTagName(element);
+ if (tagName != null) {
+ buffer.append(tagName);
+ }
+ buffer.append(' ');
+
+ return buffer.toString();
+ }
+
+ /**
+ * @see com.ibm.sed.model.commentelement.CommentElementHandler#getStartTag(XMLElement)
+ */
+ public String generateStartTagContent(XMLElement element) {
+ XMLGenerator generator = element.getModel().getGenerator();
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append(' ');
+ String tagName = generator.generateTagName(element);
+ if (tagName != null) {
+ buffer.append(tagName);
+ }
+
+ NamedNodeMap attributes = element.getAttributes();
+ int length = attributes.getLength();
+ for (int i = 0; i < length; i++) {
+ Attr attr = (Attr) attributes.item(i);
+ if (attr == null) {
+ continue;
+ }
+ buffer.append(' ');
+ String attrName = generator.generateAttrName(attr);
+ if (attrName != null) {
+ buffer.append(attrName);
+ }
+ String attrValue = generator.generateAttrValue(attr);
+ if (attrValue != null) {
+ // attr name only for HTML boolean and JSP
+ buffer.append('=');
+ buffer.append(attrValue);
+ }
+ }
+
+ buffer.append(' ');
+
+ return buffer.toString();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.model.commentelement.CommentElementHandler#isCommentElement(com.ibm.sed.model.xml.XMLElement)
+ */
+ public boolean isCommentElement(XMLElement element) {
+ return (element != null && element.getTagName().equals(elementName)) ? true : false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.model.commentelement.CommentElementHandler#isEmpty()
+ */
+ public boolean isEmpty() {
+ return isEmpty;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/CommentElementConfiguration.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/CommentElementConfiguration.java
new file mode 100644
index 0000000000..d4aac41461
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/CommentElementConfiguration.java
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.commentelement.impl;
+
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IPluginDescriptor;
+import org.eclipse.wst.xml.core.Logger;
+import org.eclipse.wst.xml.core.commentelement.CommentElementAdapter;
+import org.eclipse.wst.xml.core.commentelement.CommentElementHandler;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ */
+public class CommentElementConfiguration {
+ private Map fAttributes = null;
+ private boolean fCustom;
+ private IConfigurationElement fElement = null;
+
+ private boolean fEmpty;
+ private CommentElementHandler fHandler = null;
+ private String fID = null;
+ private boolean fJSPComment;
+ private String[] fPrefix = null;
+ private boolean fXMLComment;
+
+ CommentElementConfiguration() {
+ super();
+ }
+
+ CommentElementConfiguration(IConfigurationElement element) {
+ super();
+ fElement = element;
+ fCustom = (element.getName().equalsIgnoreCase("handler-custom")) ? true : false; //$NON-NLS-1$
+
+ fillAttributes(element);
+
+ fXMLComment = fJSPComment = false;
+ String commentType = getProperty("commenttype"); //$NON-NLS-1$
+ if (commentType.equalsIgnoreCase("xml")) { //$NON-NLS-1$
+ fXMLComment = true;
+ } else if (commentType.equalsIgnoreCase("jsp")) { //$NON-NLS-1$
+ fJSPComment = true;
+ } else if (commentType.equalsIgnoreCase("both")) { //$NON-NLS-1$
+ fXMLComment = fJSPComment = true;
+ }
+ String empty = getProperty("isempty"); //$NON-NLS-1$
+ fEmpty = (empty != null && !empty.equals("false")) ? true : false; //$NON-NLS-1$
+ }
+
+ public boolean acceptJSPComment() {
+ return fJSPComment;
+ }
+
+ public boolean acceptXMLComment() {
+ return fXMLComment;
+ }
+
+ public Element createElement(Document document, String data, boolean isJSPTag) {
+ XMLElement element = (XMLElement) getHandler().createElement(document, data, isJSPTag);
+ if (element != null) {
+ CommentElementAdapter adapter = (CommentElementAdapter) element.getAdapterFor(CommentElementAdapter.class);
+ if (adapter != null) {
+ adapter.setConfiguration(this);
+ }
+ }
+ return element;
+ }
+
+ private void fillAttributes(IConfigurationElement element) {
+ if (fAttributes == null) {
+ fAttributes = new HashMap();
+ } else {
+ fAttributes.clear();
+ }
+ String[] names = element.getAttributeNames();
+ if (names == null) {
+ return;
+ }
+ int length = names.length;
+ for (int i = 0; i < length; i++) {
+ String name = names[i];
+ fAttributes.put(name.toLowerCase(), element.getAttribute(name));
+ }
+ }
+
+ public CommentElementHandler getHandler() {
+ if (fHandler == null) {
+ if (fElement != null) {
+ try {
+ if (isCustom()) {
+ fHandler = (CommentElementHandler) fElement.createExecutableExtension("class"); //$NON-NLS-1$
+ } else {
+ String elementName = getProperty("elementname"); //$NON-NLS-1$
+ fHandler = new BasicCommentElementHandler(elementName, fEmpty);
+ }
+ // ((AbstractCommentElementHandler)fHandler).setElementPrefix(fElement.getAttribute("prefix"));
+ } catch (Exception e) {
+ // catch and log (and ignore) ANY exception created
+ // by executable extension.
+ Logger.logException(e);
+ fHandler = null;
+ }
+ }
+ if (fHandler == null) {
+ fHandler = new CommentElementHandler() {
+ public Element createElement(Document document, String data, boolean isJSPTag) {
+ return null;
+ }
+
+ public String generateEndTagContent(XMLElement element) {
+ return null;
+ }
+
+ public String generateStartTagContent(XMLElement element) {
+ return null;
+ }
+
+ public String getElementPrefix() {
+ return null;
+ }
+
+ public boolean isCommentElement(XMLElement element) {
+ return false;
+ }
+
+ public boolean isEmpty() {
+ return false;
+ }
+ };
+ }
+ }
+ return fHandler;
+ }
+
+ public String getHandlerID() {
+ if (fID == null) {
+ fID = getProperty("id"); //$NON-NLS-1$
+ if (fID == null) {
+ if (isCustom()) {
+ fID = getProperty("class"); //$NON-NLS-1$
+ } else {
+ StringBuffer buf = new StringBuffer();
+ buf.append(getHandlerPluginDescriptor().getUniqueIdentifier());
+ buf.append('.');
+ buf.append(getProperty("elementname")); //$NON-NLS-1$
+ fID = buf.toString();
+ }
+ }
+ }
+ return fID;
+ }
+
+ public IPluginDescriptor getHandlerPluginDescriptor() {
+ return fElement.getDeclaringExtension().getDeclaringPluginDescriptor();
+ }
+
+ public String[] getPrefix() {
+ if (fPrefix == null) {
+ if (fElement != null) {
+ if (isCustom()) { // custom
+ IConfigurationElement[] prefixes = fElement.getChildren("startwith"); //$NON-NLS-1$
+ if (prefixes != null) {
+ fPrefix = new String[prefixes.length];
+ for (int i = 0; i < prefixes.length; i++) {
+ fPrefix[i] = prefixes[i].getAttribute("prefix"); //$NON-NLS-1$
+ }
+ }
+ } else { // basic
+ String name = getProperty("elementname"); //$NON-NLS-1$
+ if (name != null) {
+ if (isEmpty()) {
+ fPrefix = new String[1];
+ fPrefix[0] = name;
+ } else {
+ fPrefix = new String[2];
+ fPrefix[0] = name;
+ fPrefix[1] = '/' + name;
+ }
+ }
+ }
+ }
+ }
+ if (fPrefix == null) {
+ fPrefix = new String[1];
+ fPrefix[0] = ""; //$NON-NLS-1$
+ }
+ return fPrefix;
+ }
+
+ public String getProperty(String name) {
+ return (fAttributes != null) ? (String) fAttributes.get(name) : null;
+ }
+
+ private boolean isCustom() {
+ return fCustom;
+ }
+
+ private boolean isEmpty() {
+ return fEmpty;
+ }
+
+ void setupCommentElement(XMLElement element) {
+ element.setCommentTag(true);
+ CommentElementAdapter adapter = new CommentElementAdapter(false, fHandler);
+ adapter.setConfiguration(this);
+ element.addAdapter(adapter);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/CommentElementRegistry.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/CommentElementRegistry.java
new file mode 100644
index 0000000000..3245298479
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/impl/CommentElementRegistry.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.commentelement.impl;
+
+
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IPluginRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.xml.core.commentelement.CommentElementHandler;
+import org.eclipse.wst.xml.core.document.XMLElement;
+
+
+/**
+ */
+public class CommentElementRegistry {
+
+ private static CommentElementRegistry fInstance = null;
+
+ public synchronized static CommentElementRegistry getInstance() {
+ if (fInstance == null) {
+ fInstance = new CommentElementRegistry();
+ }
+ return fInstance;
+ }
+
+ private String EXTENSION_POINT_ID = "commentElementHandler"; //$NON-NLS-1$
+ private CommentElementConfiguration[] fConfigurations = null;
+
+ private String PLUGIN_ID = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+
+ /**
+ * Constructor for CommentElementRegistry.
+ */
+ private CommentElementRegistry() {
+ super();
+ }
+
+ public CommentElementConfiguration[] getConfigurations() {
+ if (fConfigurations == null) {
+ IPluginRegistry pluginRegistry = Platform.getPluginRegistry();
+ IExtensionPoint point = pluginRegistry.getExtensionPoint(PLUGIN_ID, EXTENSION_POINT_ID);
+ if (point != null) {
+ IConfigurationElement[] elements = point.getConfigurationElements();
+ fConfigurations = new CommentElementConfiguration[elements.length];
+ for (int i = 0; i < elements.length; i++) {
+ fConfigurations[i] = new CommentElementConfiguration(elements[i]);
+ }
+ }
+ if (fConfigurations == null) {
+ fConfigurations = new CommentElementConfiguration[0];
+ }
+ }
+ return fConfigurations;
+ }
+
+ public boolean setupCommentElement(XMLElement element) {
+ CommentElementConfiguration configurations[] = getConfigurations();
+ int length = configurations.length;
+ for (int i = 0; i < length; i++) {
+ CommentElementConfiguration conf = configurations[i];
+ boolean isJSP = element.isJSPTag();
+ if (isJSP && conf.acceptJSPComment() || !isJSP && conf.acceptXMLComment()) {
+ CommentElementHandler handler = conf.getHandler();
+ if (handler.isCommentElement(element)) {
+ conf.setupCommentElement(element);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/util/CommentElementFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/util/CommentElementFactory.java
new file mode 100644
index 0000000000..2ae4c84734
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/util/CommentElementFactory.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.commentelement.util;
+
+
+
+import org.eclipse.wst.xml.core.commentelement.CommentElementAdapter;
+import org.eclipse.wst.xml.core.commentelement.CommentElementHandler;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ */
+public class CommentElementFactory {
+ public static final int IS_EMPTY = 4866;
+ public static final int IS_END = 1808;
+
+ public static final int IS_START = 28011;
+
+ private Document fDocument;
+ private CommentElementHandler fHandler;
+ private boolean fJSPTag;
+
+ /**
+ * Constructor for CommentElementFactory.
+ */
+ private CommentElementFactory() {
+ super();
+ }
+
+ public CommentElementFactory(Document document, boolean isJSPTag, CommentElementHandler handler) {
+ super();
+ fDocument = document;
+ fJSPTag = isJSPTag;
+ fHandler = handler;
+ }
+
+ public Element create(String name, int nodeType) {
+ XMLElement element = (XMLElement) fDocument.createElement(name);
+ if (element == null)
+ return null;
+ element.setCommentTag(true);
+ if (nodeType == IS_EMPTY) {
+ element.setEmptyTag(true);
+ }
+ element.setJSPTag(fJSPTag);
+
+ CommentElementAdapter adapter = new CommentElementAdapter((nodeType == IS_END), fHandler);
+ element.addAdapter(adapter);
+
+ return element;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/util/TagScanner.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/util/TagScanner.java
new file mode 100644
index 0000000000..a74fe0bb77
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/commentelement/util/TagScanner.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.commentelement.util;
+
+
+
+/**
+ */
+public class TagScanner {
+
+ /**
+ */
+ private static boolean isEqual(char c) {
+ return (c == '=');
+ }
+
+ /**
+ */
+ private static boolean isQuote(char c) {
+ return (c == '"' || c == '\'');
+ }
+
+ /**
+ */
+ private static boolean isSpace(char c) {
+ return Character.isWhitespace(c);
+ }
+
+ private int length = 0;
+ private int memOffset = 0;
+ private int offset = 0;
+ private boolean oneLine = false;
+
+ private String tag = null;
+
+ /**
+ */
+ public TagScanner(String tag, int offset) {
+ super();
+
+ this.tag = tag;
+ this.offset = offset;
+ this.memOffset = -1;
+ if (tag != null)
+ this.length = tag.length();
+ }
+
+ /**
+ */
+ public TagScanner(String tag, int offset, boolean oneLine) {
+ this(tag, offset);
+
+ this.oneLine = oneLine;
+ }
+
+ /**
+ */
+ public int getNextOffset() {
+ int i;
+ char c;
+ for (i = offset; i < length; i++) {
+ c = tag.charAt(i);
+ if (isEnd(c))
+ break;
+ if (isQuote(c)) {
+ i++;
+ break;
+ }
+ if (!isSpace(c) && !isEqual(c))
+ break;
+ }
+ return i;
+ }
+
+ /**
+ */
+ public int getOffset() {
+ return this.memOffset;
+ }
+
+ /**
+ */
+ private final boolean isEnd(char c) {
+ return (this.oneLine && (c == '\r' || c == '\n'));
+ }
+
+ /**
+ */
+ public boolean isNewLine() {
+ if (oneLine)
+ return false;
+ char c;
+ for (int i = memOffset - 1; 0 <= i; i--) {
+ c = tag.charAt(i);
+ if (c == '\r' || c == '\n')
+ return true;
+ if (!isSpace(c))
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ */
+ private char nextChar() {
+ for (; this.offset < this.length; this.offset++) {
+ char c = this.tag.charAt(this.offset);
+ if (isEnd(c))
+ break;
+ if (!isSpace(c))
+ return c;
+ }
+ return 0;
+ }
+
+ /**
+ */
+ public String nextName() {
+ if (this.tag == null)
+ return null;
+ if (this.offset >= this.length)
+ return null;
+
+ if (nextChar() == 0)
+ return null;
+
+ int nameOffset = this.offset;
+ for (; this.offset < this.length; this.offset++) {
+ char c = this.tag.charAt(this.offset);
+ if (isEnd(c) || isSpace(c))
+ break;
+ if (isEqual(c) && this.offset > nameOffset)
+ break;
+ }
+ if (this.offset == nameOffset)
+ return null;
+
+ this.memOffset = nameOffset;
+ return this.tag.substring(nameOffset, this.offset);
+ }
+
+ /**
+ */
+ public String nextValue() {
+ if (this.tag == null)
+ return null;
+ if (this.offset >= this.length)
+ return null;
+
+ char seperator = nextChar();
+ if (!isEqual(seperator))
+ return null;
+ this.offset++; // skip '='
+ char quote = nextChar();
+ if (quote == 0)
+ return null;
+ if (isQuote(quote))
+ this.offset++;
+ else
+ quote = 0;
+
+ int valueOffset = this.offset;
+ for (; this.offset < this.length; this.offset++) {
+ char c = this.tag.charAt(this.offset);
+ if (isEnd(c)) {
+ quote = 0;
+ break;
+ }
+ if (quote == 0) {
+ if (isSpace(c))
+ break;
+ } else {
+ if (c == quote)
+ break;
+ }
+ }
+ int valueEnd = this.offset;
+ if (quote != 0 && this.offset < this.length)
+ this.offset++;
+ if (valueEnd == valueOffset)
+ return null;
+
+ this.memOffset = valueOffset;
+ return this.tag.substring(valueOffset, valueEnd);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/ContentDescriberForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/ContentDescriberForXML.java
new file mode 100644
index 0000000000..a78089e004
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/ContentDescriberForXML.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.contenttype;
+
+import org.eclipse.core.runtime.content.ITextContentDescriber;
+import org.eclipse.wst.common.encoding.AbstractContentDescriber;
+import org.eclipse.wst.common.encoding.IResourceCharsetDetector;
+
+
+public class ContentDescriberForXML extends AbstractContentDescriber implements ITextContentDescriber {
+ protected IResourceCharsetDetector getDetector() {
+ return new XMLResourceEncodingDetector();
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLHeadTokenizer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLHeadTokenizer.java
new file mode 100644
index 0000000000..35ca57cf57
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLHeadTokenizer.java
@@ -0,0 +1,1226 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+/* The following code was generated by JFlex 1.2.2 on 4/6/04 11:13 PM */
+
+/*nlsXXX*/
+package org.eclipse.wst.xml.core.contenttype;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.wst.common.encoding.IntStack;
+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;
+import org.eclipse.wst.xml.core.internal.contenttype.HeadParserToken;
+
+
+
+/**
+ * This class is a scanner generated by <a
+ * href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex </a> 1.2.2
+ * on 4/6/04 11:13 PM from the specification file
+ * <tt>file:/D:/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizer.jflex</tt>
+ */
+public class XMLHeadTokenizer {
+
+ /** this character denotes the end of file */
+ final public static int YYEOF = -1;
+
+ /** lexical states */
+ final public static int YYINITIAL = 0;
+ final public static int UnDelimitedString = 10;
+ final public static int DQ_STRING = 6;
+ final public static int SQ_STRING = 8;
+ final public static int ST_XMLDecl = 2;
+ final public static int QuotedAttributeValue = 4;
+
+ /**
+ * YY_LEXSTATE[l] is the state in the DFA for the lexical state l
+ * YY_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
+ * beginning of a line l is of the form l = 2*k, k a non negative integer
+ */
+ private final static int YY_LEXSTATE[] = {0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6};
+
+ /**
+ * Translates characters to character classes
+ */
+ final private static String yycmap_packed = "\11\0\1\6\1\7\2\0\1\11\22\0\1\6\1\0\1\27\2\0" + "\1\31\1\0\1\30\24\0\1\12\1\10\1\26\1\13\3\0\1\21" + "\1\23\1\17\1\0\1\25\1\0\1\24\2\0\1\16\1\15\1\20" + "\1\22\10\0\1\14\12\0\1\21\1\23\1\17\1\0\1\25\1\0" + "\1\24\2\0\1\16\1\15\1\20\1\22\10\0\1\14\102\0\1\4" + "\3\0\1\5\17\0\1\3\16\0\1\1\20\0\1\3\16\0\1\1" + "\1\2\170\0\1\2\ufe87\0"; //$NON-NLS-2$//$NON-NLS-3$
+
+ /**
+ * Translates characters to character classes
+ */
+ final private static char[] yycmap = yy_unpack_cmap(yycmap_packed);
+
+
+ /* error codes */
+ final private static int YY_UNKNOWN_ERROR = 0;
+ final private static int YY_ILLEGAL_STATE = 1;
+ final private static int YY_NO_MATCH = 2;
+ final private static int YY_PUSHBACK_2BIG = 3;
+
+ /* error messages for the codes above */
+ final private static String YY_ERROR_MSG[] = {"Unkown internal scanner error", "Internal error: unknown state", "Error: could not match input", "Error: pushback value was too large"};
+
+ /** the input device */
+ private java.io.Reader yy_reader;
+
+ /** the current state of the DFA */
+ private int yy_state;
+
+ /** the current lexical state */
+ private int yy_lexical_state = YYINITIAL;
+
+ /**
+ * this buffer contains the current text to be matched and is the source
+ * of the yytext() string
+ */
+ private char yy_buffer[] = new char[16384];
+
+ /** the textposition at the last accepting state */
+ private int yy_markedPos;
+
+ /** the textposition at the last state to be included in yytext */
+ private int yy_pushbackPos;
+
+ /** the current text position in the buffer */
+ private int yy_currentPos;
+
+ /** startRead marks the beginning of the yytext() string in the buffer */
+ private int yy_startRead;
+
+ /**
+ * endRead marks the last character in the buffer, that has been read from
+ * input
+ */
+ private int yy_endRead;
+
+ /** number of newlines encountered up to the start of the matched text */
+ // future_TODO: remove from skeleton
+ // private int yyline;
+ /** the number of characters up to the start of the matched text */
+ private int yychar;
+
+ /**
+ * the number of characters from the last newline up to the start of the
+ * matched text
+ */
+ // future_TODO: remove from skeleton
+ //private int yycolumn;
+ /**
+ * yy_atBOL == true <=>the scanner is currently at the beginning of a line
+ */
+ private boolean yy_atBOL;
+
+ /** yy_atEOF == true <=>the scanner has returned a value for EOF */
+ private boolean yy_atEOF;
+
+ /** denotes if the user-EOF-code has already been executed */
+ private boolean yy_eof_done;
+
+ /* user code: */
+
+
+ private boolean hasMore = true;
+ private final static int MAX_TO_SCAN = 1000;
+ StringBuffer string = new StringBuffer();
+ // state stack for easier state handling
+ private IntStack fStateStack = new IntStack();
+ private String valueText = null;
+
+
+ public XMLHeadTokenizer() {
+ super();
+ }
+
+ public void reset(Reader in) {
+ /* the input device */
+ yy_reader = in;
+
+ /* the current state of the DFA */
+ yy_state = 0;
+
+ /* the current lexical state */
+ yy_lexical_state = YYINITIAL;
+
+ /*
+ * this buffer contains the current text to be matched and is the
+ * source of the yytext() string
+ */
+ java.util.Arrays.fill(yy_buffer, (char) 0);
+
+ /* the textposition at the last accepting state */
+ yy_markedPos = 0;
+
+ /* the textposition at the last state to be included in yytext */
+ yy_pushbackPos = 0;
+
+ /* the current text position in the buffer */
+ yy_currentPos = 0;
+
+ /* startRead marks the beginning of the yytext() string in the buffer */
+ yy_startRead = 0;
+
+ /**
+ * endRead marks the last character in the buffer, that has been read
+ * from input
+ */
+ yy_endRead = 0;
+
+ /* number of newlines encountered up to the start of the matched text */
+ // future_TODO: remove from skeleton
+ //yyline = 0;
+ /* the number of characters up to the start of the matched text */
+ yychar = 0;
+
+ /**
+ * the number of characters from the last newline up to the start of
+ * the matched text
+ */
+ // future_TODO: remove from skeleton
+ //yycolumn = 0;
+ /**
+ * yy_atBOL == true <=>the scanner is currently at the beginning of a
+ * line
+ */
+ yy_atBOL = false;
+
+ /* yy_atEOF == true <=> the scanner has returned a value for EOF */
+ yy_atEOF = false;
+
+ /* denotes if the user-EOF-code has already been executed */
+ yy_eof_done = false;
+
+
+ fStateStack.clear();
+
+ hasMore = true;
+
+ // its a little wasteful to "throw away" first char array generated
+ // by class init (via auto generated code), but we really do want
+ // a small buffer for our head parsers.
+ if (yy_buffer.length != MAX_TO_SCAN) {
+ yy_buffer = new char[MAX_TO_SCAN];
+ }
+
+
+ }
+
+
+ public final HeadParserToken getNextToken() throws IOException {
+ String context = null;
+ context = primGetNextToken();
+ HeadParserToken result = null;
+ if (valueText != null) {
+ result = createToken(context, yychar, valueText);
+ valueText = null;
+ } else {
+ result = createToken(context, yychar, yytext());
+ }
+ return result;
+ }
+
+ public final boolean hasMoreTokens() {
+ return hasMore && yychar < MAX_TO_SCAN;
+ }
+
+ private void pushCurrentState() {
+ fStateStack.push(yystate());
+
+ }
+
+ private void popState() {
+ yybegin(fStateStack.pop());
+ }
+
+ private HeadParserToken createToken(String context, int start, String text) {
+ return new HeadParserToken(context, start, text);
+ }
+
+
+
+ /**
+ * Creates a new scanner There is also a java.io.InputStream version of
+ * this constructor.
+ *
+ * @param in
+ * the java.io.Reader to read input from.
+ */
+ public XMLHeadTokenizer(java.io.Reader in) {
+ this.yy_reader = in;
+ }
+
+ /**
+ * Creates a new scanner. There is also java.io.Reader version of this
+ * constructor.
+ *
+ * @param in
+ * the java.io.Inputstream to read input from.
+ */
+ public XMLHeadTokenizer(java.io.InputStream in) {
+ this(new java.io.InputStreamReader(in));
+ }
+
+ /**
+ * Unpacks the compressed character translation table.
+ *
+ * @param packed
+ * the packed character translation table
+ * @return the unpacked character translation table
+ */
+ private static char[] yy_unpack_cmap(String packed) {
+ char[] map = new char[0x10000];
+ int i = 0; /* index in packed string */
+ int j = 0; /* index in unpacked array */
+ while (i < 128) {
+ int count = packed.charAt(i++);
+ char value = packed.charAt(i++);
+ do
+ map[j++] = value;
+ while (--count > 0);
+ }
+ return map;
+ }
+
+
+ /**
+ * Gets the next input character.
+ *
+ * @return the next character of the input stream, EOF if the end of the
+ * stream is reached.
+ * @exception IOException
+ * if any I/O-Error occurs
+ */
+ private int yy_advance() throws java.io.IOException {
+
+ /* standard case */
+ if (yy_currentPos < yy_endRead)
+ return yy_buffer[yy_currentPos++];
+
+ /* if the eof is reached, we don't need to work hard */
+ if (yy_atEOF)
+ return YYEOF;
+
+ /* otherwise: need to refill the buffer */
+
+ /* first: make room (if you can) */
+ if (yy_startRead > 0) {
+ System.arraycopy(yy_buffer, yy_startRead, yy_buffer, 0, yy_endRead - yy_startRead);
+
+ /* translate stored positions */
+ yy_endRead -= yy_startRead;
+ yy_currentPos -= yy_startRead;
+ yy_markedPos -= yy_startRead;
+ yy_pushbackPos -= yy_startRead;
+ yy_startRead = 0;
+ }
+
+ /* is the buffer big enough? */
+ if (yy_currentPos >= yy_buffer.length) {
+ /* if not: blow it up */
+ char newBuffer[] = new char[yy_currentPos * 2];
+ System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+ yy_buffer = newBuffer;
+ }
+
+ /* finally: fill the buffer with new input */
+ int numRead = yy_reader.read(yy_buffer, yy_endRead, yy_buffer.length - yy_endRead);
+
+ if (numRead == -1)
+ return YYEOF;
+
+ yy_endRead += numRead;
+
+ return yy_buffer[yy_currentPos++];
+ }
+
+
+ /**
+ * Closes the input stream.
+ */
+ final public void yyclose() throws java.io.IOException {
+ yy_atEOF = true; /* indicate end of file */
+ yy_endRead = yy_startRead; /* invalidate buffer */
+ yy_reader.close();
+ }
+
+
+ /**
+ * Returns the current lexical state.
+ */
+ final public int yystate() {
+ return yy_lexical_state;
+ }
+
+ /**
+ * Enters a new lexical state
+ *
+ * @param newState
+ * the new lexical state
+ */
+ final public void yybegin(int newState) {
+ yy_lexical_state = newState;
+ }
+
+
+ /**
+ * Returns the text matched by the current regular expression.
+ */
+ final public String yytext() {
+ return new String(yy_buffer, yy_startRead, yy_markedPos - yy_startRead);
+ }
+
+ /**
+ * Returns the length of the matched text region.
+ */
+ final public int yylength() {
+ return yy_markedPos - yy_startRead;
+ }
+
+
+ /**
+ * Reports an error that occured while scanning.
+ *
+ * @param errorCode
+ * the code of the errormessage to display
+ */
+ private void yy_ScanError(int errorCode) {
+ try {
+ System.out.println(YY_ERROR_MSG[errorCode]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println(YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+ }
+
+ // System.exit(1);
+ }
+
+
+ /**
+ * Pushes the specified amount of characters back into the input stream.
+ *
+ * They will be read again by then next call of the scanning method
+ *
+ * @param number
+ * the number of characters to be read again. This number must
+ * not be greater than yylength()!
+ */
+ private void yypushback(int number) {
+ if (number > yylength())
+ yy_ScanError(YY_PUSHBACK_2BIG);
+
+ yy_markedPos -= number;
+ }
+
+
+ /**
+ * Contains user EOF-code, which will be executed exactly once, when the
+ * end of file is reached
+ */
+ private void yy_do_eof() {
+ if (!yy_eof_done) {
+ yy_eof_done = true;
+ hasMore = false;
+
+ }
+ }
+
+
+ /**
+ * Resumes scanning until the next regular expression is matched, the end
+ * of input is encountered or an I/O-Error occurs.
+ *
+ * @return the next token
+ * @exception IOException
+ * if any I/O-Error occurs
+ */
+ public String primGetNextToken() throws java.io.IOException {
+ int yy_input;
+ int yy_action;
+
+
+ while (true) {
+
+ yychar += yylength();
+
+ yy_atBOL = yy_markedPos <= 0 || yy_buffer[yy_markedPos - 1] == '\n';
+ if (!yy_atBOL && yy_buffer[yy_markedPos - 1] == '\r') {
+ yy_atBOL = yy_advance() != '\n';
+ if (!yy_atEOF)
+ yy_currentPos--;
+ }
+
+ yy_action = -1;
+
+ yy_currentPos = yy_startRead = yy_markedPos;
+
+ if (yy_atBOL)
+ yy_state = YY_LEXSTATE[yy_lexical_state + 1];
+ else
+ yy_state = YY_LEXSTATE[yy_lexical_state];
+
+
+ yy_forAction : {
+ while (true) {
+
+ yy_input = yy_advance();
+
+ if (yy_input == YYEOF)
+ break yy_forAction;
+
+ yy_input = yycmap[yy_input];
+
+ boolean yy_isFinal = false;
+ boolean yy_noLookAhead = false;
+
+ yy_forNext : {
+ switch (yy_state) {
+ case 0 :
+ switch (yy_input) {
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 7;
+ break yy_forNext;
+ }
+
+ case 1 :
+ switch (yy_input) {
+ case 1 :
+ yy_isFinal = true;
+ yy_state = 8;
+ break yy_forNext;
+ case 2 :
+ yy_isFinal = true;
+ yy_state = 9;
+ break yy_forNext;
+ case 3 :
+ yy_isFinal = true;
+ yy_state = 10;
+ break yy_forNext;
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 11;
+ break yy_forNext;
+ case 10 :
+ yy_isFinal = true;
+ yy_state = 12;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 7;
+ break yy_forNext;
+ }
+
+ case 2 :
+ switch (yy_input) {
+ case 11 :
+ yy_isFinal = true;
+ yy_state = 13;
+ break yy_forNext;
+ case 15 :
+ yy_isFinal = true;
+ yy_state = 14;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 7;
+ break yy_forNext;
+ }
+
+ case 3 :
+ switch (yy_input) {
+ case 6 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 16;
+ break yy_forNext;
+ case 7 :
+ yy_isFinal = true;
+ yy_state = 17;
+ break yy_forNext;
+ case 23 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 18;
+ break yy_forNext;
+ case 24 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 19;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 15;
+ break yy_forNext;
+ }
+
+ case 4 :
+ switch (yy_input) {
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 21;
+ break yy_forNext;
+ case 11 :
+ yy_isFinal = true;
+ yy_state = 22;
+ break yy_forNext;
+ case 23 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 23;
+ break yy_forNext;
+ case 24 :
+ yy_isFinal = true;
+ yy_state = 24;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 20;
+ break yy_forNext;
+ }
+
+ case 5 :
+ switch (yy_input) {
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 21;
+ break yy_forNext;
+ case 24 :
+ yy_isFinal = true;
+ yy_state = 25;
+ break yy_forNext;
+ case 25 :
+ yy_isFinal = true;
+ yy_state = 26;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 20;
+ break yy_forNext;
+ }
+
+ case 6 :
+ switch (yy_input) {
+ case 11 :
+ yy_isFinal = true;
+ yy_state = 26;
+ break yy_forNext;
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 27;
+ break yy_forNext;
+ case 23 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 28;
+ break yy_forNext;
+ case 24 :
+ yy_isFinal = true;
+ yy_state = 29;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 20;
+ break yy_forNext;
+ }
+
+ case 8 :
+ switch (yy_input) {
+ case 2 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 30;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 9 :
+ switch (yy_input) {
+ case 1 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 31;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 10 :
+ switch (yy_input) {
+ case 4 :
+ yy_state = 32;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 11 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_state = 33;
+ break yy_forNext;
+ case 10 :
+ yy_state = 34;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 12 :
+ switch (yy_input) {
+ case 11 :
+ yy_state = 35;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 13 :
+ switch (yy_input) {
+ case 22 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 36;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 14 :
+ switch (yy_input) {
+ case 16 :
+ yy_state = 37;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 16 :
+ switch (yy_input) {
+ case 6 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 16;
+ break yy_forNext;
+ case 7 :
+ yy_state = 38;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 15;
+ break yy_forNext;
+ }
+
+ case 17 :
+ switch (yy_input) {
+ case 6 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 16;
+ break yy_forNext;
+ case 7 :
+ yy_state = 38;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 15;
+ break yy_forNext;
+ }
+
+ case 22 :
+ switch (yy_input) {
+ case 22 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 39;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 24 :
+ switch (yy_input) {
+ case 10 :
+ yy_state = 40;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 25 :
+ switch (yy_input) {
+ case 10 :
+ yy_state = 40;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 26 :
+ switch (yy_input) {
+ case 22 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 41;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 29 :
+ switch (yy_input) {
+ case 10 :
+ yy_state = 40;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 32 :
+ switch (yy_input) {
+ case 5 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 42;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 33 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_state = 33;
+ break yy_forNext;
+ case 10 :
+ yy_state = 34;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 34 :
+ switch (yy_input) {
+ case 11 :
+ yy_state = 35;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 35 :
+ switch (yy_input) {
+ case 12 :
+ yy_state = 43;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 37 :
+ switch (yy_input) {
+ case 17 :
+ yy_state = 44;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 38 :
+ switch (yy_input) {
+ case 6 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 16;
+ break yy_forNext;
+ case 7 :
+ yy_state = 38;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 15;
+ break yy_forNext;
+ }
+
+ case 40 :
+ switch (yy_input) {
+ case 24 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 21;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 43 :
+ switch (yy_input) {
+ case 13 :
+ yy_state = 45;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 44 :
+ switch (yy_input) {
+ case 18 :
+ yy_state = 46;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 45 :
+ switch (yy_input) {
+ case 14 :
+ yy_state = 47;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 46 :
+ switch (yy_input) {
+ case 19 :
+ yy_state = 48;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 47 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 49;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 48 :
+ switch (yy_input) {
+ case 20 :
+ yy_state = 50;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 49 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 49;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 50 :
+ switch (yy_input) {
+ case 16 :
+ yy_state = 51;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 51 :
+ switch (yy_input) {
+ case 21 :
+ yy_state = 52;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 52 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_state = 52;
+ break yy_forNext;
+ case 8 :
+ yy_isFinal = true;
+ yy_state = 53;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 53 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 53;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ default :
+ yy_ScanError(YY_ILLEGAL_STATE);
+ break;
+ }
+ }
+
+ if (yy_isFinal) {
+ yy_action = yy_state;
+ yy_markedPos = yy_currentPos;
+ if (yy_noLookAhead)
+ break yy_forAction;
+ }
+
+ }
+ }
+
+
+ switch (yy_action) {
+
+ case 25 : {
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.StringValue;
+ }
+ case 55 :
+ break;
+ case 21 : {
+ yypushback(1);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.InvalidTerminatedStringValue;
+ }
+ case 56 :
+ break;
+ case 15 :
+ case 16 : {
+ yypushback(1);
+ yybegin(UnDelimitedString);
+ string.setLength(0);
+ }
+ case 57 :
+ break;
+ case 28 :
+ case 29 : {
+ yypushback(1);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;
+ }
+ case 58 :
+ break;
+ case 39 : {
+ yypushback(2);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.InvalidTerminatedStringValue;
+ }
+ case 59 :
+ break;
+ case 41 : {
+ yypushback(2);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.InvalidTerminatedStringValue;
+ }
+ case 60 :
+ break;
+ case 7 :
+ case 8 :
+ case 9 :
+ case 10 :
+ case 11 :
+ case 12 :
+ case 13 :
+ case 14 :
+ case 17 : {
+ if (yychar > MAX_TO_SCAN) {
+ hasMore = false;
+ return EncodingParserConstants.MAX_CHARS_REACHED;
+ }
+ }
+ case 61 :
+ break;
+ case 30 : {
+ if (yychar == 0) {
+ hasMore = false;
+ return EncodingParserConstants.UTF16BE;
+ }
+ }
+ case 62 :
+ break;
+ case 31 : {
+ if (yychar == 0) {
+ hasMore = false;
+ return EncodingParserConstants.UTF16LE;
+ }
+ }
+ case 63 :
+ break;
+ case 42 : {
+ if (yychar == 0) {
+ hasMore = false;
+ return EncodingParserConstants.UTF83ByteBOM;
+ }
+ }
+ case 64 :
+ break;
+ case 49 : {
+ if (yychar == 0) {
+ yybegin(ST_XMLDecl);
+ return XMLHeadTokenizerConstants.XMLDeclStart;
+ }
+ }
+ case 65 :
+ break;
+ case 36 : {
+ yybegin(YYINITIAL);
+ hasMore = false;
+ return XMLHeadTokenizerConstants.XMLDeclEnd;
+ }
+ case 66 :
+ break;
+ case 53 : {
+ pushCurrentState();
+ yybegin(QuotedAttributeValue);
+ return XMLHeadTokenizerConstants.XMLDelEncoding;
+ }
+ case 67 :
+ break;
+ case 23 : {
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.StringValue;
+ }
+ case 68 :
+ break;
+ case 20 :
+ case 22 :
+ case 24 :
+ case 26 : {
+ string.append(yytext());
+ }
+ case 69 :
+ break;
+ case 19 : {
+ yybegin(SQ_STRING);
+ string.setLength(0);
+ }
+ case 70 :
+ break;
+ case 18 : {
+ yybegin(DQ_STRING);
+ string.setLength(0);
+ }
+ case 71 :
+ break;
+ case 27 : {
+ yypushback(1);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.UnDelimitedStringValue;
+ }
+ case 72 :
+ break;
+ default :
+ if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+ yy_atEOF = true;
+ yy_do_eof();
+ {
+ hasMore = false;
+ return EncodingParserConstants.EOF;
+ }
+ } else {
+ yy_ScanError(YY_NO_MATCH);
+ }
+ }
+ }
+ }
+
+ /**
+ * Runs the scanner on input files.
+ *
+ * This main method is the debugging routine for the scanner. It prints
+ * each returned token to System.out until the end of file is reached, or
+ * an error occured.
+ *
+ * @param argv
+ * the command line, contains the filenames to run the scanner
+ * on.
+ */
+ public static void main(String argv[]) {
+ for (int i = 0; i < argv.length; i++) {
+ XMLHeadTokenizer scanner = null;
+ try {
+ scanner = new XMLHeadTokenizer(new java.io.FileReader(argv[i]));
+ } catch (java.io.FileNotFoundException e) {
+ System.out.println("File not found : \"" + argv[i] + "\"");
+ System.exit(1);
+ }
+ // catch (java.io.IOException e) {
+ // System.out.println("Error opening file \"" + argv[i] + "\"");
+ // System.exit(1);
+ // }
+ catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println("Usage : java XMLHeadTokenizer <inputfile>");
+ System.exit(1);
+ }
+
+ try {
+ do {
+ System.out.println(scanner.primGetNextToken());
+ } while (!scanner.yy_atEOF);
+
+ } catch (java.io.IOException e) {
+ System.out.println("An I/O error occured while scanning :");
+ System.out.println(e);
+ System.exit(1);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ }
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLHeadTokenizerConstants.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLHeadTokenizerConstants.java
new file mode 100644
index 0000000000..1153d5fdfa
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLHeadTokenizerConstants.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.contenttype;
+
+import org.eclipse.wst.common.encoding.EncodingParserConstants;;
+
+public interface XMLHeadTokenizerConstants extends EncodingParserConstants {
+
+ final String XMLDeclEnd = "XMLDeclEnd"; //$NON-NLS-1$
+ final String XMLDeclStart = "XMLDeclStart"; //$NON-NLS-1$
+ final String XMLDelEncoding = "XMLDelEncoding"; //$NON-NLS-1$
+ // final String XMLDeclVersion = "XMLDeclVersion";
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLResourceEncodingDetector.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLResourceEncodingDetector.java
new file mode 100644
index 0000000000..0d9d0c75d1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/contenttype/XMLResourceEncodingDetector.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.contenttype;
+
+import java.io.IOException;
+
+import org.eclipse.wst.common.encoding.AbstractResourceEncodingDetector;
+import org.eclipse.wst.common.encoding.EncodingMemento;
+import org.eclipse.wst.common.encoding.EncodingParserConstants;
+import org.eclipse.wst.common.encoding.IResourceCharsetDetector;
+import org.eclipse.wst.xml.core.internal.contenttype.HeadParserToken;
+
+
+public class XMLResourceEncodingDetector extends AbstractResourceEncodingDetector implements IResourceCharsetDetector {
+ private XMLHeadTokenizer fTokenizer;
+
+ private boolean canHandleAsUnicodeStream(String tokenType) {
+ boolean canHandleAsUnicodeStream = false;
+ if (tokenType == EncodingParserConstants.UTF83ByteBOM) {
+ canHandleAsUnicodeStream = true;
+ String enc = "UTF-8"; //$NON-NLS-1$
+ createEncodingMemento(enc, EncodingMemento.DETECTED_STANDARD_UNICODE_BYTES);
+ fEncodingMemento.setUTF83ByteBOMUsed(true);
+ }
+
+ else if (tokenType == EncodingParserConstants.UTF16BE) {
+ canHandleAsUnicodeStream = true;
+ String enc = "UTF-16BE"; //$NON-NLS-1$
+ createEncodingMemento(enc, EncodingMemento.DETECTED_STANDARD_UNICODE_BYTES);
+ } else if (tokenType == EncodingParserConstants.UTF16LE) {
+ canHandleAsUnicodeStream = true;
+ String enc = "UTF-16"; //$NON-NLS-1$
+ createEncodingMemento(enc, EncodingMemento.DETECTED_STANDARD_UNICODE_BYTES);
+ }
+ return canHandleAsUnicodeStream;
+ }
+
+ public String getSpecDefaultEncoding() {
+ // by default, UTF-8 as per XML spec
+ final String enc = "UTF-8"; //$NON-NLS-1$
+ return enc;
+ }
+
+ /**
+ * @return Returns the tokenizer.
+ */
+ private XMLHeadTokenizer getTokenizer() {
+ // TODO: need to work on 'reset' in tokenizer, so new instance isn't
+ // always needed
+ //if (fTokenizer == null) {
+ fTokenizer = new XMLHeadTokenizer();
+ //}
+ return fTokenizer;
+ }
+
+ private boolean isLegalString(String valueTokenType) {
+ if (valueTokenType == null)
+ return false;
+ else
+ return valueTokenType.equals(EncodingParserConstants.StringValue) || valueTokenType.equals(EncodingParserConstants.UnDelimitedStringValue) || valueTokenType.equals(EncodingParserConstants.InvalidTerminatedStringValue) || valueTokenType.equals(EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue);
+ }
+
+ protected void parseInput() throws IOException {
+ XMLHeadTokenizer tokenizer = getTokenizer();
+ tokenizer.reset(fReader);
+ HeadParserToken token = null;
+ String tokenType = null;
+ do {
+ token = tokenizer.getNextToken();
+ tokenType = token.getType();
+ if (canHandleAsUnicodeStream(tokenType)) {
+ // side effect of canHandle is to create appropriate memento
+ } else {
+ if (tokenType == XMLHeadTokenizerConstants.XMLDelEncoding) {
+ if (tokenizer.hasMoreTokens()) {
+ token = tokenizer.getNextToken();
+ tokenType = token.getType();
+ if (isLegalString(tokenType)) {
+ String enc = token.getText();
+ if (enc != null && enc.length() > 0) {
+ createEncodingMemento(enc, EncodingMemento.FOUND_ENCODING_IN_CONTENT);
+ }
+
+ }
+ }
+ }
+ }
+ } while (tokenizer.hasMoreTokens());
+
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/DocumentLoaderForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/DocumentLoaderForXML.java
new file mode 100644
index 0000000000..0561e4c0f2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/DocumentLoaderForXML.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.common.encoding.CodedReaderCreator;
+import org.eclipse.wst.common.encoding.EncodingMemento;
+import org.eclipse.wst.common.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.document.IDocumentLoaderForFileBuffers;
+import org.eclipse.wst.sse.core.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.document.StructuredDocumentLoader;
+import org.eclipse.wst.xml.core.encoding.XMLDocumentCharsetDetector;
+import org.eclipse.wst.xml.core.internal.filebuffers.DocumentFactoryForXML;
+import org.eclipse.wst.xml.core.text.rules.StructuredTextPartitionerForXML;
+
+
+
+public class DocumentLoaderForXML extends StructuredDocumentLoader implements IDocumentLoader, IDocumentLoaderForFileBuffers {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.document.IDocumentLoader#createNewStructuredDocument()
+ */
+ public IEncodedDocument createNewStructuredDocument() {
+ DocumentFactoryForXML factory = new DocumentFactoryForXML();
+ IEncodedDocument document = (IEncodedDocument) factory.createDocument();
+ return document;
+ }
+
+ public IEncodedDocument createNewStructuredDocument(Reader reader) throws UnsupportedEncodingException, IOException {
+ IEncodedDocument structuredDocument = createNewStructuredDocument();
+ StringBuffer allText = readInputStream(reader);
+ structuredDocument.set(allText.toString());
+ return structuredDocument;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.document.IDocumentLoader#createNewStructuredDocument(java.lang.String,
+ * java.io.InputStream)
+ */
+ public IEncodedDocument createNewStructuredDocument(String filename, InputStream inputStream) throws IOException {
+ return createNewStructuredDocument(filename, inputStream, EncodingRule.CONTENT_BASED);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.document.IDocumentLoader#createNewStructuredDocument(java.lang.String,
+ * java.io.InputStream, com.ibm.encoding.resource.EncodingRule)
+ */
+ public IEncodedDocument createNewStructuredDocument(String filename, InputStream inputStream, EncodingRule encodingRule) throws IOException {
+ if (filename == null && inputStream == null) {
+ throw new IllegalArgumentException("can not have both null filename and inputstream"); //$NON-NLS-1$
+ }
+ CodedReaderCreator codedReaderCreator = new CodedReaderCreator();
+ Reader fullPreparedReader = null;
+ IEncodedDocument structuredDocument = createNewStructuredDocument();
+ try {
+ codedReaderCreator.set(filename, inputStream);
+ codedReaderCreator.setEncodingRule(encodingRule);
+ EncodingMemento encodingMemento = codedReaderCreator.getEncodingMemento();
+ fullPreparedReader = codedReaderCreator.getCodedReader();
+ structuredDocument.setEncodingMemento(encodingMemento);
+ StringBuffer allText = readInputStream(fullPreparedReader);
+ structuredDocument.set(allText.toString());
+ } catch (CoreException e) {
+ // impossible in this context
+ throw new Error(e);
+ } finally {
+ if (fullPreparedReader != null) {
+ fullPreparedReader.close();
+ }
+ }
+
+ return structuredDocument;
+ }
+
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.document.IDocumentLoader#getDefaultDocumentPartitioner()
+ */
+ public IDocumentPartitioner getDefaultDocumentPartitioner() {
+ return new StructuredTextPartitionerForXML();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.document.IDocumentLoader#getDocumentEncodingDetector()
+ */
+ public IDocumentCharsetDetector getDocumentEncodingDetector() {
+ return new XMLDocumentCharsetDetector();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.document.IDocumentLoader#handleLineDelimiter(java.lang.StringBuffer,
+ * org.eclipse.wst.sse.core.document.IEncodedDocument)
+ */
+ public StringBuffer handleLineDelimiter(StringBuffer originalString, IEncodedDocument theStructuredDocument) {
+ // TODO Auto-generated method stub
+ return originalString;
+ }
+
+}
+
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/DocumentTypeAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/DocumentTypeAdapter.java
new file mode 100644
index 0000000000..285ad87906
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/DocumentTypeAdapter.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.w3c.dom.DocumentType;
+
+
+/**
+ */
+public interface DocumentTypeAdapter extends INodeAdapter {
+ static final int LOWER_CASE = 2;
+ static final int STRICT_CASE = 0;
+ static final int UPPER_CASE = 1;
+
+ /**
+ */
+ int getAttrNameCase();
+
+ /**
+ */
+ DocumentType getDocumentType();
+
+ /**
+ */
+ int getTagNameCase();
+
+ /**
+ */
+ boolean hasFeature(String feature);
+
+ /**
+ */
+ boolean isXMLType();
+
+ /**
+ */
+ void release();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/InvalidCharacterException.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/InvalidCharacterException.java
new file mode 100644
index 0000000000..e0a7add83d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/InvalidCharacterException.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+/**
+ * Thrown an invalid character is specified in : XMLNode#setSource(String)
+ */
+public class InvalidCharacterException extends Exception {
+
+ private char invalidChar = 0;
+ private int offset = -1;
+
+ /**
+ */
+ public InvalidCharacterException() {
+ super();
+ }
+
+ /**
+ */
+ public InvalidCharacterException(String s) {
+ super(s);
+ }
+
+ /**
+ */
+ public InvalidCharacterException(String s, char c) {
+ super(s);
+ this.invalidChar = c;
+ }
+
+ /**
+ */
+ public InvalidCharacterException(String s, char c, int offset) {
+ super(s);
+ this.invalidChar = c;
+ this.offset = offset;
+ }
+
+ /**
+ */
+ public char getInvalidChar() {
+ return this.invalidChar;
+ }
+
+ /**
+ */
+ public int getOffset() {
+ return this.offset;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/JSPTag.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/JSPTag.java
new file mode 100644
index 0000000000..b4398d9fa0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/JSPTag.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+/**
+ * JSPTag interface
+ */
+public interface JSPTag {
+ static final String COMMENT_CLOSE = "--%>";//$NON-NLS-1$
+ static final String COMMENT_OPEN = "<%--";//$NON-NLS-1$
+ static final String DECLARATION_TOKEN = "!";//$NON-NLS-1$
+ static final String DIRECTIVE_TOKEN = "@";//$NON-NLS-1$
+ static final String EXPRESSION_TOKEN = "=";//$NON-NLS-1$
+ static final String JSP_DECLARATION = "jsp:declaration";//$NON-NLS-1$
+ static final String JSP_DIRECTIVE = "jsp:directive";//$NON-NLS-1$
+ static final String JSP_EXPRESSION = "jsp:expression";//$NON-NLS-1$
+ static final String JSP_ROOT = "jsp:root";//$NON-NLS-1$
+
+ static final String JSP_SCRIPTLET = "jsp:scriptlet";//$NON-NLS-1$
+ static final String TAG_CLOSE = "%>";//$NON-NLS-1$
+ static final String TAG_OPEN = "<%";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/TagAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/TagAdapter.java
new file mode 100644
index 0000000000..1c7d0c4f37
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/TagAdapter.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.eclipse.wst.sse.core.INodeAdapter;
+
+/**
+ */
+public interface TagAdapter extends INodeAdapter {
+
+ /**
+ */
+ String getEndTag(XMLElement element);
+
+ /**
+ */
+ String getStartTag(XMLElement element);
+
+ /**
+ */
+ boolean isEndTag();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLAttr.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLAttr.java
new file mode 100644
index 0000000000..60b804141b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLAttr.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.w3c.dom.Attr;
+
+
+/**
+ */
+public interface XMLAttr extends XMLNode, Attr {
+
+ /**
+ */
+ ITextRegion getEqualRegion();
+
+ /**
+ * @return
+ */
+ int getNameRegionEndOffset();
+
+ int getNameRegionStartOffset();
+
+ String getNameRegionText();
+
+ /**
+ * @return
+ */
+ int getNameRegionTextEndOffset();
+
+ int getValueRegionStartOffset();
+
+ String getValueRegionText();
+
+ /**
+ * Check if Attr has JSP in value
+ */
+ boolean hasJSPValue();
+
+ /**
+ * Check if Attr has only name but not equal sign nor value
+ */
+ boolean hasNameOnly();
+
+ /**
+ */
+ boolean isGlobalAttr();
+
+ /**
+ */
+ boolean isXMLAttr();
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLCharEntity.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLCharEntity.java
new file mode 100644
index 0000000000..d1984d9fa0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLCharEntity.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+/**
+ * XML Namespace constants
+ */
+public interface XMLCharEntity {
+ static final String AMP_NAME = "amp";//$NON-NLS-1$
+ static final String AMP_REF = "&amp;";//$NON-NLS-1$
+ static final String AMP_VALUE = "&";//$NON-NLS-1$
+ static final String APOS_NAME = "apos";//$NON-NLS-1$
+ static final String APOS_REF = "&apos;";//$NON-NLS-1$
+ static final String APOS_VALUE = "'";//$NON-NLS-1$
+ static final String GT_NAME = "gt";//$NON-NLS-1$
+ static final String GT_REF = "&gt;";//$NON-NLS-1$
+ static final String GT_VALUE = ">";//$NON-NLS-1$
+
+ static final String LT_NAME = "lt";//$NON-NLS-1$
+ static final String LT_REF = "&lt;";//$NON-NLS-1$
+ static final String LT_VALUE = "<";//$NON-NLS-1$
+ static final String QUOT_NAME = "quot";//$NON-NLS-1$
+ static final String QUOT_REF = "&quot;";//$NON-NLS-1$
+ static final String QUOT_VALUE = "\"";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLDocument.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLDocument.java
new file mode 100644
index 0000000000..a461cab1a7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLDocument.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.ranges.DocumentRange;
+import org.w3c.dom.traversal.DocumentTraversal;
+
+/**
+ * This interface enables creation of DOCTYPE declaration and some DOM Level 2
+ * interfaces.
+ */
+public interface XMLDocument extends XMLNode, Document, DocumentRange, DocumentTraversal {
+
+ /**
+ * create comment element. tagName must be registered as comment element
+ * name in plugin.xml
+ *
+ * @param tagName
+ * the element name
+ * @param isJSPTag
+ * true if the element is JSP style comment (&lt;%-- ...
+ * --%&gt;)
+ * @return Element element instance
+ * @throws DOMException
+ * throwed if the element name is registered as comment
+ * element
+ */
+ Element createCommentElement(String tagName, boolean isJSPTag) throws DOMException;
+
+ /**
+ */
+ DocumentType createDoctype(String name);
+
+ /**
+ */
+ String getDocumentTypeId();
+
+ /**
+ */
+ boolean isJSPDocument();
+
+ /**
+ */
+ boolean isJSPType();
+
+ /**
+ */
+ boolean isXMLType();
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLDocumentType.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLDocumentType.java
new file mode 100644
index 0000000000..082d4ff41a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLDocumentType.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.w3c.dom.DocumentType;
+
+/**
+ * This interface enables setting of Public and System ID for DOCTYPE
+ * declaration.
+ */
+public interface XMLDocumentType extends XMLNode, DocumentType {
+
+ /**
+ */
+ void setPublicId(String publicId);
+
+ /**
+ */
+ void setSystemId(String systemId);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLElement.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLElement.java
new file mode 100644
index 0000000000..b983975138
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLElement.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.w3c.dom.Element;
+
+/**
+ */
+public interface XMLElement extends XMLNode, Element {
+
+ /**
+ * @deprecated this should probably not be public, but already implemented
+ */
+ int getEndStartOffset();
+
+ /**
+ */
+ String getEndTagName();
+
+ /**
+ * @deprecated this should probably not be public, but already implemented
+ *
+ */
+ int getStartEndOffset();
+
+ /**
+ */
+ boolean hasEndTag();
+
+ /**
+ */
+ boolean hasStartTag();
+
+ /**
+ */
+ boolean isCommentTag();
+
+ /**
+ * isEmptyTag method
+ *
+ * @return boolean
+ */
+ boolean isEmptyTag();
+
+ /**
+ */
+ boolean isEndTag();
+
+ /**
+ * Returns true for "global tag" (basically, without prefix)
+ */
+ boolean isGlobalTag();
+
+ /**
+ * Returns true for no the start and the end tags
+ */
+ boolean isImplicitTag();
+
+ /**
+ * isJSPTag method
+ *
+ * @return boolean
+ */
+ boolean isJSPTag();
+
+ /**
+ */
+ boolean isStartTagClosed();
+
+ /**
+ */
+ boolean isXMLTag();
+
+ /**
+ * @deprecated this should probably not be public, but already implemented
+ */
+ void notifyEndTagChanged();
+
+ /**
+ * @deprecated this should probably not be public, but already implemented
+ */
+ void notifyStartTagChanged();
+
+ /**
+ */
+ void setCommentTag(boolean isCommentTag);
+
+ /**
+ */
+ void setEmptyTag(boolean isEmptyTag);
+
+ /**
+ */
+ void setJSPTag(boolean isJSPTag);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLGenerator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLGenerator.java
new file mode 100644
index 0000000000..5b9321bba0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLGenerator.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+public interface XMLGenerator {
+
+ /**
+ */
+ String generateAttrName(Attr attr);
+
+ /**
+ */
+ String generateAttrValue(Attr attr);
+
+ /**
+ */
+ String generateAttrValue(Attr attr, char quote);
+
+ /**
+ */
+ String generateAttrValue(String value, char quote);
+
+ /**
+ * generateCDATASection method
+ *
+ * @return java.lang.String
+ * @param comment
+ * org.w3c.dom.CDATASection
+ */
+ String generateCDATASection(CDATASection cdata);
+
+ /**
+ * generateChild method
+ *
+ * @return java.lang.String
+ * @param org.w3c.dom.Node
+ */
+ String generateChild(Node parentNode);
+
+ /**
+ */
+ String generateCloseTag(Node node);
+
+ /**
+ * generateComment method
+ *
+ * @return java.lang.String
+ * @param comment
+ * org.w3c.dom.Comment
+ */
+ String generateComment(Comment comment);
+
+ /**
+ * generateDoctype method
+ *
+ * @return java.lang.String
+ * @param docType
+ * org.w3c.dom.DocumentType
+ */
+ String generateDoctype(DocumentType docType);
+
+ /**
+ * generateElement method
+ *
+ * @return java.lang.String
+ * @param element
+ * Element
+ */
+ String generateElement(Element element);
+
+ /**
+ * generateEndTag method
+ *
+ * @return java.lang.String
+ * @param element
+ * org.w3c.dom.Element
+ */
+ String generateEndTag(Element element);
+
+ /**
+ * generateEntityRef method
+ *
+ * @return java.lang.String
+ * @param entityRef
+ * org.w3c.dom.EntityReference
+ */
+ String generateEntityRef(EntityReference entityRef);
+
+ /**
+ * generatePI method
+ *
+ * @return java.lang.String
+ * @param pi
+ * org.w3c.dom.ProcessingInstruction
+ */
+ String generatePI(ProcessingInstruction pi);
+
+ /**
+ * generateSource method
+ *
+ * @return java.lang.String
+ * @param node
+ * org.w3c.dom.Node
+ */
+ String generateSource(Node node);
+
+ /**
+ * generateStartTag method
+ *
+ * @return java.lang.String
+ * @param element
+ * Element
+ */
+ String generateStartTag(Element element);
+
+ /**
+ */
+ String generateTagName(Element element);
+
+ /**
+ * generateText method
+ *
+ * @return java.lang.String
+ * @param text
+ * org.w3c.dom.Text
+ */
+ String generateText(Text text);
+
+ /**
+ */
+ String generateTextData(Text text, String data);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLModel.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLModel.java
new file mode 100644
index 0000000000..f95cff4d25
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLModel.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+import org.eclipse.wst.sse.core.IStructuredModel;
+
+
+
+/**
+ */
+public interface XMLModel extends IStructuredModel {
+
+ XMLDocument getDocument();
+
+ /**
+ */
+ XMLGenerator getGenerator();
+
+ /**
+ */
+ XMLModelNotifier getModelNotifier();
+
+ /**
+ */
+ void setModelNotifier(XMLModelNotifier notifier);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLModelNotifier.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLModelNotifier.java
new file mode 100644
index 0000000000..1cee885546
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLModelNotifier.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public interface XMLModelNotifier {
+
+ /**
+ * attrReplaced method
+ *
+ * @param element
+ * org.w3c.dom.Element
+ * @param newAttr
+ * org.w3c.dom.Attr
+ * @param oldAttr
+ * org.w3c.dom.Attr
+ */
+ void attrReplaced(Element element, Attr newAttr, Attr oldAttr);
+
+ /**
+ */
+ void beginChanging();
+
+ /**
+ */
+ void beginChanging(boolean newModel);
+
+ /**
+ * Cancel pending notifications. This is called in the context of
+ * "reinitialization" so is assumed ALL notifications can be safely
+ * canceled, assuming that once factories and adapters are re-initialized
+ * they will be re-notified as text is set in model, if still appropriate.
+ */
+ void cancelPending();
+
+ /**
+ * childReplaced method
+ *
+ * @param parentNode
+ * org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param oldChild
+ * org.w3c.dom.Node
+ */
+ void childReplaced(Node parentNode, Node newChild, Node oldChild);
+
+ /**
+ */
+ void editableChanged(Node node);
+
+ /**
+ */
+ void endChanging();
+
+ /**
+ */
+ void endTagChanged(Element element);
+
+ /**
+ */
+ boolean hasChanged();
+
+ /**
+ */
+ boolean isChanging();
+
+ /**
+ */
+ void propertyChanged(Node node);
+
+ /**
+ */
+ void startTagChanged(Element element);
+
+ /**
+ */
+ void structureChanged(Node node);
+
+ /**
+ * valueChanged method
+ *
+ * @param node
+ * org.w3c.dom.Node
+ */
+ void valueChanged(Node node);
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLNamespace.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLNamespace.java
new file mode 100644
index 0000000000..04188a6781
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLNamespace.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+/**
+ * XML Namespace constants
+ */
+public interface XMLNamespace {
+
+ static final String XMLNS = "xmlns";//$NON-NLS-1$
+ static final String XMLNS_PREFIX = "xmlns:";//$NON-NLS-1$
+ static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLNode.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLNode.java
new file mode 100644
index 0000000000..b20058190c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLNode.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+/**
+ * A interface to make concept clearer, just to denote the combination of
+ * three other interfaces.
+ *
+ */
+public interface XMLNode extends org.eclipse.wst.sse.core.IndexedRegion, org.eclipse.wst.sse.core.INodeNotifier, org.w3c.dom.Node {
+
+ /**
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ IStructuredDocumentRegion getEndStructuredDocumentRegion();
+
+ /**
+ */
+ IStructuredDocumentRegion getFirstStructuredDocumentRegion();
+
+ /**
+ */
+ IStructuredDocumentRegion getLastStructuredDocumentRegion();
+
+ /**
+ */
+ XMLModel getModel();
+
+ /**
+ */
+ ITextRegion getNameRegion();
+
+ /**
+ */
+ String getSource();
+
+ /**
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ IStructuredDocumentRegion getStartStructuredDocumentRegion();
+
+ /**
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocument
+ */
+ IStructuredDocument getStructuredDocument();
+
+ /**
+ */
+ ITextRegion getValueRegion();
+
+ /**
+ */
+ String getValueSource();
+
+ /**
+ *
+ * @return boolean Whether children of the element can be appended or
+ * removed.
+ */
+ boolean isChildEditable();
+
+ /**
+ */
+ boolean isClosed();
+
+ /**
+ * isContainer method
+ *
+ * @return boolean
+ */
+ boolean isContainer();
+
+ /**
+ */
+ boolean isDataEditable();
+
+ /**
+ */
+ void setChildEditable(boolean editable);
+
+ /**
+ */
+ void setDataEditable(boolean editable);
+
+ /**
+ * faster approach to set
+ */
+ void setEditable(boolean editable, boolean deep);
+
+ /**
+ * Sets the specified raw source to the Text node. Throws
+ * InvalidCharacterException when the specified raw source includes
+ * invalid characters, such as, ' <', '>' and '&'. Valid character
+ * entities, such as, "&amp;lt;", are accepted.
+ */
+ void setSource(String source) throws InvalidCharacterException;
+
+ /**
+ * Sets the specified raw source to the Text or Attr node's value. When
+ * the specified raw source includes invalid characters, such as, ' <',
+ * '>' and '&', converts them. Valid character entities, such as,
+ * "&amp;lt;", are accepted.
+ */
+ void setValueSource(String source);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLText.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLText.java
new file mode 100644
index 0000000000..fe80a06a73
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/document/XMLText.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.document;
+
+
+
+import org.w3c.dom.Text;
+
+/**
+ */
+public interface XMLText extends XMLNode, Text {
+
+ /**
+ * Appends the content of the text node
+ */
+ void appendText(Text text);
+
+ /**
+ * Inserts the content of the text node at the specified position
+ */
+ void insertText(Text text, int offset);
+
+ /**
+ */
+ boolean isInvalid();
+
+ /**
+ */
+ boolean isWhitespace();
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/encoding/XMLDocumentCharsetDetector.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/encoding/XMLDocumentCharsetDetector.java
new file mode 100644
index 0000000000..bdde4b27a0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/encoding/XMLDocumentCharsetDetector.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.encoding;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.document.DocumentReader;
+import org.eclipse.wst.sse.core.document.IDocumentCharsetDetector;
+import org.eclipse.wst.xml.core.contenttype.XMLResourceEncodingDetector;
+
+
+/**
+ * This class reads and parses first of XML file to get encoding.
+ *
+ */
+public class XMLDocumentCharsetDetector extends XMLResourceEncodingDetector implements IDocumentCharsetDetector {
+
+ /**
+ * XMLLoader constructor comment.
+ */
+ public XMLDocumentCharsetDetector() {
+ super();
+ }
+
+ public void set(IDocument document) {
+ set(new DocumentReader(document, 0));
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/encoding/XMLDocumentLoader.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/encoding/XMLDocumentLoader.java
new file mode 100644
index 0000000000..a87b340a1b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/encoding/XMLDocumentLoader.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.encoding;
+
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.common.encoding.ContentTypeEncodingPreferences;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.core.document.AbstractDocumentLoader;
+import org.eclipse.wst.sse.core.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.document.StructuredDocumentFactory;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
+import org.eclipse.wst.sse.core.parser.RegionParser;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+import org.eclipse.wst.xml.core.internal.parser.XMLStructuredDocumentReParser;
+import org.eclipse.wst.xml.core.text.rules.StructuredTextPartitionerForXML;
+
+
+/**
+ * This class reads an XML file and creates an XML Structured Model.
+ *
+ */
+public class XMLDocumentLoader extends AbstractDocumentLoader {
+
+ public XMLDocumentLoader() {
+ super();
+ }
+
+ public IDocumentPartitioner getDefaultDocumentPartitioner() {
+ return new StructuredTextPartitionerForXML();
+ }
+
+ public IDocumentCharsetDetector getDocumentEncodingDetector() {
+ if (fDocumentEncodingDetector == null) {
+ fDocumentEncodingDetector = new XMLDocumentCharsetDetector();
+ }
+ return fDocumentEncodingDetector;
+ }
+
+ public RegionParser getParser() {
+ return new XMLSourceParser();
+ }
+
+ protected String getPreferredNewLineDelimiter() {
+ return ContentTypeEncodingPreferences.getPreferredNewLineDelimiter(IContentTypeIdentifier.ContentTypeID_SSEXML);
+ }
+
+ protected String getSpecDefaultEncoding() {
+ // by default, UTF-8 as per XML spec
+ final String enc = "UTF-8"; //$NON-NLS-1$
+ return enc;
+ }
+
+ protected IEncodedDocument newEncodedDocument() {
+ IStructuredDocument structuredDocument = StructuredDocumentFactory.getNewStructuredDocumentInstance(getParser());
+ if (structuredDocument instanceof BasicStructuredDocument) {
+ ((BasicStructuredDocument) structuredDocument).setReParser(new XMLStructuredDocumentReParser());
+ }
+ return structuredDocument;
+ }
+
+ public IDocumentLoader newInstance() {
+ return new XMLDocumentLoader();
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/CommentNodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/CommentNodeFormatter.java
new file mode 100644
index 0000000000..f962f15db6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/CommentNodeFormatter.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.format;
+
+import org.eclipse.wst.sse.core.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.Node;
+
+
+public class CommentNodeFormatter extends NodeFormatter {
+
+ protected String adjustIndentations(String aString, String lineIndent, String singleIndent) {
+ String result = new String();
+
+ int indexOfLineDelimiter = StringUtils.indexOfLineDelimiter(aString);
+ result = aString.substring(0, indexOfLineDelimiter);
+ while (indexOfLineDelimiter != -1) {
+ // Before find the next LineDelimiter, we have to figure out the
+ // size of the current LineDelimiter
+ // so we can figure out how many bytes to skip before finding the
+ // next LineDelimiter.
+ // Otherwise, we may treat the LF in CRLF as the next
+ // LineDelimiter.
+ int lineDelimiterSize = 1;
+ if (aString.length() >= indexOfLineDelimiter + 2 && aString.substring(indexOfLineDelimiter, indexOfLineDelimiter + 1).compareTo(CR) == 0 && aString.substring(indexOfLineDelimiter + 1, indexOfLineDelimiter + 2).compareTo(LF) == 0)
+ lineDelimiterSize = 2;
+
+ int indexOfNextLineDelimiter = StringUtils.indexOfLineDelimiter(aString, indexOfLineDelimiter + lineDelimiterSize);
+ int indexOfNonblank = StringUtils.indexOfNonblank(aString, indexOfLineDelimiter);
+
+ if (indexOfNonblank != -1) {
+ if (indexOfNextLineDelimiter == -1) {
+ // last line; copy till the end
+ result += lineIndent + singleIndent + aString.substring(indexOfNonblank);
+ } else if (indexOfNextLineDelimiter != -1 && indexOfNextLineDelimiter < indexOfNonblank) {
+ // blank line; just add a indent
+ result += lineIndent + singleIndent;
+ } else {
+ // copy all text between indexOfNonblank and
+ // indexOfNextLineDelimiter
+ result += lineIndent + singleIndent + aString.substring(indexOfNonblank, indexOfNextLineDelimiter);
+ }
+
+ indexOfLineDelimiter = indexOfNextLineDelimiter;
+ } else {
+ if (indexOfNextLineDelimiter == -1) {
+ result += lineIndent;
+ } else {
+ // blank line; just add a indent
+ result += lineIndent + singleIndent;
+ }
+
+ indexOfLineDelimiter = indexOfNextLineDelimiter;
+ }
+ }
+
+ return result;
+ }
+
+ protected void formatNode(XMLNode node, IStructuredFormatContraints formatContraints) {
+ if (node != null) {
+ // lineDelimiterFound means multi line comment
+ String nodeValue = node.getNodeValue();
+ boolean lineDelimiterFoundInComment = StringUtils.containsLineDelimiter(nodeValue);
+
+ if (lineDelimiterFoundInComment) {
+ // format indentation before node
+ formatIndentationBeforeNode(node, formatContraints);
+
+ // adjust indentations in multi line comment
+ String lineDelimiter = node.getModel().getStructuredDocument().getLineDelimiter();
+ String lineIndent = formatContraints.getCurrentIndent();
+ String singleIndent = getFormatPreferences().getIndent();
+ String newNodevalue = adjustIndentations(nodeValue, lineDelimiter + lineIndent, singleIndent);
+ if (nodeValue.compareTo(newNodevalue) != 0)
+ node.setNodeValue(newNodevalue);
+ }
+
+ if (!nodeHasSiblings(node) || (node.getPreviousSibling() != null && node.getPreviousSibling().getNodeType() == Node.TEXT_NODE && !StringUtils.containsLineDelimiter(node.getPreviousSibling().getNodeValue()) && node.getNextSibling() == null)) {
+ // single child
+ // or inline comment after text
+ // do nothing
+ } else
+ // format indentation after node
+ formatIndentationAfterNode(node, formatContraints);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/DocumentNodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/DocumentNodeFormatter.java
new file mode 100644
index 0000000000..ee671a9925
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/DocumentNodeFormatter.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.format;
+
+import org.eclipse.wst.sse.core.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.format.IStructuredFormatter;
+import org.eclipse.wst.xml.core.document.XMLNode;
+
+
+public class DocumentNodeFormatter extends NodeFormatter {
+ protected void formatChildren(XMLNode node, IStructuredFormatContraints formatContraints) {
+ String singleIndent = getFormatPreferences().getIndent();
+ String lineIndent = formatContraints.getCurrentIndent();
+
+ if (node != null && (fProgressMonitor == null || !fProgressMonitor.isCanceled())) {
+ // normalize node first to combine adjacent text nodes
+ node.normalize();
+
+ XMLNode nextChild = (XMLNode) node.getFirstChild();
+ while (nextChild != null) {
+ XMLNode eachChildNode = nextChild;
+ nextChild = (XMLNode) eachChildNode.getNextSibling();
+ IStructuredFormatter formatter = getFormatter(eachChildNode);
+ IStructuredFormatContraints childFormatContraints = formatter.getFormatContraints();
+ String childIndent = lineIndent + singleIndent;
+ childFormatContraints.setCurrentIndent(childIndent);
+ childFormatContraints.setClearAllBlankLines(formatContraints.getClearAllBlankLines());
+
+ // format each child
+ formatter.format(eachChildNode, childFormatContraints);
+
+ if (nextChild != null && nextChild.getParentNode() == null)
+ // nextNode is deleted during format
+ nextChild = (XMLNode) eachChildNode.getNextSibling();
+ }
+ }
+ }
+
+ protected void formatNode(XMLNode node, IStructuredFormatContraints formatContraints) {
+ if (node != null)
+ formatChildren(node, formatContraints);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/ElementNodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/ElementNodeFormatter.java
new file mode 100644
index 0000000000..52d63d9a81
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/ElementNodeFormatter.java
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.format;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.core.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.modelquery.ModelQueryAdapter;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLGenerator;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.internal.document.AttrImpl;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+public class ElementNodeFormatter extends DocumentNodeFormatter {
+ static protected final char DOUBLE_QUOTE = '"';//$NON-NLS-1$
+ static protected final String DOUBLE_QUOTES = "\"\"";//$NON-NLS-1$
+ static protected final char EQUAL_CHAR = '='; // equal sign$NON-NLS-1$
+ static protected final String PRESERVE = "preserve";//$NON-NLS-1$
+ static protected final String PRESERVE_QUOTED = "\"preserve\"";//$NON-NLS-1$
+ static protected final char SINGLE_QUOTE = '\'';//$NON-NLS-1$
+ static protected final String XML_SPACE = "xml:space";//$NON-NLS-1$
+
+ protected void formatEndTag(XMLNode node, IStructuredFormatContraints formatContraints) {
+ String tagName = node.getNodeName();
+
+ if (!isEndTagMissing(node)) {
+ // end tag exists
+
+ IStructuredDocument structuredDocument = node.getModel().getStructuredDocument();
+ String lineDelimiter = structuredDocument.getLineDelimiter();
+ String nodeIndentation = getNodeIndent(node);
+ XMLNode lastChild = (XMLNode) node.getLastChild();
+ if (lastChild != null && lastChild.getNodeType() != Node.TEXT_NODE) {
+ if (isEndTagMissing(lastChild)) {
+ // find deepest child
+ XMLNode deepestChild = (XMLNode) lastChild.getLastChild();
+ while (deepestChild != null && deepestChild.getLastChild() != null && isEndTagMissing(deepestChild)) {
+ lastChild = deepestChild;
+ deepestChild = (XMLNode) deepestChild.getLastChild();
+ }
+
+ if (deepestChild != null) {
+ if (deepestChild.getNodeType() == Node.TEXT_NODE) {
+ // Special indentation handling if lastChild's end
+ // tag is missing and deepestChild is a text node.
+ String nodeText = deepestChild.getNodeValue();
+
+ if (!nodeText.endsWith(lineDelimiter + nodeIndentation)) {
+ nodeText = StringUtils.appendIfNotEndWith(nodeText, lineDelimiter);
+ nodeText = StringUtils.appendIfNotEndWith(nodeText, nodeIndentation);
+ }
+
+ replaceNodeValue(deepestChild, nodeText);
+ } else
+ insertAfterNode(lastChild, lineDelimiter + nodeIndentation);
+ }
+ } else
+ // indent end tag
+ insertAfterNode(lastChild, lineDelimiter + nodeIndentation);
+ } else if (lastChild == null && firstStructuredDocumentRegionContainsLineDelimiters(node)) {
+ // indent end tag
+ replace(structuredDocument, node.getFirstStructuredDocumentRegion().getEndOffset(), 0, lineDelimiter + nodeIndentation);
+ }
+
+ // format end tag name
+ IStructuredDocumentRegion endTagStructuredDocumentRegion = node.getLastStructuredDocumentRegion();
+ if (endTagStructuredDocumentRegion.getRegions().size() >= 3) {
+ ITextRegion endTagNameRegion = endTagStructuredDocumentRegion.getRegions().get(1);
+ removeRegionSpaces(node, endTagStructuredDocumentRegion, endTagNameRegion);
+ }
+ }
+ }
+
+ protected void formatNode(XMLNode node, IStructuredFormatContraints formatContraints) {
+ if (node != null) {
+ // format indentation before node
+ formatIndentationBeforeNode(node, formatContraints);
+
+ // format start tag
+ XMLNode newNode = node;
+ int startTagStartOffset = node.getStartOffset();
+ XMLModel structuredModel = node.getModel();
+
+ formatStartTag(node, formatContraints);
+ // save new node
+ newNode = (XMLNode) structuredModel.getIndexedRegion(startTagStartOffset);
+
+ IStructuredDocumentRegion flatNode = newNode.getFirstStructuredDocumentRegion();
+ if (flatNode != null) {
+ ITextRegionList regions = flatNode.getRegions();
+ ITextRegion lastRegion = regions.get(regions.size() - 1);
+ // format children and end tag if not empty start tag
+ if (lastRegion.getType() != XMLRegionContext.XML_EMPTY_TAG_CLOSE) {
+ // format children
+ formatChildren(newNode, formatContraints);
+
+ // save new node
+ newNode = (XMLNode) structuredModel.getIndexedRegion(startTagStartOffset);
+
+ // format end tag
+ formatEndTag(newNode, formatContraints);
+ }
+ }
+
+ // format indentation after node
+ formatIndentationAfterNode(newNode, formatContraints);
+ }
+ }
+
+ /**
+ * This method formats the start tag name, and formats the attributes if
+ * available.
+ */
+ protected void formatStartTag(XMLNode node, IStructuredFormatContraints formatContraints) {
+ String singleIndent = getFormatPreferences().getIndent();
+ String lineIndent = formatContraints.getCurrentIndent();
+ String attrIndent = lineIndent + singleIndent;
+ boolean splitMultiAttrs = ((IStructuredFormatPreferencesXML) fFormatPreferences).getSplitMultiAttrs();
+ IStructuredDocumentRegion flatNode = node.getFirstStructuredDocumentRegion();
+ NamedNodeMap attributes = node.getAttributes();
+ String tagName = node.getNodeName();
+
+ // Note: attributes should not be null even if the node has no
+ // attributes. However, attributes.getLength() will be 0. But, check
+ // for null just in case.
+ if (attributes != null) {
+ // compute current available line width
+ int currentAvailableLineWidth = 0;
+ try {
+ // 1 is for "<"
+ int nodeNameOffset = node.getStartOffset() + 1 + node.getNodeName().length();
+ int lineOffset = node.getStructuredDocument().getLineInformationOfOffset(nodeNameOffset).getOffset();
+ String text = node.getStructuredDocument().get(lineOffset, nodeNameOffset - lineOffset);
+ int usedWidth = getIndentationLength(text);
+ currentAvailableLineWidth = getFormatPreferences().getLineWidth() - usedWidth;
+ } catch (BadLocationException exception) {
+ throw new SourceEditingRuntimeException(exception);
+ }
+
+ StringBuffer stringBuffer = new StringBuffer();
+ String lineDelimiter = node.getModel().getStructuredDocument().getLineDelimiter();
+ int attrLength = attributes.getLength();
+ int lastUndefinedRegionOffset = 0;
+ for (int i = 0; i < attrLength; i++) {
+ AttrImpl attr = (AttrImpl) attributes.item(i);
+ ITextRegion nameRegion = attr.getNameRegion();
+ ITextRegion equalRegion = attr.getEqualRegion();
+ ITextRegion valueRegion = attr.getValueRegion();
+
+ // append undefined regions
+ String undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, attr.getStartOffset() - lastUndefinedRegionOffset);
+ stringBuffer.append(undefinedRegion);
+ lastUndefinedRegionOffset = attr.getStartOffset();
+
+ // check for xml:space attribute
+ if (flatNode.getText(nameRegion).compareTo(XML_SPACE) == 0) {
+ if (valueRegion == null) {
+ ModelQueryAdapter adapter = (ModelQueryAdapter) ((XMLDocument) node.getOwnerDocument()).getAdapterFor(ModelQueryAdapter.class);
+ CMElementDeclaration elementDeclaration = (CMElementDeclaration) adapter.getModelQuery().getCMNode(node);
+ if (elementDeclaration == null)
+ // CMElementDeclaration not found, default to
+ // PRESERVE
+ formatContraints.setClearAllBlankLines(false);
+ else {
+ CMAttributeDeclaration attributeDeclaration = (CMAttributeDeclaration) elementDeclaration.getAttributes().getNamedItem(XML_SPACE);
+ if (attributeDeclaration == null)
+ // CMAttributeDeclaration not found, default
+ // to PRESERVE
+ formatContraints.setClearAllBlankLines(false);
+ else {
+ String defaultValue = attributeDeclaration.getAttrType().getImpliedValue();
+
+ if (defaultValue.compareTo(PRESERVE) == 0)
+ formatContraints.setClearAllBlankLines(false);
+ else
+ formatContraints.setClearAllBlankLines(getFormatPreferences().getClearAllBlankLines());
+ }
+ }
+ } else {
+ XMLGenerator generator = node.getModel().getGenerator();
+ String newAttrValue = generator.generateAttrValue(attr);
+
+ // There is a problem in
+ // StructuredDocumentRegionUtil.getAttrValue(ITextRegion)
+ // when the region is instanceof ContextRegion.
+ // Workaround for now.
+ if (flatNode.getText(valueRegion).length() == 1) {
+ char firstChar = flatNode.getText(valueRegion).charAt(0);
+ if ((firstChar == DOUBLE_QUOTE) || (firstChar == SINGLE_QUOTE))
+ newAttrValue = DOUBLE_QUOTES;
+ }
+
+ if (newAttrValue.compareTo(PRESERVE_QUOTED) == 0)
+ formatContraints.setClearAllBlankLines(false);
+ else
+ formatContraints.setClearAllBlankLines(getFormatPreferences().getClearAllBlankLines());
+ }
+ }
+
+ if (splitMultiAttrs && attrLength > 1) {
+ stringBuffer.append(lineDelimiter + attrIndent);
+ stringBuffer.append(flatNode.getText(nameRegion));
+ if (valueRegion != null) {
+ // append undefined regions
+ undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, flatNode.getStartOffset(equalRegion) - lastUndefinedRegionOffset);
+ stringBuffer.append(undefinedRegion);
+ lastUndefinedRegionOffset = flatNode.getStartOffset(equalRegion);
+
+ stringBuffer.append(EQUAL_CHAR);
+
+ // append undefined regions
+ undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, flatNode.getStartOffset(valueRegion) - lastUndefinedRegionOffset);
+ stringBuffer.append(undefinedRegion);
+ lastUndefinedRegionOffset = flatNode.getStartOffset(valueRegion);
+
+ // Note: trim() should not be needed for
+ // valueRegion.getText(). Just a workaround for a
+ // problem found in valueRegion for now.
+ stringBuffer.append(flatNode.getText(valueRegion).trim());
+ }
+ } else {
+ if (valueRegion != null) {
+ int textLength = 1 + flatNode.getText(nameRegion).length() + 1 + flatNode.getText(valueRegion).length();
+ if (i == attrLength - 1) {
+ if (flatNode != null) {
+ ITextRegionList regions = flatNode.getRegions();
+ ITextRegion lastRegion = regions.get(regions.size() - 1);
+ if (lastRegion.getType() != XMLRegionContext.XML_EMPTY_TAG_CLOSE)
+ // 3 is for " />"
+ textLength += 3;
+ else
+ // 1 is for ">"
+ textLength++;
+ }
+ }
+
+ if (currentAvailableLineWidth >= textLength) {
+ stringBuffer.append(SPACE_CHAR);
+ currentAvailableLineWidth--;
+ } else {
+ stringBuffer.append(lineDelimiter + attrIndent);
+ currentAvailableLineWidth = getFormatPreferences().getLineWidth() - attrIndent.length();
+ }
+
+ stringBuffer.append(flatNode.getText(nameRegion));
+
+ // append undefined regions
+ undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, flatNode.getStartOffset(equalRegion) - lastUndefinedRegionOffset);
+ stringBuffer.append(undefinedRegion);
+ lastUndefinedRegionOffset = flatNode.getStartOffset(equalRegion);
+
+ stringBuffer.append(EQUAL_CHAR);
+
+ // append undefined regions
+ undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, flatNode.getStartOffset(valueRegion) - lastUndefinedRegionOffset);
+ stringBuffer.append(undefinedRegion);
+ lastUndefinedRegionOffset = flatNode.getStartOffset(valueRegion);
+
+ // Note: trim() should not be needed for
+ // valueRegion.getText(). Just a workaround for a
+ // problem found in valueRegion for now.
+ stringBuffer.append(flatNode.getText(valueRegion).trim());
+
+ currentAvailableLineWidth -= flatNode.getText(nameRegion).length();
+ currentAvailableLineWidth--;
+ currentAvailableLineWidth -= flatNode.getText(valueRegion).trim().length();
+ } else {
+ if (currentAvailableLineWidth >= 1 + flatNode.getText(nameRegion).length()) {
+ stringBuffer.append(SPACE_CHAR);
+ currentAvailableLineWidth--;
+ } else {
+ stringBuffer.append(lineDelimiter + attrIndent);
+ currentAvailableLineWidth = getFormatPreferences().getLineWidth() - attrIndent.length();
+ }
+
+ stringBuffer.append(flatNode.getText(nameRegion));
+
+ currentAvailableLineWidth -= flatNode.getText(nameRegion).length();
+ }
+ }
+ }
+
+ // append undefined regions
+ String undefinedRegion = getUndefinedRegions(node, lastUndefinedRegionOffset, node.getEndOffset() - lastUndefinedRegionOffset);
+ stringBuffer.append(undefinedRegion);
+
+ XMLModel structuredModel = node.getModel();
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+ // 1 is for "<"
+ int offset = node.getStartOffset() + 1 + node.getNodeName().length();
+ // 1 is for "<"
+ int length = node.getFirstStructuredDocumentRegion().getTextLength() - 1 - node.getNodeName().length();
+
+ if (flatNode != null) {
+ ITextRegionList regions = flatNode.getRegions();
+ ITextRegion firstRegion = regions.get(0);
+ ITextRegion lastRegion = regions.get(regions.size() - 1);
+
+ if (firstRegion.getType() == XMLRegionContext.XML_END_TAG_OPEN)
+ // skip formatting for end tags in this format: </tagName>
+ return;
+ else {
+ if (lastRegion.getType() == XMLRegionContext.XML_TAG_CLOSE || lastRegion.getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE)
+ length = length - lastRegion.getLength();
+
+ if (lastRegion.getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE)
+ // leave space before XML_EMPTY_TAG_CLOSE: <tagName />
+ stringBuffer.append(SPACE_CHAR);
+ }
+ }
+
+ replace(structuredDocument, offset, length, stringBuffer.toString());
+ }
+ }
+
+ protected String getUndefinedRegions(XMLNode node, int startOffset, int length) {
+ String result = new String();
+
+ IStructuredDocumentRegion flatNode = node.getFirstStructuredDocumentRegion();
+ ITextRegionList regions = flatNode.getRegions();
+ for (int i = 0; i < regions.size(); i++) {
+ ITextRegion region = regions.get(i);
+ String regionType = region.getType();
+ int regionStartOffset = flatNode.getStartOffset(region);
+
+ if (regionType.compareTo(XMLRegionContext.UNDEFINED) == 0 && regionStartOffset >= startOffset && regionStartOffset < startOffset + length)
+ result = result + flatNode.getFullText(region);
+ }
+
+ if (result.length() > 0)
+ return SPACE + result.trim();
+ else
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/FormatProcessorXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/FormatProcessorXML.java
new file mode 100644
index 0000000000..d9f2b0df10
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/FormatProcessorXML.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.format;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.sse.core.format.AbstractStructuredFormatProcessor;
+import org.eclipse.wst.sse.core.format.IStructuredFormatPreferences;
+import org.eclipse.wst.sse.core.format.IStructuredFormatter;
+import org.eclipse.wst.sse.core.preferences.CommonModelPreferenceNames;
+import org.eclipse.wst.xml.core.XMLModelPlugin;
+import org.eclipse.wst.xml.core.internal.document.CDATASectionImpl;
+import org.w3c.dom.Node;
+
+
+public class FormatProcessorXML extends AbstractStructuredFormatProcessor {
+ protected IStructuredFormatPreferences fFormatPreferences = null;
+
+ protected String getFileExtension() {
+ return "xml"; //$NON-NLS-1$
+ }
+
+ public IStructuredFormatPreferences getFormatPreferences() {
+ if (fFormatPreferences == null) {
+ fFormatPreferences = new StructuredFormatPreferencesXML();
+
+ Preferences preferences = getModelPreferences();
+ if (preferences != null) {
+ fFormatPreferences.setLineWidth(preferences.getInt(CommonModelPreferenceNames.LINE_WIDTH));
+ ((IStructuredFormatPreferencesXML) fFormatPreferences).setSplitMultiAttrs(preferences.getBoolean(CommonModelPreferenceNames.SPLIT_MULTI_ATTRS));
+ fFormatPreferences.setClearAllBlankLines(preferences.getBoolean(CommonModelPreferenceNames.CLEAR_ALL_BLANK_LINES));
+
+ if (preferences.getBoolean(CommonModelPreferenceNames.INDENT_USING_TABS))
+ fFormatPreferences.setIndent("\t"); //$NON-NLS-1$
+ else {
+ int tabWidth = getModelManagerPlugin().getPluginPreferences().getInt(CommonModelPreferenceNames.TAB_WIDTH);
+ String indent = ""; //$NON-NLS-1$
+ for (int i = 0; i < tabWidth; i++) {
+ indent += " "; //$NON-NLS-1$
+ }
+ fFormatPreferences.setIndent(indent);
+ }
+ }
+ }
+
+ return fFormatPreferences;
+ }
+
+ protected IStructuredFormatter getFormatter(Node node) {
+ // 262135 - NPE during format of empty document
+ if (node == null)
+ return null;
+
+ short nodeType = node.getNodeType();
+ IStructuredFormatter formatter = null;
+ switch (nodeType) {
+ case Node.ELEMENT_NODE : {
+ formatter = new ElementNodeFormatter();
+ break;
+ }
+ case Node.TEXT_NODE : {
+ if (node instanceof CDATASectionImpl)
+ formatter = new NodeFormatter();
+ else
+ formatter = new TextNodeFormatter();
+ break;
+ }
+ case Node.COMMENT_NODE : {
+ formatter = new CommentNodeFormatter();
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ formatter = new NodeFormatter();
+ break;
+ }
+ case Node.DOCUMENT_NODE : {
+ formatter = new DocumentNodeFormatter();
+ break;
+ }
+ default : {
+ formatter = new NodeFormatter();
+ }
+ }
+
+ // init fomatter
+ formatter.setFormatPreferences(getFormatPreferences());
+ formatter.setProgressMonitor(fProgressMonitor);
+
+ return formatter;
+ }
+
+ private IModelManagerPlugin getModelManagerPlugin() {
+
+ IModelManagerPlugin plugin = (IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID);
+ return plugin;
+ }
+
+ protected Preferences getModelPreferences() {
+ return XMLModelPlugin.getDefault().getPluginPreferences();
+ }
+
+ protected void refreshFormatPreferences() {
+ fFormatPreferences = null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/IStructuredFormatPreferencesXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/IStructuredFormatPreferencesXML.java
new file mode 100644
index 0000000000..bc3faccf25
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/IStructuredFormatPreferencesXML.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.format;
+
+import org.eclipse.wst.sse.core.format.IStructuredFormatPreferences;
+
+public interface IStructuredFormatPreferencesXML extends IStructuredFormatPreferences {
+ boolean getSplitMultiAttrs();
+
+ void setSplitMultiAttrs(boolean splitMultiAttrs);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/NodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/NodeFormatter.java
new file mode 100644
index 0000000000..1948cdfc87
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/NodeFormatter.java
@@ -0,0 +1,775 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.format;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.core.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.format.IStructuredFormatPreferences;
+import org.eclipse.wst.sse.core.format.IStructuredFormatter;
+import org.eclipse.wst.sse.core.format.StructuredFormatContraints;
+import org.eclipse.wst.sse.core.internal.parser.ContextRegion;
+import org.eclipse.wst.sse.core.preferences.CommonModelPreferenceNames;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.xml.core.XMLModelPlugin;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.internal.document.CDATASectionImpl;
+import org.eclipse.wst.xml.core.internal.parser.regions.TagNameRegion;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Node;
+
+
+public class NodeFormatter implements IStructuredFormatter {
+ static protected final String CR = "\r"; //$NON-NLS-1$
+ static protected final String CRLF = "\r\n"; //$NON-NLS-1$
+ static protected final String DELIMITERS = " \t\n\r\f"; //$NON-NLS-1$
+ static protected final String EMPTY_STRING = ""; //$NON-NLS-1$
+ static protected final String FF = "\f"; //$NON-NLS-1$
+ static protected final String LF = "\n"; //$NON-NLS-1$
+ static protected final String SPACE = " "; //$NON-NLS-1$
+ static protected final char SPACE_CHAR = ' '; //$NON-NLS-1$
+ static protected final String TAB = "\t"; //$NON-NLS-1$
+ static protected final char TAB_CHAR = '\t'; //$NON-NLS-1$
+ protected IStructuredFormatContraints fFormatContraints = null;
+ protected IStructuredFormatPreferences fFormatPreferences = null;
+ protected IProgressMonitor fProgressMonitor = null;
+
+ protected String compressSpaces(String string, IStructuredFormatContraints formatContraints) {
+ /*
+ * Note that the StructuredTextEditor supports mixed new line
+ * characters (CR, LF, CRLF) in one file. We have to handle that when
+ * we try to preserve blank lines.
+ */
+ String[] stringArray = null;
+ boolean clearAllBlankLines = formatContraints.getClearAllBlankLines();
+
+ if (clearAllBlankLines)
+ stringArray = StringUtils.asArray(string);
+ else
+ stringArray = StringUtils.asArray(string, DELIMITERS, true);
+
+ StringBuffer compressedString = new StringBuffer();
+ if (stringArray.length > 0) {
+ boolean cr = false, lf = false, cr2 = false, nonSpace = true;
+
+ if (stringArray[0].compareTo(CR) == 0)
+ cr = true;
+ else if (stringArray[0].compareTo(LF) == 0)
+ lf = true;
+ else if ((stringArray[0].compareTo(SPACE) != 0) && (stringArray[0].compareTo(TAB) != 0) && (stringArray[0].compareTo(FF) != 0)) {
+ compressedString.append(stringArray[0]);
+ nonSpace = true;
+ }
+
+ for (int i = 1; i < stringArray.length; i++) {
+ if (stringArray[i].compareTo(CR) == 0) {
+ if (cr && lf) {
+ if (nonSpace) {
+ compressedString.append(CR + LF);
+ nonSpace = false;
+ }
+ compressedString.append(stringArray[i]);
+ cr2 = true;
+ } else if (cr) {
+ if (nonSpace) {
+ compressedString.append(CR);
+ nonSpace = false;
+ }
+ compressedString.append(stringArray[i]);
+ cr2 = true;
+ } else
+ cr = true;
+ } else if (stringArray[i].compareTo(LF) == 0) {
+ if (cr && lf && cr2) {
+ compressedString.append(stringArray[i]);
+ } else if (lf) {
+ if (nonSpace) {
+ compressedString.append(LF);
+ nonSpace = false;
+ }
+ compressedString.append(stringArray[i]);
+ } else
+ lf = true;
+ } else if ((stringArray[i].compareTo(SPACE) != 0) && (stringArray[i].compareTo(TAB) != 0) && (stringArray[i].compareTo(FF) != 0)) {
+ if (compressedString.length() > 0)
+ compressedString.append(SPACE);
+ compressedString.append(stringArray[i]);
+
+ cr = false;
+ lf = false;
+ cr2 = false;
+ nonSpace = true;
+ }
+ }
+ }
+
+ return compressedString.toString();
+ }
+
+ protected boolean firstStructuredDocumentRegionContainsLineDelimiters(XMLNode node) {
+ boolean result = false;
+
+ if (node != null) {
+ IStructuredDocumentRegion firstStructuredDocumentRegion = node.getFirstStructuredDocumentRegion();
+ if (firstStructuredDocumentRegion != null && firstStructuredDocumentRegion.getText() != null) {
+ String firstStructuredDocumentRegionText = firstStructuredDocumentRegion.getText();
+ result = StringUtils.containsLineDelimiter(firstStructuredDocumentRegionText);
+ }
+ }
+
+ return result;
+ }
+
+ public void format(Node node) {
+ IStructuredFormatContraints formatContraints = getFormatContraints();
+
+ format(node, formatContraints);
+ }
+
+ public void format(Node node, IStructuredFormatContraints formatContraints) {
+ if (formatContraints.getFormatWithSiblingIndent())
+ formatContraints.setCurrentIndent(getSiblingIndent(node));
+
+ if (node instanceof XMLNode)
+ formatNode((XMLNode) node, formatContraints);
+ }
+
+ protected void formatIndentationAfterNode(XMLNode node, IStructuredFormatContraints formatContraints) {
+ if (node != null) {
+ XMLNode nextSibling = (XMLNode) node.getNextSibling();
+ IStructuredDocument doc = node.getModel().getStructuredDocument();
+ int line = doc.getLineOfOffset(node.getEndOffset());
+ String lineDelimiter = doc.getLineDelimiter();
+ try {
+ lineDelimiter = doc.getLineDelimiter(line);
+ if (lineDelimiter == null)
+ lineDelimiter = ""; //$NON-NLS-1$
+ } catch (BadLocationException exception) {
+ throw new SourceEditingRuntimeException(exception);
+ }
+ String tagName = node.getNodeName();
+
+ if (node.getParentNode() != null) {
+ if (node.getParentNode().getNodeType() == Node.DOCUMENT_NODE)
+ if (nextSibling != null)
+ if (nextSibling.getNodeType() == Node.TEXT_NODE)
+ getFormatter(nextSibling).format(nextSibling, formatContraints);
+ else if (nextSibling.getNodeType() == Node.COMMENT_NODE) {
+ // do nothing
+ } else {
+ String lineIndent = formatContraints.getCurrentIndent();
+ insertAfterNode(node, lineDelimiter + lineIndent);
+ }
+ else {
+ }
+
+ else if (nextSibling != null)
+ if (nextSibling.getNodeType() == Node.TEXT_NODE)
+ getFormatter(nextSibling).format(nextSibling, formatContraints);
+ else if (nextSibling.getNodeType() == Node.COMMENT_NODE) {
+ // do nothing
+ } else {
+ String lineIndent = formatContraints.getCurrentIndent();
+ insertAfterNode(node, lineDelimiter + lineIndent);
+ }
+ else {
+ XMLNode indentNode = getParentIndentNode(node);
+ String lineIndent = getNodeIndent(indentNode);
+ XMLNode lastChild = getDeepestChildNode(node);
+ boolean clearAllBlankLines = formatContraints.getClearAllBlankLines();
+
+ if (lastChild != null) {
+ if ((lastChild.getNodeType() == Node.TEXT_NODE) && (lastChild.getNodeValue().endsWith(lineDelimiter + lineIndent))) {
+ // this text node already ends with the requested
+ // indentation
+ }
+
+ else if ((lastChild.getNodeType() == Node.TEXT_NODE) && (lastChild.getNodeValue() != null && lastChild.getNodeValue().endsWith(lineDelimiter)))
+ if (clearAllBlankLines) {
+ replaceNodeValue(lastChild, lineDelimiter + lineIndent);
+ } else {
+ // append indentation
+ insertAfterNode(lastChild, lineIndent);
+ }
+ else if (lastChild.getNodeType() == Node.TEXT_NODE)
+ if (lastChild.getNodeValue().length() == 0) {
+ // replace
+ replaceNodeValue(lastChild, lineDelimiter + lineIndent);
+ } else {
+ // append indentation
+ insertAfterNode(lastChild, lineDelimiter + lineIndent);
+ }
+ else {
+ // append indentation
+ insertAfterNode(lastChild, lineDelimiter + lineIndent);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected void formatIndentationBeforeNode(XMLNode node, IStructuredFormatContraints formatContraints) {
+ if (node != null) {
+ XMLNode previousSibling = (XMLNode) node.getPreviousSibling();
+ IStructuredDocument doc = node.getModel().getStructuredDocument();
+ int line = doc.getLineOfOffset(node.getStartOffset());
+ String lineDelimiter = doc.getLineDelimiter();
+ try {
+ if (line > 0) {
+ lineDelimiter = doc.getLineDelimiter(line - 1);
+ if (lineDelimiter == null)
+ lineDelimiter = ""; //$NON-NLS-1$
+ }
+ } catch (BadLocationException exception) {
+ throw new SourceEditingRuntimeException(exception);
+ }
+ String lineIndent = formatContraints.getCurrentIndent();
+ String tagName = node.getNodeName();
+
+ if (node.getParentNode() != null) {
+ if (node.getParentNode().getNodeType() == Node.DOCUMENT_NODE) {
+ if (previousSibling != null)
+ if (previousSibling.getNodeType() == Node.TEXT_NODE)
+ getFormatter(previousSibling).format(previousSibling, formatContraints);
+ else {
+ insertBeforeNode(node, lineDelimiter + lineIndent);
+ }
+ } else {
+ if (previousSibling == null || previousSibling.getNodeType() != Node.TEXT_NODE) {
+ // 261968 - formatting tag without closing bracket:
+ // <t1><t1
+ // 265673 - Null ptr in formatIndentationBeforeNode
+ int prevEndNodeOffset = -1;
+ int prevEndRegionOffset = -1;
+ if (previousSibling != null) {
+ prevEndNodeOffset = previousSibling.getEndOffset();
+ IStructuredDocumentRegion endRegion = previousSibling.getEndStructuredDocumentRegion();
+ if (endRegion != null) {
+ prevEndRegionOffset = endRegion.getTextEndOffset();
+ }
+ }
+ if ((previousSibling == null) || (prevEndNodeOffset != -1 && prevEndNodeOffset == prevEndRegionOffset)) {
+ insertBeforeNode(node, lineDelimiter + lineIndent);
+ }
+
+ } else {
+ if (previousSibling.getNodeValue().length() == 0) {
+ // replace
+ replaceNodeValue(previousSibling, lineDelimiter + lineIndent);
+ } else {
+ // append indentation
+ if (!previousSibling.getNodeValue().endsWith(lineDelimiter + lineIndent)) {
+ if (previousSibling.getNodeValue().endsWith(lineDelimiter)) {
+ insertAfterNode(previousSibling, lineIndent);
+ } else
+ getFormatter(previousSibling).format(previousSibling, formatContraints);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected void formatNode(XMLNode node, IStructuredFormatContraints formatContraints) {
+ if (node != null && (fProgressMonitor == null || !fProgressMonitor.isCanceled())) {
+ // format indentation before node
+ formatIndentationBeforeNode(node, formatContraints);
+
+ // format indentation after node
+ formatIndentationAfterNode(node, formatContraints);
+ }
+ }
+
+ /**
+ * This method will compute the correct indentation after this node
+ * depending on the indentations of its sibling nodes and parent node. Not
+ * needed anymore?
+ */
+ protected void formatTrailingText(XMLNode node, IStructuredFormatContraints formatContraints) {
+ String lineDelimiter = node.getModel().getStructuredDocument().getLineDelimiter();
+ String lineIndent = formatContraints.getCurrentIndent();
+ String parentLineIndent = getNodeIndent(node.getParentNode());
+ boolean clearAllBlankLines = formatContraints.getClearAllBlankLines();
+
+ if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE)) {
+ XMLNode nextSibling = (XMLNode) node.getNextSibling();
+ if ((nextSibling != null) && (nextSibling.getNodeType() == Node.TEXT_NODE)) {
+ String nextSiblingText = nextSibling.getNodeValue();
+ if (nextSibling.getNextSibling() == null)
+ if ((nextSibling.getParentNode().getNodeType() == Node.DOCUMENT_NODE) && (nextSiblingText.trim().length() == 0))
+ // delete spaces at the end of the document
+ replaceNodeValue(nextSibling, EMPTY_STRING);
+ else
+ // replace the text node with parent indentation
+ replaceNodeValue(nextSibling, lineDelimiter + parentLineIndent);
+ else
+ // replace the text node with indentation
+ replaceNodeValue(nextSibling, lineDelimiter + lineIndent);
+ } else {
+ if (nextSibling == null) {
+ lineIndent = parentLineIndent;
+
+ if (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)
+ if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter + lineIndent))) {
+ // this text node already ends with the requested
+ // indentation
+ }
+
+ else if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter)))
+ if (clearAllBlankLines)
+ replaceNodeValue(node, lineDelimiter + lineIndent);
+ else
+ // append indentation
+ insertAfterNode(node, lineIndent);
+ else if (node.getNodeType() == Node.TEXT_NODE)
+ if (node.getNodeValue().length() == 0)
+ // replace
+ replaceNodeValue(node, lineDelimiter + lineIndent);
+ else
+ // append indentation
+ if (!node.getNodeValue().endsWith(lineDelimiter + lineIndent))
+ if (node.getNodeValue().endsWith(lineDelimiter))
+ insertAfterNode(node, lineIndent);
+ else
+ insertAfterNode(node, lineDelimiter + lineIndent);
+ else
+ replaceNodeValue(node, lineDelimiter + lineIndent);
+ } else {
+ if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter + lineIndent))) {
+ // this text node already ends with the requested
+ // indentation
+ }
+
+ else if ((node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().endsWith(lineDelimiter)))
+ if (clearAllBlankLines)
+ replaceNodeValue(node, lineDelimiter + lineIndent);
+ else
+ // append indentation
+ insertAfterNode(node, lineIndent);
+ else if (node.getNodeType() == Node.TEXT_NODE)
+ if (node.getNodeValue().length() == 0)
+ // replace
+ replaceNodeValue(node, lineDelimiter + lineIndent);
+ else
+ // append indentation
+ insertAfterNode(node, lineDelimiter + lineIndent);
+ else
+ // append indentation
+ insertAfterNode(node, lineDelimiter + lineIndent);
+ }
+ }
+ }
+ }
+
+ protected String getCompressedNodeText(XMLNode node, IStructuredFormatContraints formatContraints) {
+ return compressSpaces(getNodeText(node), formatContraints);
+ }
+
+ protected XMLNode getDeepestChildNode(XMLNode node) {
+ XMLNode result = null;
+ XMLNode lastChild = (XMLNode) node.getLastChild();
+
+ if (lastChild == null)
+ result = node;
+ else {
+ result = getDeepestChildNode(lastChild);
+
+ if ((result.getNodeType() == Node.TEXT_NODE || result.getNodeType() == Node.COMMENT_NODE) && !isEndTagMissing(node))
+ result = node;
+ }
+
+ return result;
+ }
+
+ public IStructuredFormatContraints getFormatContraints() {
+ if (fFormatContraints == null) {
+ fFormatContraints = new StructuredFormatContraints();
+
+ fFormatContraints.setClearAllBlankLines(getFormatPreferences().getClearAllBlankLines());
+ }
+
+ return fFormatContraints;
+ }
+
+ public IStructuredFormatPreferences getFormatPreferences() {
+ if (fFormatPreferences == null) {
+ fFormatPreferences = new StructuredFormatPreferencesXML();
+
+ Preferences preferences = getModelPreferences();
+ if (preferences != null) {
+ fFormatPreferences.setLineWidth(preferences.getInt(CommonModelPreferenceNames.LINE_WIDTH));
+ ((IStructuredFormatPreferencesXML) fFormatPreferences).setSplitMultiAttrs(preferences.getBoolean(CommonModelPreferenceNames.SPLIT_MULTI_ATTRS));
+ fFormatPreferences.setClearAllBlankLines(preferences.getBoolean(CommonModelPreferenceNames.CLEAR_ALL_BLANK_LINES));
+
+ if (preferences.getBoolean(CommonModelPreferenceNames.INDENT_USING_TABS))
+ fFormatPreferences.setIndent("\t"); //$NON-NLS-1$
+ else {
+ int tabWidth = getModelManagerPlugin().getPluginPreferences().getInt(CommonModelPreferenceNames.TAB_WIDTH);
+ String indent = ""; //$NON-NLS-1$
+ for (int i = 0; i < tabWidth; i++) {
+ indent += " "; //$NON-NLS-1$
+ }
+ fFormatPreferences.setIndent(indent);
+ }
+ }
+ }
+
+ return fFormatPreferences;
+ }
+
+ protected IStructuredFormatter getFormatter(XMLNode node) {
+ // 262135 - NPE during format of empty document
+ if (node == null)
+ return null;
+
+ short nodeType = ((Node) node).getNodeType();
+ IStructuredFormatter formatter = null;
+ switch (nodeType) {
+ case Node.ELEMENT_NODE : {
+ formatter = new ElementNodeFormatter();
+ break;
+ }
+ case Node.TEXT_NODE : {
+ if (node instanceof CDATASectionImpl)
+ formatter = new NodeFormatter();
+ else
+ formatter = new TextNodeFormatter();
+ break;
+ }
+ case Node.COMMENT_NODE : {
+ formatter = new CommentNodeFormatter();
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ formatter = new NodeFormatter();
+ break;
+ }
+ case Node.DOCUMENT_NODE : {
+ formatter = new DocumentNodeFormatter();
+ break;
+ }
+ default : {
+ formatter = new NodeFormatter();
+ }
+ }
+
+ // init fomatter
+ formatter.setFormatPreferences(getFormatPreferences());
+ formatter.setProgressMonitor(fProgressMonitor);
+
+ return formatter;
+ }
+
+ protected int getIndentationLength(String indent) {
+ // TODO Kit : The calculation of IndentationLength is not correct
+ // here.
+ // nodeIndentation may contain tabs. Multiply by 4 temporarily to get
+ // approx. width.
+ // Need to re-work.
+
+ int indentationLength = 0;
+
+ for (int i = 0; i < indent.length(); i++) {
+ if (indent.substring(i, i + 1).compareTo(TAB) == 0)
+ indentationLength += 4;
+ else
+ indentationLength++;
+ }
+
+ return indentationLength;
+ }
+
+ private IModelManagerPlugin getModelManagerPlugin() {
+
+ IModelManagerPlugin plugin = (IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID);
+ return plugin;
+ }
+
+ protected Preferences getModelPreferences() {
+ return XMLModelPlugin.getDefault().getPluginPreferences();
+ }
+
+ /**
+ * This method will find the indentation for this node. It will search
+ * backwards starting from the beginning of the node until a character
+ * other than a space or a tab is found. If this node is null or it's a
+ * document node or it's a first level node (node's parent is a document
+ * node) the default empty string will be returned as the indentation.
+ */
+ protected String getNodeIndent(Node node) {
+ String result = EMPTY_STRING;
+
+ if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && (node.getParentNode() != null) && (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)) {
+ XMLNode siblingTextNode = (XMLNode) node.getPreviousSibling();
+ if ((siblingTextNode != null) && (siblingTextNode.getNodeType() == Node.TEXT_NODE)) {
+ // find the indentation
+ String siblingText = siblingTextNode.getNodeValue();
+ int siblingTextLength = siblingText.length();
+ if ((siblingText != null) && (siblingTextLength > 0) && ((siblingText.charAt(siblingTextLength - 1) == SPACE_CHAR) || (siblingText.charAt(siblingTextLength - 1) == TAB_CHAR))) {
+ int searchIndex = siblingTextLength - 1;
+ while ((searchIndex >= 0) && ((siblingText.charAt(searchIndex) == SPACE_CHAR) || (siblingText.charAt(searchIndex) == TAB_CHAR)))
+ searchIndex--;
+
+ if (searchIndex < siblingTextLength)
+ result = siblingText.substring(searchIndex + 1, siblingTextLength);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ protected String getNodeName(XMLNode node) {
+ return node.getNodeName();
+ }
+
+ protected String getNodeText(XMLNode node) {
+ String text = null;
+
+ if ((node instanceof org.eclipse.wst.xml.core.internal.document.CharacterDataImpl) && !(node instanceof org.eclipse.wst.xml.core.internal.document.CommentImpl) && !(node instanceof org.eclipse.wst.xml.core.internal.document.CDATASectionImpl) && !isJSPTag(node))
+ text = ((org.eclipse.wst.xml.core.internal.document.CharacterDataImpl) node).getSource();
+ else
+ text = node.getFirstStructuredDocumentRegion().getText();
+
+ return text;
+ }
+
+ protected XMLNode getParentIndentNode(XMLNode node) {
+ XMLNode result = null;
+ XMLNode parentNode = (XMLNode) node.getParentNode();
+
+ if (parentNode.getNodeType() == Node.DOCUMENT_NODE)
+ result = parentNode;
+ else {
+ ITextRegion region = parentNode.getLastStructuredDocumentRegion().getFirstRegion();
+ if (region.getType() == XMLRegionContext.XML_END_TAG_OPEN)
+ result = parentNode;
+ else
+ result = getParentIndentNode(parentNode);
+ }
+
+ return result;
+ }
+
+ /**
+ * This method will find the indentation for a node sibling to this node.
+ * It will try to find a sibling node before this node first. If there is
+ * no sibling node before this node, it will try to find a sibling node
+ * after this node. If still not found, we will check if this node is
+ * already indented from its parent. If yes, this node's indentation will
+ * be used. Otherwise, the parent node's indentation plus one indentation
+ * will be used. If this node is null or it's a document node or it's a
+ * first level node (node's parent is a document node) the default empty
+ * string will be returned as the indentation.
+ */
+ protected String getSiblingIndent(Node node) {
+ String result = EMPTY_STRING;
+
+ if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && (node.getParentNode() != null) && (node.getParentNode().getNodeType() != Node.DOCUMENT_NODE)) {
+ // find the text node before the previous non-text sibling
+ // if that's not found, we will try the text node before the next
+ // non-text sibling
+ XMLNode sibling = (XMLNode) node.getPreviousSibling();
+ while ((sibling != null) && (sibling.getNodeType() == Node.TEXT_NODE || sibling.getNodeType() == Node.COMMENT_NODE)) {
+ if (sibling.getNodeType() == Node.COMMENT_NODE && sibling.getPreviousSibling() != null && sibling.getPreviousSibling().getNodeType() == Node.TEXT_NODE && StringUtils.containsLineDelimiter(sibling.getPreviousSibling().getNodeValue()))
+ break;
+ sibling = (XMLNode) sibling.getPreviousSibling();
+ }
+ if (sibling == null) {
+ sibling = (XMLNode) node.getNextSibling();
+ while ((sibling != null) && (sibling.getNodeType() == Node.TEXT_NODE))
+ sibling = (XMLNode) sibling.getNextSibling();
+ }
+ String singleIndent = getFormatPreferences().getIndent();
+ String parentLineIndent = getNodeIndent(node.getParentNode());
+
+ if (sibling != null) {
+ String siblingIndent = getNodeIndent(sibling);
+ if (siblingIndent.length() > 0)
+ result = siblingIndent;
+ else {
+ String nodeIndent = getNodeIndent(node);
+ if (nodeIndent.length() > parentLineIndent.length())
+ // this node is indented from its parent, its
+ // indentation will be used
+ result = nodeIndent;
+ else
+ result = parentLineIndent + singleIndent;
+ }
+ } else {
+ String nodeIndent = getNodeIndent(node);
+ if (nodeIndent.length() > parentLineIndent.length())
+ // this node is indented from its parent, its indentation
+ // will be used
+ result = nodeIndent;
+ else
+ result = parentLineIndent + singleIndent;
+ }
+ }
+
+ return result;
+ }
+
+ protected void insertAfterNode(XMLNode node, String string) {
+ XMLModel structuredModel = node.getModel();
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+ int offset = node.getEndOffset();
+ int length = 0;
+
+ // 261968 - formatting tag without closing bracket: <t1><t1
+ if (node.getEndStructuredDocumentRegion() != null) {
+ offset = node.getEndStructuredDocumentRegion().getTextEndOffset();
+ length = node.getEndOffset() - offset;
+ }
+ replace(structuredDocument, offset, length, string);
+ }
+
+ protected void insertBeforeNode(XMLNode node, String string) {
+ XMLModel structuredModel = node.getModel();
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+ replace(structuredDocument, node.getStartOffset(), 0, string);
+ }
+
+ /**
+ * Allowing the INodeAdapter to compare itself against the type allows it
+ * to return true in more than one case.
+ */
+ public boolean isAdapterForType(Object type) {
+ return type.equals(IStructuredFormatter.class);
+ }
+
+ protected boolean isEndTagMissing(XMLNode node) {
+ boolean result = false;
+
+ if ((node != null) && (node.getNodeType() != Node.DOCUMENT_NODE) && !isJSPTag(node)) {
+ IStructuredDocumentRegion startTagStructuredDocumentRegion = node.getFirstStructuredDocumentRegion();
+ IStructuredDocumentRegion endTagStructuredDocumentRegion = node.getLastStructuredDocumentRegion();
+
+ ITextRegion startTagNameRegion = null;
+ if (startTagStructuredDocumentRegion.getRegions().size() > 1)
+ startTagNameRegion = startTagStructuredDocumentRegion.getRegions().get(1);
+ ITextRegion endTagNameRegion = null;
+ if (endTagStructuredDocumentRegion.getRegions().size() > 1)
+ endTagNameRegion = endTagStructuredDocumentRegion.getRegions().get(1);
+
+ ITextRegionList startTagRegions = startTagStructuredDocumentRegion.getRegions();
+ if (startTagNameRegion == endTagNameRegion && startTagNameRegion != null && (startTagRegions.get(0)).getType() != XMLRegionContext.XML_END_TAG_OPEN && (startTagRegions.get(startTagRegions.size() - 1).getType()) != XMLRegionContext.XML_EMPTY_TAG_CLOSE)
+ // end tag missing
+ result = true;
+ }
+
+ return result;
+ }
+
+ protected boolean isJSPTag(XMLNode node) {
+ boolean result = false;
+
+ IStructuredDocumentRegion flatNode = node.getFirstStructuredDocumentRegion();
+ // in some cases, the nodes exists, but hasn't been associated with
+ // a flatnode yet (the screen updates can be initiated on a different
+ // thread,
+ // so the request for a flatnode can come in before the node is fully
+ // formed.
+ // if the flatnode is null, we'll just allow the defaults to apply.
+ // (html adapter in this case).
+ if (flatNode != null) {
+ String flatNodeType = flatNode.getType();
+ if ((flatNodeType == XMLJSPRegionContexts.JSP_CONTENT) || (flatNodeType == XMLJSPRegionContexts.JSP_EXPRESSION_OPEN) || (flatNodeType == XMLJSPRegionContexts.JSP_SCRIPTLET_OPEN) || (flatNodeType == XMLJSPRegionContexts.JSP_DECLARATION_OPEN) || (flatNodeType == XMLJSPRegionContexts.JSP_DIRECTIVE_CLOSE) || (flatNodeType == XMLJSPRegionContexts.JSP_DIRECTIVE_NAME) || (flatNodeType == XMLJSPRegionContexts.JSP_DIRECTIVE_OPEN) || (flatNodeType == XMLJSPRegionContexts.JSP_CLOSE)) {
+ result = true;
+ }
+ }
+
+ return result;
+ }
+
+ protected boolean nodeHasSiblings(XMLNode node) {
+ return (node.getPreviousSibling() != null) || (node.getNextSibling() != null);
+ }
+
+ /**
+ * Node changed. No format should be performed automatically.
+ */
+ public void notifyChanged(org.eclipse.wst.sse.core.INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ }
+
+ protected void removeRegionSpaces(XMLNode node, IStructuredDocumentRegion flatNode, ITextRegion region) {
+ if ((region != null) && (region instanceof ContextRegion || region instanceof TagNameRegion) && (flatNode.getEndOffset(region) > flatNode.getTextEndOffset(region))) {
+ XMLModel structuredModel = node.getModel();
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+
+ replace(structuredDocument, flatNode.getTextEndOffset(region), flatNode.getEndOffset(region) - flatNode.getTextEndOffset(region), EMPTY_STRING);
+ }
+ }
+
+ /**
+ * This method will replace the string at offset and length with a new
+ * string. If the string to be replaced is the same as the new string, the
+ * string will not be replaced.
+ */
+ protected void replace(IStructuredDocument structuredDocument, int offset, int length, String string) {
+ try {
+ String structuredDocumentString = structuredDocument.get(offset, length);
+ if (structuredDocumentString.compareTo(string) != 0)
+ structuredDocument.replaceText(structuredDocument, offset, length, string);
+ } catch (BadLocationException exception) {
+ throw new SourceEditingRuntimeException(exception);
+ }
+ }
+
+ /**
+ * This method will replace the node value with a new string. If the node
+ * value to be replaced is the same as the new string, the node value will
+ * not be replaced.
+ */
+ protected void replaceNodeValue(XMLNode node, String string) {
+ XMLModel structuredModel = node.getModel();
+ IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+ int offset = node.getStartOffset();
+ int length = node.getEndOffset() - node.getStartOffset();
+
+ try {
+ String structuredDocumentString = structuredDocument.get(offset, length);
+ if (structuredDocumentString.compareTo(string) != 0)
+ replace(structuredDocument, offset, length, string);
+ } catch (BadLocationException exception) {
+ throw new SourceEditingRuntimeException(exception);
+ }
+ }
+
+ public void setFormatPreferences(IStructuredFormatPreferences formatPreferences) {
+ fFormatPreferences = formatPreferences;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.format.IStructuredFormatter#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ fProgressMonitor = monitor;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/StructuredFormatPreferencesXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/StructuredFormatPreferencesXML.java
new file mode 100644
index 0000000000..079ae41c29
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/StructuredFormatPreferencesXML.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.format;
+
+import org.eclipse.wst.sse.core.format.StructuredFormatPreferences;
+
+public class StructuredFormatPreferencesXML extends StructuredFormatPreferences implements IStructuredFormatPreferencesXML {
+ private boolean fSplitMultiAttrs;
+
+ public boolean getSplitMultiAttrs() {
+ return fSplitMultiAttrs;
+ }
+
+ public void setSplitMultiAttrs(boolean splitMultiAttrs) {
+ fSplitMultiAttrs = splitMultiAttrs;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/TextNodeFormatter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/TextNodeFormatter.java
new file mode 100644
index 0000000000..1d428e9de2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/format/TextNodeFormatter.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.format;
+
+import java.util.Vector;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.core.format.IStructuredFormatContraints;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.Node;
+
+
+public class TextNodeFormatter extends NodeFormatter {
+ protected void formatNode(XMLNode node, IStructuredFormatContraints formatContraints) {
+ if (node != null) {
+ IStructuredDocument doc = node.getModel().getStructuredDocument();
+ int line = doc.getLineOfOffset(node.getStartOffset());
+ String lineDelimiter = doc.getLineDelimiter();
+ try {
+ lineDelimiter = doc.getLineDelimiter(line);
+ if (lineDelimiter == null)
+ lineDelimiter = ""; //$NON-NLS-1$
+ } catch (BadLocationException exception) {
+ throw new SourceEditingRuntimeException(exception);
+ }
+ int lineWidth = getFormatPreferences().getLineWidth();
+ XMLNode parentNode = (XMLNode) node.getParentNode();
+ XMLNode nextSibling = (XMLNode) node.getNextSibling();
+ String nodeIndentation = formatContraints.getCurrentIndent();
+
+ // compute current available line width
+ int currentAvailableLineWidth = 0;
+ try {
+ int nodeNameOffset = node.getStartOffset();
+ int lineOffset = node.getStructuredDocument().getLineInformationOfOffset(nodeNameOffset).getOffset();
+ String text = node.getStructuredDocument().get(lineOffset, nodeNameOffset - lineOffset);
+ int usedWidth = getIndentationLength(text);
+ currentAvailableLineWidth = getFormatPreferences().getLineWidth() - usedWidth;
+ } catch (BadLocationException exception) {
+ throw new SourceEditingRuntimeException(exception);
+ }
+
+ String compressedText = getCompressedNodeText(node, formatContraints);
+
+ if (((compressedText.length() <= (currentAvailableLineWidth - node.getParentNode().getNodeName().length() - 3) && !StringUtils.containsLineDelimiter(compressedText)) && (!nodeHasSiblings(node) || (!StringUtils.containsLineDelimiter(node.getNodeValue()) && node.getNextSibling() != null && node.getNextSibling().getNodeType() == Node.COMMENT_NODE && !StringUtils.containsLineDelimiter(node.getNextSibling().getNodeValue()))) && !firstStructuredDocumentRegionContainsLineDelimiters((XMLNode) node.getParentNode())) || node.getStartStructuredDocumentRegion().getStartOffset() == 0) {
+ // enough space
+ // and text has no line delimiters
+ // and (node has no siblings or followed by inline comment)
+ // and
+ // parentFirstStructuredDocumentRegionContainsLineDelimiters
+
+ if (isEndTagMissing(parentNode)) {
+ parentNode = (XMLNode) parentNode.getParentNode();
+ while (isEndTagMissing(parentNode))
+ parentNode = (XMLNode) parentNode.getParentNode();
+
+ // add parent's indentation to end
+ nodeIndentation = getNodeIndent(parentNode);
+
+ if (!compressedText.endsWith(lineDelimiter + nodeIndentation)) {
+ compressedText = StringUtils.appendIfNotEndWith(compressedText, lineDelimiter);
+ compressedText = StringUtils.appendIfNotEndWith(compressedText, nodeIndentation);
+ }
+ }
+
+ if ((parentNode != null) && (parentNode.getNodeType() == Node.DOCUMENT_NODE) && (node.getNodeValue().length() > 0) && (node.getNodeValue().trim().length() == 0) && ((node.getPreviousSibling() == null) || (node.getNextSibling() == null)))
+ // delete spaces at the beginning or end of the document
+ compressedText = EMPTY_STRING;
+
+ replaceNodeValue(node, compressedText);
+ } else {
+ // not enough space, need to reflow text
+
+ currentAvailableLineWidth = lineWidth - getIndentationLength(nodeIndentation);
+ Vector vector = reflowText(compressedText, currentAvailableLineWidth);
+ int vectorSize = vector.size();
+ String reflowedText = new String();
+
+ for (int i = 0; i < vectorSize; i++) {
+ if (((String) vector.elementAt(i)).trim().length() > 0)
+ reflowedText = reflowedText + lineDelimiter + nodeIndentation + (String) vector.elementAt(i);
+ else
+ reflowedText = reflowedText + lineDelimiter;
+ }
+
+ if (node.getNextSibling() == null) {
+ if (isEndTagMissing(parentNode)) {
+ // don't add indentation to end if parent end tag is
+ // missing
+ }
+
+ else {
+ // add parent's indentation to end
+ nodeIndentation = getNodeIndent(parentNode);
+
+ if (!reflowedText.endsWith(lineDelimiter + nodeIndentation)) {
+ reflowedText = StringUtils.appendIfNotEndWith(reflowedText, lineDelimiter);
+ reflowedText = StringUtils.appendIfNotEndWith(reflowedText, nodeIndentation);
+ }
+ }
+ } else {
+ if (!reflowedText.endsWith(lineDelimiter + nodeIndentation)) {
+ // not already ended with the expected indentation
+
+ if (node.getNextSibling().getNodeType() == Node.COMMENT_NODE) {
+ // add indentation to end if
+ // currentTextEndsWithLineDelimiter
+ // or followed by multiLineComment
+
+ String nodeText = getNodeText(node);
+ int indexOfLastLineDelimiter = StringUtils.indexOfLastLineDelimiter(nodeText);
+ boolean currentTextEndsWithLineDelimiter = indexOfLastLineDelimiter != -1;
+ if (currentTextEndsWithLineDelimiter) {
+ // no more non blank character after the last
+ // line delimiter
+ currentTextEndsWithLineDelimiter = StringUtils.indexOfNonblank(nodeText, indexOfLastLineDelimiter) == -1;
+ }
+
+ String nodeValue = node.getNextSibling().getNodeValue();
+ boolean multiLineComment = StringUtils.containsLineDelimiter(nodeValue);
+
+ if (currentTextEndsWithLineDelimiter || multiLineComment) {
+ reflowedText = StringUtils.appendIfNotEndWith(reflowedText, lineDelimiter);
+ reflowedText = StringUtils.appendIfNotEndWith(reflowedText, nodeIndentation);
+ }
+ } else {
+ // not a comment, just add add indentation to end
+ reflowedText = StringUtils.appendIfNotEndWith(reflowedText, lineDelimiter);
+ reflowedText = StringUtils.appendIfNotEndWith(reflowedText, nodeIndentation);
+ }
+ }
+ }
+
+ replaceNodeValue(node, reflowedText);
+ }
+
+ }
+ }
+
+ protected Vector reflowText(String text, int availableWidth) {
+ String[] stringArray = null;
+ boolean clearAllBlankLines = getFormatPreferences().getClearAllBlankLines();
+
+ if (clearAllBlankLines)
+ stringArray = StringUtils.asArray(text);
+ else
+ stringArray = StringUtils.asArray(text, DELIMITERS, true);
+
+ Vector output = new Vector();
+ if ((stringArray != null) && (stringArray.length > 0)) {
+ StringBuffer buffer = new StringBuffer();
+ if (stringArray[0].compareTo(CR) != 0)
+ buffer.append(stringArray[0]);
+ int bufferLength = stringArray[0].toString().length();
+ boolean cr = stringArray[0].compareTo(CR) == 0;
+
+ for (int i = 1; i < stringArray.length; i++) {
+ String eachString = stringArray[i];
+ if ((eachString.compareTo(SPACE) != 0) && (eachString.compareTo(TAB) != 0) && (eachString.compareTo(FF) != 0)) {
+ if ((bufferLength + 1 + eachString.length() > availableWidth) || (eachString.compareTo(CR) == 0) || (eachString.compareTo(LF) == 0)) {
+ if ((eachString.compareTo(LF) == 0) && cr) {
+ // do nothing
+ } else {
+ output.add(buffer.toString());
+ buffer = new StringBuffer();
+ bufferLength = 0;
+ }
+ cr = eachString.compareTo(CR) == 0;
+ } else if (buffer.toString().trim().length() > 0) {
+ buffer.append(SPACE);
+ bufferLength++;
+ }
+ if ((eachString.compareTo(CR) != 0) && (eachString.compareTo(LF) != 0)) {
+ buffer.append(eachString);
+ bufferLength = bufferLength + eachString.length();
+ }
+ }
+ }
+ output.add(buffer.toString());
+ } else
+ output.add(text);
+
+ return output;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/DebugAdapterFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/DebugAdapterFactory.java
new file mode 100644
index 0000000000..4275c5047d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/DebugAdapterFactory.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal;
+
+import java.util.ArrayList;
+
+import org.eclipse.wst.sse.core.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.PropagatingAdapterFactory;
+
+
+public class DebugAdapterFactory extends AbstractAdapterFactory implements PropagatingAdapterFactory {
+
+ /**
+ * Constructor for PageDirectiveWatcherFactory.
+ */
+ public DebugAdapterFactory() {
+ this(IDebugAdapter.class, true);
+ }
+
+ /**
+ * Constructor for PageDirectiveWatcherFactory.
+ *
+ * @param adapterKey
+ * @param registerAdapters
+ */
+ public DebugAdapterFactory(Object adapterKey, boolean registerAdapters) {
+ super(adapterKey, registerAdapters);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.PropagatingAdapterFactory#addContributedFactories(org.eclipse.wst.sse.core.AdapterFactory)
+ */
+ public void addContributedFactories(AdapterFactory factory) {
+ //none expected
+ }
+
+ public AdapterFactory copy() {
+ return new DebugAdapterFactory(this.adapterKey, this.shouldRegisterAdapter);
+ }
+
+ protected INodeAdapter createAdapter(INodeNotifier target) {
+ EveryNodeDebugAdapter result = null;
+ result = EveryNodeDebugAdapter.getInstance();
+ return result;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.AdapterFactory#isFactoryForType(java.lang.Object)
+ */
+ public boolean isFactoryForType(Object type) {
+
+ return IDebugAdapter.class == type;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.PropagatingAdapterFactory#setContributedFactories(java.util.ArrayList)
+ */
+ public void setContributedFactories(ArrayList list) {
+ // none expected
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/EveryNodeDebugAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/EveryNodeDebugAdapter.java
new file mode 100644
index 0000000000..dc238974fc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/EveryNodeDebugAdapter.java
@@ -0,0 +1,274 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal;
+
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.wst.sse.core.IModelStateListener;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.events.AboutToBeChangeEvent;
+import org.eclipse.wst.sse.core.events.IModelAboutToBeChangedListener;
+import org.eclipse.wst.sse.core.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.events.NewDocumentEvent;
+import org.eclipse.wst.sse.core.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.xml.core.document.XMLNode;
+
+
+/**
+ * Purely for use in debugging
+ */
+public class EveryNodeDebugAdapter implements IDebugAdapter {
+
+ static class InternalDocumentListener implements IDocumentListener {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+ */
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ Debug.println("IdocumentAboutToBeChanged: " + event); //$NON-NLS-1$
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+ */
+ public void documentChanged(DocumentEvent event) {
+ Debug.println("IdocumentChanged: " + event); //$NON-NLS-1$
+
+ }
+
+ }
+
+ static class InternalModelStateListener implements IModelStateListener {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.IModelStateListener#modelAboutToBeChanged(org.eclipse.wst.sse.core.IStructuredModel)
+ */
+ public void modelAboutToBeChanged(IStructuredModel model) {
+ Debug.println("modelAboutToBeChanged: " + model); //$NON-NLS-1$
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.IModelStateListener#modelChanged(org.eclipse.wst.sse.core.IStructuredModel)
+ */
+ public void modelChanged(IStructuredModel model) {
+ Debug.println("modelChanged: " + model); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.IModelStateListener#modelDirtyStateChanged(org.eclipse.wst.sse.core.IStructuredModel,
+ * boolean)
+ */
+ public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
+ Debug.println("modelDirtyStateChanged: " + model); //$NON-NLS-1$
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.IModelStateListener#modelResourceDeleted(org.eclipse.wst.sse.core.IStructuredModel)
+ */
+ public void modelResourceDeleted(IStructuredModel model) {
+ Debug.println("modelResourceDeleted: " + model); //$NON-NLS-1$
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.IModelStateListener#modelResourceMoved(org.eclipse.wst.sse.core.IStructuredModel,
+ * org.eclipse.wst.sse.core.IStructuredModel)
+ */
+ public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) {
+ Debug.println("modelResourceMoved: " + "oldModel: " + oldModel + "newModel: " + newModel); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ }
+
+ static class InternalStructuredDocumentAboutToChange implements IModelAboutToBeChangedListener {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.events.IModelAboutToBeChangedListener#modelAboutToBeChanged(org.eclipse.wst.sse.core.events.AboutToBeChangeEvent)
+ */
+ public void modelAboutToBeChanged(AboutToBeChangeEvent structuredDocumentEvent) {
+ Debug.println("structuredDocumentAboutToBeChanged: " + structuredDocumentEvent); //$NON-NLS-1$
+
+ }
+
+ }
+
+ static class InternalStructuredDocumentListener implements IStructuredDocumentListener {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#newModel(org.eclipse.wst.sse.core.events.NewDocumentContentEvent)
+ */
+ public void newModel(NewDocumentEvent structuredDocumentEvent) {
+ Debug.println("structuredDocumentChanged - newModel: " + structuredDocumentEvent); //$NON-NLS-1$
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#noChange(org.eclipse.wst.sse.core.events.NoChangeEvent)
+ */
+ public void noChange(NoChangeEvent structuredDocumentEvent) {
+ Debug.println("structuredDocumentChanged - noChange: " + structuredDocumentEvent); //$NON-NLS-1$
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#nodesReplaced(org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent)
+ */
+ public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
+ Debug.println("structuredDocumentChanged - nodesReplaced: " + structuredDocumentEvent); //$NON-NLS-1$
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#regionChanged(org.eclipse.wst.sse.core.events.RegionChangedEvent)
+ */
+ public void regionChanged(RegionChangedEvent structuredDocumentEvent) {
+ Debug.println("structuredDocumentChanged - regionChanged: " + structuredDocumentEvent); //$NON-NLS-1$
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#regionsReplaced(org.eclipse.wst.sse.core.events.RegionsReplacedEvent)
+ */
+ public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) {
+ Debug.println("structuredDocumentChanged - regionsReplaced: " + structuredDocumentEvent); //$NON-NLS-1$
+
+ }
+
+ }
+
+ private static EveryNodeDebugAdapter singletonInstance;
+
+ public static EveryNodeDebugAdapter getInstance() {
+ if (singletonInstance == null) {
+ singletonInstance = new EveryNodeDebugAdapter();
+ }
+ return singletonInstance;
+ }
+
+ InternalDocumentListener fInternalDocumentListener;
+ InternalModelStateListener fInternalModelStateListener;
+ InternalStructuredDocumentAboutToChange fInternalStructuredDocumentAboutToChange;
+ InternalStructuredDocumentListener fInternalStructuredDocumentListener;
+ IStructuredModel fModel;
+
+ /**
+ *
+ */
+ public EveryNodeDebugAdapter() {
+ super();
+ fInternalDocumentListener = new InternalDocumentListener();
+ fInternalStructuredDocumentAboutToChange = new InternalStructuredDocumentAboutToChange();
+ fInternalStructuredDocumentListener = new InternalStructuredDocumentListener();
+ fInternalModelStateListener = new InternalModelStateListener();
+ }
+
+ /**
+ * @param target
+ */
+ public EveryNodeDebugAdapter(INodeNotifier target) {
+ this();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.INodeAdapter#isAdapterForType(java.lang.Object)
+ */
+ public boolean isAdapterForType(Object type) {
+ return (type == IDebugAdapter.class);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.INodeAdapter#notifyChanged(org.eclipse.wst.sse.core.INodeNotifier,
+ * int, java.lang.Object, java.lang.Object, java.lang.Object, int)
+ */
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ if (notifier instanceof XMLNode) {
+ setModel(((XMLNode) notifier).getModel());
+ }
+ Debug.println("notifier: " + notifier + " " + INodeNotifier.EVENT_TYPE_STRINGS[eventType] + " changedFeature: " + changedFeature + " oldValue: " + oldValue + " newValue: " + newValue + " pos: " + pos); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.internal.IDebugAdapter#setDocument(org.eclipse.wst.sse.core.text.IStructuredDocument)
+ */
+ private void setModel(IStructuredModel structuredModel) {
+ if (fModel == structuredModel)
+ return;
+
+ if (fModel != null) {
+ fModel.removeModelStateListener(fInternalModelStateListener);
+ //
+ IStructuredDocument structuredDocument = fModel.getStructuredDocument();
+ if (structuredDocument != null) {
+ structuredDocument.removeDocumentListener(fInternalDocumentListener);
+ structuredDocument.removeDocumentAboutToChangeListener(fInternalStructuredDocumentAboutToChange);
+ structuredDocument.removeDocumentChangedListener(fInternalStructuredDocumentListener);
+ }
+ }
+ fModel = structuredModel;
+ if (fModel != null) {
+
+ fModel.addModelStateListener(fInternalModelStateListener);
+ //
+ IStructuredDocument structuredDocument = fModel.getStructuredDocument();
+ if (structuredDocument != null) {
+ structuredDocument.addDocumentListener(fInternalDocumentListener);
+ structuredDocument.addDocumentAboutToChangeListener(fInternalStructuredDocumentAboutToChange);
+ structuredDocument.addDocumentChangedListener(fInternalStructuredDocumentListener);
+ }
+ }
+
+
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/IDebugAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/IDebugAdapter.java
new file mode 100644
index 0000000000..50b902514e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/IDebugAdapter.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal;
+
+import org.eclipse.wst.sse.core.INodeAdapter;
+
+
+public interface IDebugAdapter extends INodeAdapter {
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ByteReader.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ByteReader.java
new file mode 100644
index 0000000000..e5f04fa496
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/ByteReader.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * This is an "adapter" class, simply to get in input stream to act like a
+ * reader. We could not use InputStreamReader directly because its internal
+ * buffers are not controllable, and it sometimes pulls too much out of input
+ * stream (even when it wasn't needed for our purposes).
+ *
+ * The use of this class is highly specialized and by not means meant to be
+ * general purpose. Its use is restricted to those cases where the input
+ * stream can be regarded as ascii just long enough to determine what the real
+ * encoding should be.
+ */
+
+public class ByteReader extends Reader {
+
+ /** Default byte buffer size (2048). */
+ public static final int DEFAULT_BUFFER_SIZE = 2048;
+
+ protected byte[] fBuffer;
+
+ protected InputStream fInputStream;
+
+ protected ByteReader() {
+ super();
+ }
+
+ public ByteReader(InputStream inputStream) {
+ this(inputStream, DEFAULT_BUFFER_SIZE);
+ if (!inputStream.markSupported()) {
+ throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+ }
+ }
+
+ public ByteReader(InputStream inputStream, int size) {
+ fInputStream = inputStream;
+ if (!inputStream.markSupported()) {
+ throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+ }
+ fBuffer = new byte[size];
+
+ }
+
+ public void close() throws IOException {
+ fInputStream.close();
+ }
+
+ public void mark(int readAheadLimit) throws IOException {
+ fInputStream.mark(readAheadLimit);
+ }
+
+ public boolean markSupported() {
+ return true;
+ }
+
+ public int read() throws IOException {
+ int b0 = fInputStream.read();
+ return (b0 & 0x00FF);
+ }
+
+ public int read(char ch[], int offset, int length) throws IOException {
+ if (length > fBuffer.length) {
+ length = fBuffer.length;
+ }
+
+ int count = fInputStream.read(fBuffer, 0, length);
+
+ for (int i = 0; i < count; i++) {
+ int b0 = fBuffer[i];
+ // the 0x00FF is to "lose" the negative bits filled in the byte to
+ // int conversion
+ // (and which would be there if cast directly from byte to char).
+ char c0 = (char) (b0 & 0x00FF);
+ ch[i] = c0;
+ }
+ return count;
+ }
+
+ public boolean ready() throws IOException {
+ return fInputStream.available() > 0;
+ }
+
+ public void reset() throws IOException {
+ fInputStream.reset();
+ }
+
+ public long skip(long n) throws IOException {
+ return fInputStream.skip(n);
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/EncodingParserConstants.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/EncodingParserConstants.java
new file mode 100644
index 0000000000..7e12f93503
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/EncodingParserConstants.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+
+public interface EncodingParserConstants {
+
+ final String EOF = "EOF"; //$NON-NLS-1$
+ final String InvalidTerminatedStringValue = "InvalidTerminatedStringValue"; //$NON-NLS-1$
+ final String InvalidTermintatedUnDelimitedStringValue = "InvalidTermintatedUnDelimitedStringValue"; //$NON-NLS-1$
+ final String MAX_CHARS_REACHED = "MAX_CHARS_REACHED"; //$NON-NLS-1$
+ final String StringValue = "strval"; //$NON-NLS-1$
+ final String UnDelimitedStringValue = "UnDelimitedStringValue"; //$NON-NLS-1$
+ String UTF16BE = "UTF16BE"; //$NON-NLS-1$
+ String UTF16LE = "UTF16LE"; //$NON-NLS-1$
+
+
+ String UTF83ByteBOM = "UTF83ByteBOM"; //$NON-NLS-1$
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/HeadParserToken.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/HeadParserToken.java
new file mode 100644
index 0000000000..0f14b8b570
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/HeadParserToken.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+public class HeadParserToken {
+ private int fStart;
+
+ private String fText;
+ private String fType;
+
+ protected HeadParserToken() {
+ super();
+ }
+
+ public HeadParserToken(String type, int start, String text) {
+ this();
+ fType = type;
+ fStart = start;
+ fText = text;
+
+ }
+
+ public String getText() {
+ return fText;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return ("text: " + fText + " offset: " + fStart + " type: " + fType); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/IntStack.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/IntStack.java
new file mode 100644
index 0000000000..1d1052d850
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/IntStack.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+/*
+ *
+ * A non-resizable class implementing the behavior of java.util.Stack, but
+ * directly for the <code> integer </code> primitive.
+ */
+import java.util.EmptyStackException;
+
+public class IntStack {
+ private int[] list = null;
+
+ private int size = 0;
+
+ public IntStack() {
+ this(100);
+ }
+
+ public IntStack(int maxdepth) {
+ super();
+ list = new int[maxdepth];
+ initialize();
+ }
+
+ public void clear() {
+ initialize();
+ }
+
+ public boolean empty() {
+ return size == 0;
+ }
+
+ public int get(int slot) {
+ return list[slot];
+ }
+
+ private void initialize() {
+ for (int i = 0; i < list.length; i++)
+ list[i] = -1;
+ }
+
+ /**
+ * Returns the int at the top of the stack without removing it
+ *
+ * @return int at the top of this stack.
+ * @exception EmptyStackException
+ * when empty.
+ */
+ public int peek() {
+ if (size == 0)
+ throw new EmptyStackException();
+ return list[size - 1];
+ }
+
+ /**
+ * Removes and returns the int at the top of the stack
+ *
+ * @return int at the top of this stack.
+ * @exception EmptyStackException
+ * when empty.
+ */
+ public int pop() {
+ int value = peek();
+ list[size - 1] = -1;
+ size--;
+ return value;
+ }
+
+ /**
+ * Pushes an item onto the top of this stack.
+ *
+ * @param newValue -
+ * the int to be pushed onto this stack.
+ * @return the <code>newValue</code> argument.
+ */
+ public int push(int newValue) {
+ if (size == list.length) {
+ throw new StackOverflowError();
+ }
+ list[size++] = newValue;
+ return newValue;
+ }
+
+ public int size() {
+ return list.length;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLDeclDetector.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLDeclDetector.java
new file mode 100644
index 0000000000..5843f61c4f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLDeclDetector.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+
+public class XMLDeclDetector {
+ private static final int MAX_BUF_SIZE = 1024 * 2;
+ private static final int MAX_MARK_SIZE = 1024 * 2;
+ protected boolean fHeaderParsed;
+ private boolean fIsXML;
+ protected Reader fReader;
+ //private boolean DEBUG = false;
+ private XMLHeadTokenizer fTokenizer;
+
+ private boolean canHandleAsUnicodeStream(String tokenType) {
+ boolean canHandleAsUnicodeStream = false;
+ if (tokenType == EncodingParserConstants.UTF83ByteBOM) {
+ canHandleAsUnicodeStream = true;
+ //fUnicode = "UTF-8"; //$NON-NLS-1$
+ } else if (tokenType == EncodingParserConstants.UTF16BE) {
+ canHandleAsUnicodeStream = true;
+ //fUnicode = "UTF-16BE"; //$NON-NLS-1$
+ } else if (tokenType == EncodingParserConstants.UTF16LE) {
+ canHandleAsUnicodeStream = true;
+ //fUnicode = "UTF-16"; //$NON-NLS-1$
+ }
+ return canHandleAsUnicodeStream;
+ }
+
+ final private void ensureInputSet() {
+ if (fReader == null) {
+ throw new IllegalStateException("input must be set before use"); //$NON-NLS-1$
+ }
+ }
+
+ //private String fUnicode;
+
+ /**
+ * @return Returns the tokenizer.
+ */
+ private XMLHeadTokenizer getTokenizer() {
+ if (fTokenizer == null) {
+ fTokenizer = new XMLHeadTokenizer();
+ }
+ return fTokenizer;
+ }
+
+ /**
+ * @return Returns the isXML.
+ */
+ public boolean isXML() throws IOException {
+ ensureInputSet();
+ if (!fHeaderParsed) {
+ parseInput();
+ }
+ return fIsXML;
+ }
+
+ private void parseInput() throws IOException {
+ XMLHeadTokenizer tokenizer = getTokenizer();
+ tokenizer.reset(fReader);
+ HeadParserToken token = null;
+ String tokenType = null;
+ do {
+ token = tokenizer.getNextToken();
+ tokenType = token.getType();
+ if (canHandleAsUnicodeStream(tokenType)) {
+ fReader.reset();
+ // this is (obviously) not always true.
+ // TODO: need to fix so we "remember" original iFile or
+ // inputstream, and
+ // create appropriate InputStreamReader.
+ // I'm not sure what to do for the set(reader) case ... if its
+ // even relevent.
+ // plus, ensure against infinite loops!
+ fIsXML = true;
+ //fReader = new InputStreamReader(fReader, fUnicode);
+ // parseInput();
+ } else {
+ if (tokenType == XMLHeadTokenizerConstants.XMLDelEncoding) {
+ fIsXML = true;
+ }
+ }
+ } while (tokenizer.hasMoreTokens());
+
+ }
+
+ private void resetAll() {
+ fReader = null;
+ fHeaderParsed = false;
+ fIsXML = false;
+ //fUnicode = null;
+
+ }
+
+ public void set(IFile iFile) throws CoreException {
+ resetAll();
+ InputStream inputStream = iFile.getContents(true);
+ InputStream resettableStream = new BufferedInputStream(inputStream, MAX_BUF_SIZE);
+ resettableStream.mark(MAX_MARK_SIZE);
+ set(resettableStream);
+ }
+
+ public void set(InputStream inputStream) {
+ resetAll();
+ fReader = new ByteReader(inputStream);
+ try {
+ fReader.mark(MAX_MARK_SIZE);
+ } catch (IOException e) {
+ // impossible, since we know ByteReader supports marking
+ throw new Error(e);
+ }
+ }
+
+ /**
+ * Note: this is not part of interface to help avoid confusion ... it
+ * expected this Reader is a well formed character reader ... that is, its
+ * all ready been determined to not be a unicode marked input stream. And,
+ * its assumed to be in the correct position, at position zero, ready to
+ * read first character.
+ */
+ public void set(Reader reader) {
+ resetAll();
+ fReader = reader;
+ if (!fReader.markSupported()) {
+ fReader = new BufferedReader(fReader);
+ }
+
+ try {
+ fReader.mark(MAX_MARK_SIZE);
+ } catch (IOException e) {
+ // impossble, since we just checked if markable
+ throw new Error(e);
+ }
+
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizer.java
new file mode 100644
index 0000000000..b4a9b6ebba
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizer.java
@@ -0,0 +1,1222 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+/* The following code was generated by JFlex 1.2.2 on 4/6/04 11:13 PM */
+
+/*nlsXXX*/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+import java.io.IOException;
+import java.io.Reader;
+
+
+
+/**
+ * This class is a scanner generated by <a
+ * href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex </a> 1.2.2
+ * on 4/6/04 11:13 PM from the specification file
+ * <tt>file:/D:/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizer.jflex</tt>
+ */
+public class XMLHeadTokenizer {
+
+ /** this character denotes the end of file */
+ final public static int YYEOF = -1;
+
+ /** lexical states */
+ final public static int YYINITIAL = 0;
+ final public static int UnDelimitedString = 10;
+ final public static int DQ_STRING = 6;
+ final public static int SQ_STRING = 8;
+ final public static int ST_XMLDecl = 2;
+ final public static int QuotedAttributeValue = 4;
+
+ /**
+ * YY_LEXSTATE[l] is the state in the DFA for the lexical state l
+ * YY_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
+ * beginning of a line l is of the form l = 2*k, k a non negative integer
+ */
+ private final static int YY_LEXSTATE[] = {0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6};
+
+ /**
+ * Translates characters to character classes
+ */
+ final private static String yycmap_packed = "\11\0\1\6\1\7\2\0\1\11\22\0\1\6\1\0\1\27\2\0" + "\1\31\1\0\1\30\24\0\1\12\1\10\1\26\1\13\3\0\1\21" + "\1\23\1\17\1\0\1\25\1\0\1\24\2\0\1\16\1\15\1\20" + "\1\22\10\0\1\14\12\0\1\21\1\23\1\17\1\0\1\25\1\0" + "\1\24\2\0\1\16\1\15\1\20\1\22\10\0\1\14\102\0\1\4" + "\3\0\1\5\17\0\1\3\16\0\1\1\20\0\1\3\16\0\1\1" + "\1\2\170\0\1\2\ufe87\0";
+
+ /**
+ * Translates characters to character classes
+ */
+ final private static char[] yycmap = yy_unpack_cmap(yycmap_packed);
+
+
+ /* error codes */
+ final private static int YY_UNKNOWN_ERROR = 0;
+ final private static int YY_ILLEGAL_STATE = 1;
+ final private static int YY_NO_MATCH = 2;
+ final private static int YY_PUSHBACK_2BIG = 3;
+
+ /* error messages for the codes above */
+ final private static String YY_ERROR_MSG[] = {"Unkown internal scanner error", "Internal error: unknown state", "Error: could not match input", "Error: pushback value was too large"};
+
+ /** the input device */
+ private java.io.Reader yy_reader;
+
+ /** the current state of the DFA */
+ private int yy_state;
+
+ /** the current lexical state */
+ private int yy_lexical_state = YYINITIAL;
+
+ /**
+ * this buffer contains the current text to be matched and is the source
+ * of the yytext() string
+ */
+ private char yy_buffer[] = new char[16384];
+
+ /** the textposition at the last accepting state */
+ private int yy_markedPos;
+
+ /** the textposition at the last state to be included in yytext */
+ private int yy_pushbackPos;
+
+ /** the current text position in the buffer */
+ private int yy_currentPos;
+
+ /** startRead marks the beginning of the yytext() string in the buffer */
+ private int yy_startRead;
+
+ /**
+ * endRead marks the last character in the buffer, that has been read from
+ * input
+ */
+ private int yy_endRead;
+
+ /** number of newlines encountered up to the start of the matched text */
+ int yyline;
+
+ /** the number of characters up to the start of the matched text */
+ private int yychar;
+
+ /**
+ * the number of characters from the last newline up to the start of the
+ * matched text
+ */
+ int yycolumn;
+
+ /**
+ * yy_atBOL == true <=>the scanner is currently at the beginning of a line
+ */
+ private boolean yy_atBOL;
+
+ /** yy_atEOF == true <=>the scanner has returned a value for EOF */
+ private boolean yy_atEOF;
+
+ /** denotes if the user-EOF-code has already been executed */
+ private boolean yy_eof_done;
+
+ /* user code: */
+
+
+ private boolean hasMore = true;
+ private final static int MAX_TO_SCAN = 1000;
+ StringBuffer string = new StringBuffer();
+ // state stack for easier state handling
+ private IntStack fStateStack = new IntStack();
+ private String valueText = null;
+
+
+ public XMLHeadTokenizer() {
+ super();
+ }
+
+ public void reset(Reader in) {
+ /* the input device */
+ yy_reader = in;
+
+ /* the current state of the DFA */
+ yy_state = 0;
+
+ /* the current lexical state */
+ yy_lexical_state = YYINITIAL;
+
+ /*
+ * this buffer contains the current text to be matched and is the
+ * source of the yytext() string
+ */
+ java.util.Arrays.fill(yy_buffer, (char) 0);
+
+ /* the textposition at the last accepting state */
+ yy_markedPos = 0;
+
+ /* the textposition at the last state to be included in yytext */
+ yy_pushbackPos = 0;
+
+ /* the current text position in the buffer */
+ yy_currentPos = 0;
+
+ /* startRead marks the beginning of the yytext() string in the buffer */
+ yy_startRead = 0;
+
+ /**
+ * endRead marks the last character in the buffer, that has been read
+ * from input
+ */
+ yy_endRead = 0;
+
+ /* number of newlines encountered up to the start of the matched text */
+ yyline = 0;
+
+ /* the number of characters up to the start of the matched text */
+ yychar = 0;
+
+ /**
+ * the number of characters from the last newline up to the start of
+ * the matched text
+ */
+ yycolumn = 0;
+
+ /**
+ * yy_atBOL == true <=>the scanner is currently at the beginning of a
+ * line
+ */
+ yy_atBOL = false;
+
+ /* yy_atEOF == true <=> the scanner has returned a value for EOF */
+ yy_atEOF = false;
+
+ /* denotes if the user-EOF-code has already been executed */
+ yy_eof_done = false;
+
+
+ fStateStack.clear();
+
+ hasMore = true;
+
+ // its a little wasteful to "throw away" first char array generated
+ // by class init (via auto generated code), but we really do want
+ // a small buffer for our head parsers.
+ if (yy_buffer.length != MAX_TO_SCAN) {
+ yy_buffer = new char[MAX_TO_SCAN];
+ }
+
+
+ }
+
+
+ public final HeadParserToken getNextToken() throws IOException {
+ String context = null;
+ context = primGetNextToken();
+ HeadParserToken result = null;
+ if (valueText != null) {
+ result = createToken(context, yychar, valueText);
+ valueText = null;
+ } else {
+ result = createToken(context, yychar, yytext());
+ }
+ return result;
+ }
+
+ public final boolean hasMoreTokens() {
+ return hasMore && yychar < MAX_TO_SCAN;
+ }
+
+ private void pushCurrentState() {
+ fStateStack.push(yystate());
+
+ }
+
+ private void popState() {
+ yybegin(fStateStack.pop());
+ }
+
+ private HeadParserToken createToken(String context, int start, String text) {
+ return new HeadParserToken(context, start, text);
+ }
+
+
+
+ /**
+ * Creates a new scanner There is also a java.io.InputStream version of
+ * this constructor.
+ *
+ * @param in
+ * the java.io.Reader to read input from.
+ */
+ public XMLHeadTokenizer(java.io.Reader in) {
+ this.yy_reader = in;
+ }
+
+ /**
+ * Creates a new scanner. There is also java.io.Reader version of this
+ * constructor.
+ *
+ * @param in
+ * the java.io.Inputstream to read input from.
+ */
+ public XMLHeadTokenizer(java.io.InputStream in) {
+ this(new java.io.InputStreamReader(in));
+ }
+
+ /**
+ * Unpacks the compressed character translation table.
+ *
+ * @param packed
+ * the packed character translation table
+ * @return the unpacked character translation table
+ */
+ private static char[] yy_unpack_cmap(String packed) {
+ char[] map = new char[0x10000];
+ int i = 0; /* index in packed string */
+ int j = 0; /* index in unpacked array */
+ while (i < 128) {
+ int count = packed.charAt(i++);
+ char value = packed.charAt(i++);
+ do
+ map[j++] = value;
+ while (--count > 0);
+ }
+ return map;
+ }
+
+
+ /**
+ * Gets the next input character.
+ *
+ * @return the next character of the input stream, EOF if the end of the
+ * stream is reached.
+ * @exception IOException
+ * if any I/O-Error occurs
+ */
+ private int yy_advance() throws java.io.IOException {
+
+ /* standard case */
+ if (yy_currentPos < yy_endRead)
+ return yy_buffer[yy_currentPos++];
+
+ /* if the eof is reached, we don't need to work hard */
+ if (yy_atEOF)
+ return YYEOF;
+
+ /* otherwise: need to refill the buffer */
+
+ /* first: make room (if you can) */
+ if (yy_startRead > 0) {
+ System.arraycopy(yy_buffer, yy_startRead, yy_buffer, 0, yy_endRead - yy_startRead);
+
+ /* translate stored positions */
+ yy_endRead -= yy_startRead;
+ yy_currentPos -= yy_startRead;
+ yy_markedPos -= yy_startRead;
+ yy_pushbackPos -= yy_startRead;
+ yy_startRead = 0;
+ }
+
+ /* is the buffer big enough? */
+ if (yy_currentPos >= yy_buffer.length) {
+ /* if not: blow it up */
+ char newBuffer[] = new char[yy_currentPos * 2];
+ System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+ yy_buffer = newBuffer;
+ }
+
+ /* finally: fill the buffer with new input */
+ int numRead = yy_reader.read(yy_buffer, yy_endRead, yy_buffer.length - yy_endRead);
+
+ if (numRead == -1)
+ return YYEOF;
+
+ yy_endRead += numRead;
+
+ return yy_buffer[yy_currentPos++];
+ }
+
+
+ /**
+ * Closes the input stream.
+ */
+ final public void yyclose() throws java.io.IOException {
+ yy_atEOF = true; /* indicate end of file */
+ yy_endRead = yy_startRead; /* invalidate buffer */
+ yy_reader.close();
+ }
+
+
+ /**
+ * Returns the current lexical state.
+ */
+ final public int yystate() {
+ return yy_lexical_state;
+ }
+
+ /**
+ * Enters a new lexical state
+ *
+ * @param newState
+ * the new lexical state
+ */
+ final public void yybegin(int newState) {
+ yy_lexical_state = newState;
+ }
+
+
+ /**
+ * Returns the text matched by the current regular expression.
+ */
+ final public String yytext() {
+ return new String(yy_buffer, yy_startRead, yy_markedPos - yy_startRead);
+ }
+
+ /**
+ * Returns the length of the matched text region.
+ */
+ final public int yylength() {
+ return yy_markedPos - yy_startRead;
+ }
+
+
+ /**
+ * Reports an error that occured while scanning.
+ *
+ * @param errorCode
+ * the code of the errormessage to display
+ */
+ private void yy_ScanError(int errorCode) {
+ try {
+ System.out.println(YY_ERROR_MSG[errorCode]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println(YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+ }
+
+ // System.exit(1);
+ }
+
+
+ /**
+ * Pushes the specified amount of characters back into the input stream.
+ *
+ * They will be read again by then next call of the scanning method
+ *
+ * @param number
+ * the number of characters to be read again. This number must
+ * not be greater than yylength()!
+ */
+ private void yypushback(int number) {
+ if (number > yylength())
+ yy_ScanError(YY_PUSHBACK_2BIG);
+
+ yy_markedPos -= number;
+ }
+
+
+ /**
+ * Contains user EOF-code, which will be executed exactly once, when the
+ * end of file is reached
+ */
+ private void yy_do_eof() {
+ if (!yy_eof_done) {
+ yy_eof_done = true;
+ hasMore = false;
+
+ }
+ }
+
+
+ /**
+ * Resumes scanning until the next regular expression is matched, the end
+ * of input is encountered or an I/O-Error occurs.
+ *
+ * @return the next token
+ * @exception IOException
+ * if any I/O-Error occurs
+ */
+ public String primGetNextToken() throws java.io.IOException {
+ int yy_input;
+ int yy_action;
+
+
+ while (true) {
+
+ yychar += yylength();
+
+ yy_atBOL = yy_markedPos <= 0 || yy_buffer[yy_markedPos - 1] == '\n';
+ if (!yy_atBOL && yy_buffer[yy_markedPos - 1] == '\r') {
+ yy_atBOL = yy_advance() != '\n';
+ if (!yy_atEOF)
+ yy_currentPos--;
+ }
+
+ yy_action = -1;
+
+ yy_currentPos = yy_startRead = yy_markedPos;
+
+ if (yy_atBOL)
+ yy_state = YY_LEXSTATE[yy_lexical_state + 1];
+ else
+ yy_state = YY_LEXSTATE[yy_lexical_state];
+
+
+ yy_forAction : {
+ while (true) {
+
+ yy_input = yy_advance();
+
+ if (yy_input == YYEOF)
+ break yy_forAction;
+
+ yy_input = yycmap[yy_input];
+
+ boolean yy_isFinal = false;
+ boolean yy_noLookAhead = false;
+
+ yy_forNext : {
+ switch (yy_state) {
+ case 0 :
+ switch (yy_input) {
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 7;
+ break yy_forNext;
+ }
+
+ case 1 :
+ switch (yy_input) {
+ case 1 :
+ yy_isFinal = true;
+ yy_state = 8;
+ break yy_forNext;
+ case 2 :
+ yy_isFinal = true;
+ yy_state = 9;
+ break yy_forNext;
+ case 3 :
+ yy_isFinal = true;
+ yy_state = 10;
+ break yy_forNext;
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 11;
+ break yy_forNext;
+ case 10 :
+ yy_isFinal = true;
+ yy_state = 12;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 7;
+ break yy_forNext;
+ }
+
+ case 2 :
+ switch (yy_input) {
+ case 11 :
+ yy_isFinal = true;
+ yy_state = 13;
+ break yy_forNext;
+ case 15 :
+ yy_isFinal = true;
+ yy_state = 14;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 7;
+ break yy_forNext;
+ }
+
+ case 3 :
+ switch (yy_input) {
+ case 6 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 16;
+ break yy_forNext;
+ case 7 :
+ yy_isFinal = true;
+ yy_state = 17;
+ break yy_forNext;
+ case 23 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 18;
+ break yy_forNext;
+ case 24 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 19;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 15;
+ break yy_forNext;
+ }
+
+ case 4 :
+ switch (yy_input) {
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 21;
+ break yy_forNext;
+ case 11 :
+ yy_isFinal = true;
+ yy_state = 22;
+ break yy_forNext;
+ case 23 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 23;
+ break yy_forNext;
+ case 24 :
+ yy_isFinal = true;
+ yy_state = 24;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 20;
+ break yy_forNext;
+ }
+
+ case 5 :
+ switch (yy_input) {
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 21;
+ break yy_forNext;
+ case 24 :
+ yy_isFinal = true;
+ yy_state = 25;
+ break yy_forNext;
+ case 25 :
+ yy_isFinal = true;
+ yy_state = 26;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 20;
+ break yy_forNext;
+ }
+
+ case 6 :
+ switch (yy_input) {
+ case 11 :
+ yy_isFinal = true;
+ yy_state = 26;
+ break yy_forNext;
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 27;
+ break yy_forNext;
+ case 23 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 28;
+ break yy_forNext;
+ case 24 :
+ yy_isFinal = true;
+ yy_state = 29;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 20;
+ break yy_forNext;
+ }
+
+ case 8 :
+ switch (yy_input) {
+ case 2 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 30;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 9 :
+ switch (yy_input) {
+ case 1 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 31;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 10 :
+ switch (yy_input) {
+ case 4 :
+ yy_state = 32;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 11 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_state = 33;
+ break yy_forNext;
+ case 10 :
+ yy_state = 34;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 12 :
+ switch (yy_input) {
+ case 11 :
+ yy_state = 35;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 13 :
+ switch (yy_input) {
+ case 22 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 36;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 14 :
+ switch (yy_input) {
+ case 16 :
+ yy_state = 37;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 16 :
+ switch (yy_input) {
+ case 6 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 16;
+ break yy_forNext;
+ case 7 :
+ yy_state = 38;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 15;
+ break yy_forNext;
+ }
+
+ case 17 :
+ switch (yy_input) {
+ case 6 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 16;
+ break yy_forNext;
+ case 7 :
+ yy_state = 38;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 15;
+ break yy_forNext;
+ }
+
+ case 22 :
+ switch (yy_input) {
+ case 22 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 39;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 24 :
+ switch (yy_input) {
+ case 10 :
+ yy_state = 40;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 25 :
+ switch (yy_input) {
+ case 10 :
+ yy_state = 40;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 26 :
+ switch (yy_input) {
+ case 22 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 41;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 29 :
+ switch (yy_input) {
+ case 10 :
+ yy_state = 40;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 32 :
+ switch (yy_input) {
+ case 5 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 42;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 33 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_state = 33;
+ break yy_forNext;
+ case 10 :
+ yy_state = 34;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 34 :
+ switch (yy_input) {
+ case 11 :
+ yy_state = 35;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 35 :
+ switch (yy_input) {
+ case 12 :
+ yy_state = 43;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 37 :
+ switch (yy_input) {
+ case 17 :
+ yy_state = 44;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 38 :
+ switch (yy_input) {
+ case 6 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 16;
+ break yy_forNext;
+ case 7 :
+ yy_state = 38;
+ break yy_forNext;
+ default :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 15;
+ break yy_forNext;
+ }
+
+ case 40 :
+ switch (yy_input) {
+ case 24 :
+ yy_isFinal = true;
+ yy_noLookAhead = true;
+ yy_state = 21;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 43 :
+ switch (yy_input) {
+ case 13 :
+ yy_state = 45;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 44 :
+ switch (yy_input) {
+ case 18 :
+ yy_state = 46;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 45 :
+ switch (yy_input) {
+ case 14 :
+ yy_state = 47;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 46 :
+ switch (yy_input) {
+ case 19 :
+ yy_state = 48;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 47 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 49;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 48 :
+ switch (yy_input) {
+ case 20 :
+ yy_state = 50;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 49 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 49;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 50 :
+ switch (yy_input) {
+ case 16 :
+ yy_state = 51;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 51 :
+ switch (yy_input) {
+ case 21 :
+ yy_state = 52;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 52 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_state = 52;
+ break yy_forNext;
+ case 8 :
+ yy_isFinal = true;
+ yy_state = 53;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ case 53 :
+ switch (yy_input) {
+ case 6 :
+ case 7 :
+ case 9 :
+ yy_isFinal = true;
+ yy_state = 53;
+ break yy_forNext;
+ default :
+ break yy_forAction;
+ }
+
+ default :
+ yy_ScanError(YY_ILLEGAL_STATE);
+ break;
+ }
+ }
+
+ if (yy_isFinal) {
+ yy_action = yy_state;
+ yy_markedPos = yy_currentPos;
+ if (yy_noLookAhead)
+ break yy_forAction;
+ }
+
+ }
+ }
+
+
+ switch (yy_action) {
+
+ case 25 : {
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.StringValue;
+ }
+ case 55 :
+ break;
+ case 21 : {
+ yypushback(1);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.InvalidTerminatedStringValue;
+ }
+ case 56 :
+ break;
+ case 15 :
+ case 16 : {
+ yypushback(1);
+ yybegin(UnDelimitedString);
+ string.setLength(0);
+ }
+ case 57 :
+ break;
+ case 28 :
+ case 29 : {
+ yypushback(1);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;
+ }
+ case 58 :
+ break;
+ case 39 : {
+ yypushback(2);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.InvalidTerminatedStringValue;
+ }
+ case 59 :
+ break;
+ case 41 : {
+ yypushback(2);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.InvalidTerminatedStringValue;
+ }
+ case 60 :
+ break;
+ case 7 :
+ case 8 :
+ case 9 :
+ case 10 :
+ case 11 :
+ case 12 :
+ case 13 :
+ case 14 :
+ case 17 : {
+ if (yychar > MAX_TO_SCAN) {
+ hasMore = false;
+ return EncodingParserConstants.MAX_CHARS_REACHED;
+ }
+ }
+ case 61 :
+ break;
+ case 30 : {
+ if (yychar == 0) {
+ hasMore = false;
+ return EncodingParserConstants.UTF16BE;
+ }
+ }
+ case 62 :
+ break;
+ case 31 : {
+ if (yychar == 0) {
+ hasMore = false;
+ return EncodingParserConstants.UTF16LE;
+ }
+ }
+ case 63 :
+ break;
+ case 42 : {
+ if (yychar == 0) {
+ hasMore = false;
+ return EncodingParserConstants.UTF83ByteBOM;
+ }
+ }
+ case 64 :
+ break;
+ case 49 : {
+ if (yychar == 0) {
+ yybegin(ST_XMLDecl);
+ return XMLHeadTokenizerConstants.XMLDeclStart;
+ }
+ }
+ case 65 :
+ break;
+ case 36 : {
+ yybegin(YYINITIAL);
+ hasMore = false;
+ return XMLHeadTokenizerConstants.XMLDeclEnd;
+ }
+ case 66 :
+ break;
+ case 53 : {
+ pushCurrentState();
+ yybegin(QuotedAttributeValue);
+ return XMLHeadTokenizerConstants.XMLDelEncoding;
+ }
+ case 67 :
+ break;
+ case 23 : {
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.StringValue;
+ }
+ case 68 :
+ break;
+ case 20 :
+ case 22 :
+ case 24 :
+ case 26 : {
+ string.append(yytext());
+ }
+ case 69 :
+ break;
+ case 19 : {
+ yybegin(SQ_STRING);
+ string.setLength(0);
+ }
+ case 70 :
+ break;
+ case 18 : {
+ yybegin(DQ_STRING);
+ string.setLength(0);
+ }
+ case 71 :
+ break;
+ case 27 : {
+ yypushback(1);
+ popState();
+ valueText = string.toString();
+ return EncodingParserConstants.UnDelimitedStringValue;
+ }
+ case 72 :
+ break;
+ default :
+ if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+ yy_atEOF = true;
+ yy_do_eof();
+ {
+ hasMore = false;
+ return EncodingParserConstants.EOF;
+ }
+ } else {
+ yy_ScanError(YY_NO_MATCH);
+ }
+ }
+ }
+ }
+
+ /**
+ * Runs the scanner on input files.
+ *
+ * This main method is the debugging routine for the scanner. It prints
+ * each returned token to System.out until the end of file is reached, or
+ * an error occured.
+ *
+ * @param argv
+ * the command line, contains the filenames to run the scanner
+ * on.
+ */
+ public static void main(String argv[]) {
+ for (int i = 0; i < argv.length; i++) {
+ XMLHeadTokenizer scanner = null;
+ try {
+ scanner = new XMLHeadTokenizer(new java.io.FileReader(argv[i]));
+ } catch (java.io.FileNotFoundException e) {
+ System.out.println("File not found : \"" + argv[i] + "\"");
+ System.exit(1);
+ }
+ // catch (java.io.IOException e) {
+ // System.out.println("Error opening file \"" + argv[i] + "\"");
+ // System.exit(1);
+ // }
+ catch (ArrayIndexOutOfBoundsException e) {
+ System.out.println("Usage : java XMLHeadTokenizer <inputfile>");
+ System.exit(1);
+ }
+
+ try {
+ do {
+ System.out.println(scanner.primGetNextToken());
+ } while (!scanner.yy_atEOF);
+
+ } catch (java.io.IOException e) {
+ System.out.println("An I/O error occured while scanning :");
+ System.out.println(e);
+ System.exit(1);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ }
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizerConstants.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizerConstants.java
new file mode 100644
index 0000000000..3321348059
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/contenttype/XMLHeadTokenizerConstants.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.contenttype;
+
+
+public interface XMLHeadTokenizerConstants extends EncodingParserConstants {
+
+ final String XMLDeclEnd = "XMLDeclEnd"; //$NON-NLS-1$
+ final String XMLDeclStart = "XMLDeclStart"; //$NON-NLS-1$
+ final String XMLDelEncoding = "XMLDelEncoding"; //$NON-NLS-1$
+ // final String XMLDeclVersion = "XMLDeclVersion";
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/AttrImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/AttrImpl.java
new file mode 100644
index 0000000000..959f512544
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/AttrImpl.java
@@ -0,0 +1,756 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.document.XMLAttr;
+import org.eclipse.wst.xml.core.document.XMLCharEntity;
+import org.eclipse.wst.xml.core.document.XMLNamespace;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * AttrImpl class
+ */
+public class AttrImpl extends NodeImpl implements XMLAttr {
+ private ITextRegion equalRegion = null;
+
+ private String name = null;
+ private ITextRegion nameRegion = null;
+ private String namespaceURI = null;
+ private ElementImpl ownerElement = null;
+ private ITextRegion valueRegion = null;
+ private String valueSource = null;
+
+ /**
+ * AttrImpl constructor
+ */
+ protected AttrImpl() {
+ super();
+ }
+
+ /**
+ * AttrImpl constructor
+ *
+ * @param that
+ * AttrImpl
+ */
+ protected AttrImpl(AttrImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.name = that.name;
+ this.valueSource = that.getValueSource();
+ }
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ */
+ public Node cloneNode(boolean deep) {
+ AttrImpl cloned = new AttrImpl(this);
+ return cloned;
+ }
+
+ /**
+ */
+ protected CMAttributeDeclaration getDeclaration() {
+ ElementImpl element = (ElementImpl) getOwnerElement();
+ if (element == null)
+ return null;
+ CMElementDeclaration elementDecl = element.getDeclaration();
+ if (elementDecl == null)
+ return null;
+ CMNamedNodeMap attributes = elementDecl.getAttributes();
+ if (attributes == null)
+ return null;
+ return (CMAttributeDeclaration) attributes.getNamedItem(getName());
+ }
+
+ /**
+ * getEndOffset method
+ *
+ * @return int
+ */
+ public int getEndOffset() {
+ if (this.ownerElement == null)
+ return 0;
+ int offset = this.ownerElement.getStartOffset();
+ if (this.valueRegion != null) {
+ return (offset + this.valueRegion.getEnd());
+ }
+ if (this.equalRegion != null) {
+ return (offset + this.equalRegion.getEnd());
+ }
+ if (this.nameRegion != null) {
+ return (offset + this.nameRegion.getEnd());
+ }
+ return 0;
+ }
+
+ /**
+ * getEqualRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.ITextRegion
+ */
+ public ITextRegion getEqualRegion() {
+ return this.equalRegion;
+ }
+
+ /**
+ */
+ public String getLocalName() {
+ if (this.name == null)
+ return null;
+ int index = this.name.indexOf(':');
+ if (index < 0)
+ return this.name;
+ return this.name.substring(index + 1);
+ }
+
+ /**
+ * getName method
+ *
+ * @return java.lang.String
+ */
+ public String getName() {
+ if (this.name == null)
+ return new String();
+ return this.name;
+ }
+
+ /**
+ * getNameRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.ITextRegion
+ */
+ public ITextRegion getNameRegion() {
+ return this.nameRegion;
+ }
+
+ public int getNameRegionEndOffset() {
+ if (this.ownerElement == null)
+ return 0;
+ // assuming the firstStructuredDocumentRegion is the one that contains
+ // attributes
+ IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+ if (flatNode == null)
+ return 0;
+ return flatNode.getEndOffset(this.nameRegion);
+ }
+
+ public int getNameRegionStartOffset() {
+ if (this.ownerElement == null)
+ return 0;
+ // assuming the firstStructuredDocumentRegion is the one that contains
+ // attributes
+ IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+ if (flatNode == null)
+ return 0;
+ return flatNode.getStartOffset(this.nameRegion);
+ }
+
+ public String getNameRegionText() {
+ if (this.ownerElement == null)
+ return null;
+ // assuming the firstStructuredDocumentRegion is the one that contains
+ // attributes
+ IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+ if (flatNode == null)
+ return null;
+ return flatNode.getText(this.nameRegion);
+ }
+
+ public int getNameRegionTextEndOffset() {
+ if (this.ownerElement == null)
+ return 0;
+ // assuming the firstStructuredDocumentRegion is the one that contains
+ // attributes
+ IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+ if (flatNode == null)
+ return 0;
+ return flatNode.getTextEndOffset(this.nameRegion);
+ }
+
+ /**
+ */
+ public String getNamespaceURI() {
+ String nsAttrName = null;
+ String prefix = getPrefix();
+ if (prefix != null && prefix.length() > 0) {
+ if (prefix.equals(XMLNamespace.XMLNS)) {
+ // fixed URI
+ return XMLNamespace.XMLNS_URI;
+ }
+ nsAttrName = XMLNamespace.XMLNS_PREFIX + prefix;
+ } else {
+ String name = getName();
+ if (name != null && name.equals(XMLNamespace.XMLNS)) {
+ // fixed URI
+ return XMLNamespace.XMLNS_URI;
+ }
+ // does not inherit namespace from owner element
+ // if (this.ownerElement != null) return
+ // this.ownerElement.getNamespaceURI();
+ return this.namespaceURI;
+ }
+
+ for (Node node = this.ownerElement; node != null; node = node.getParentNode()) {
+ if (node.getNodeType() != ELEMENT_NODE)
+ break;
+ Element element = (Element) node;
+ Attr attr = element.getAttributeNode(nsAttrName);
+ if (attr != null)
+ return attr.getValue();
+ }
+
+ return this.namespaceURI;
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ return getName();
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return ATTRIBUTE_NODE;
+ }
+
+ /**
+ * getNodeValue method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeValue() {
+ return getValue();
+ }
+
+ /**
+ * getOwnerElement method
+ *
+ * @return org.w3c.dom.Element
+ */
+ public Element getOwnerElement() {
+ return this.ownerElement;
+ }
+
+ /**
+ */
+ public String getPrefix() {
+ if (this.name == null)
+ return null;
+ int index = this.name.indexOf(':');
+ if (index <= 0)
+ return null;
+ // exclude JSP tag in name
+ if (this.name.charAt(0) == '<')
+ return null;
+ return this.name.substring(0, index);
+ }
+
+ /**
+ * getSpecified method
+ *
+ * @return boolean
+ */
+ public boolean getSpecified() {
+ return true;
+ }
+
+ /**
+ * getStartOffset method
+ *
+ * @return int
+ */
+ public int getStartOffset() {
+ if (this.ownerElement == null)
+ return 0;
+ int offset = this.ownerElement.getStartOffset();
+ if (this.nameRegion != null) {
+ return (offset + this.nameRegion.getStart());
+ }
+ if (this.equalRegion != null) {
+ return (offset + this.equalRegion.getStart());
+ }
+ if (this.valueRegion != null) {
+ return (offset + this.valueRegion.getStart());
+ }
+ return 0;
+ }
+
+ /**
+ * getValue method
+ *
+ * @return java.lang.String
+ */
+ public String getValue() {
+ return getValue(getValueSource());
+ }
+
+ /**
+ * Returns value for the source
+ */
+ private String getValue(String source) {
+ if (source == null)
+ return new String();
+ if (source.length() == 0)
+ return source;
+ StringBuffer buffer = null;
+ int offset = 0;
+ int length = source.length();
+ int ref = source.indexOf('&');
+ while (ref >= 0) {
+ int end = source.indexOf(';', ref + 1);
+ if (end > ref + 1) {
+ String name = source.substring(ref + 1, end);
+ String value = getCharValue(name);
+ if (value != null) {
+ if (buffer == null)
+ buffer = new StringBuffer(length);
+ if (ref > offset)
+ buffer.append(source.substring(offset, ref));
+ buffer.append(value);
+ offset = end + 1;
+ ref = end;
+ }
+ }
+ ref = source.indexOf('&', ref + 1);
+ }
+ if (buffer == null)
+ return source;
+ if (length > offset)
+ buffer.append(source.substring(offset));
+ return buffer.toString();
+ }
+
+ /**
+ * getValueRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.ITextRegion
+ */
+ public ITextRegion getValueRegion() {
+ return this.valueRegion;
+ }
+
+ public int getValueRegionStartOffset() {
+ if (this.ownerElement == null)
+ return 0;
+ // assuming the firstStructuredDocumentRegion is the one that contains
+ // attributes
+ IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+ if (flatNode == null)
+ return 0;
+ return flatNode.getStartOffset(this.valueRegion);
+ }
+
+ public String getValueRegionText() {
+ if (this.ownerElement == null)
+ return null;
+ // assuming the firstStructuredDocumentRegion is the one that contains
+ // attributes
+ IStructuredDocumentRegion flatNode = this.ownerElement.getFirstStructuredDocumentRegion();
+ if (flatNode == null)
+ return null;
+ if (this.valueRegion == null)
+ return null;
+ return flatNode.getText(this.valueRegion);
+ }
+
+ /**
+ */
+ public String getValueSource() {
+ if (this.valueSource != null)
+ return this.valueSource;
+ // DW: 4/16/2003 due to change in structuredDocument ... we need a
+ // flatnode to
+ // get at region values. For now I'll assume this is always the first
+ // flatnode .. may need to make smarter later (e.g. to search for
+ // the flatnode that this.valueRegion belongs to.
+ // DW: 4/30/2003 For some reason, this method is getting called a lot
+ // Not sure if its a threading problem, or a fundamental error
+ // elsewhere.
+ // It needs more investigation, but in the use cases I've seen,
+ // doesn't
+ // seem to hurt to simply return null in those cases. I saw this null
+ // case,
+ // when tryint go format an XML file.
+ if (this.ownerElement == null)
+ return null;
+ IStructuredDocumentRegion ownerRegion = this.ownerElement.getFirstStructuredDocumentRegion();
+ if (ownerRegion == null)
+ return null;
+ if (this.valueRegion != null)
+ return StructuredDocumentRegionUtil.getAttrValue(ownerRegion, this.valueRegion);
+ return new String();
+ }
+
+ private String getValueSource(ElementImpl ownerElement) {
+ if (this.valueSource != null)
+ return this.valueSource;
+ // DW: 4/16/2003 due to change in structuredDocument ... we need a
+ // flatnode to
+ // get at region values. For now I'll assume this is always the first
+ // flatnode .. may need to make smarter later (e.g. to search for
+ // the flatnode that this.valueRegion belongs to.
+ if (this.valueRegion != null)
+ return StructuredDocumentRegionUtil.getAttrValue(ownerElement.getStructuredDocumentRegion(), this.valueRegion);
+ return new String();
+ }
+
+ /**
+ */
+ private String getValueSource(String value) {
+ if (value == null)
+ return null;
+ if (value.length() == 0)
+ return value;
+ StringBuffer buffer = null;
+ int offset = 0;
+ int length = value.length();
+ int amp = value.indexOf('&');
+ while (amp >= 0) {
+ if (buffer == null)
+ buffer = new StringBuffer(length + 4);
+ if (amp > offset)
+ buffer.append(value.substring(offset, amp));
+ buffer.append(XMLCharEntity.AMP_REF);
+ offset = amp + 1;
+ amp = value.indexOf('&', offset);
+ }
+ if (buffer == null)
+ return value;
+ if (length > offset)
+ buffer.append(value.substring(offset));
+ return buffer.toString();
+ }
+
+ /**
+ * Check if Attr has JSP in value
+ */
+ public boolean hasJSPValue() {
+ if (this.valueRegion == null)
+ return false;
+ if (!(this.valueRegion instanceof ITextRegionContainer))
+ return false;
+ ITextRegionList regions = ((ITextRegionContainer) this.valueRegion).getRegions();
+ if (regions == null)
+ return false;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ if (region == null)
+ continue;
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_OPEN || regionType == XMLJSPRegionContexts.JSP_SCRIPTLET_OPEN || regionType == XMLJSPRegionContexts.JSP_EXPRESSION_OPEN || regionType == XMLJSPRegionContexts.JSP_DECLARATION_OPEN || regionType == XMLJSPRegionContexts.JSP_DIRECTIVE_OPEN)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if Attr has only name but not equal sign nor value
+ */
+ public boolean hasNameOnly() {
+ return (this.nameRegion != null && this.equalRegion == null && this.valueRegion == null);
+ }
+
+ /**
+ */
+ protected final boolean hasPrefix() {
+ if (this.name == null)
+ return false;
+ if (this.name.indexOf(':') <= 0)
+ return false;
+ // exclude JSP tag in name
+ if (this.name.charAt(0) == '<')
+ return false;
+ return true;
+ }
+
+ /**
+ */
+ protected final boolean ignoreCase() {
+ if (this.ownerElement != null) {
+ if (this.ownerElement.ignoreCase()) {
+ return !hasPrefix();
+ }
+ } else {
+ DocumentImpl document = (DocumentImpl) getOwnerDocument();
+ if (document != null && document.ignoreCase()) {
+ // even in case insensitive document, if having prefix, it's
+ // case sensitive
+ return !hasPrefix();
+ }
+ }
+ return false;
+ }
+
+ /**
+ */
+ public boolean isGlobalAttr() {
+ if (hasPrefix())
+ return false;
+ if (this.ownerElement == null)
+ return false;
+ return this.ownerElement.isGlobalTag();
+ }
+
+ /**
+ */
+ public final boolean isXMLAttr() {
+ if (this.ownerElement != null) {
+ if (!this.ownerElement.isXMLTag()) {
+ return hasPrefix();
+ }
+ } else {
+ DocumentImpl document = (DocumentImpl) getOwnerDocument();
+ if (document != null && !document.isXMLType()) {
+ // even in non-XML document, if having prefix, it's XML tag
+ return hasPrefix();
+ }
+ }
+ return true;
+ }
+
+ /**
+ * matchName method
+ *
+ * @return boolean
+ * @param name
+ * java.lang.String
+ */
+ protected boolean matchName(String name) {
+ if (name == null)
+ return (this.name == null);
+ if (this.name == null)
+ return false;
+ if (!ignoreCase())
+ return this.name.equals(name);
+ return this.name.equalsIgnoreCase(name);
+ }
+
+ /**
+ * notifyValueChanged method
+ */
+ protected void notifyNameChanged() {
+ if (this.ownerElement == null)
+ return;
+ DocumentImpl document = (DocumentImpl) this.ownerElement.getContainerDocument();
+ if (document == null)
+ return;
+ XMLModelImpl model = (XMLModelImpl) document.getModel();
+ if (model == null)
+ return;
+ model.nameChanged(this);
+ }
+
+ /**
+ * notifyValueChanged method
+ */
+ protected void notifyValueChanged() {
+ if (this.ownerElement == null)
+ return;
+ DocumentImpl document = (DocumentImpl) this.ownerElement.getContainerDocument();
+ if (document == null)
+ return;
+ XMLModelImpl model = (XMLModelImpl) document.getModel();
+ if (model == null)
+ return;
+ model.valueChanged(this);
+ }
+
+ /**
+ * removeRegions method
+ */
+ void removeRegions() {
+ this.nameRegion = null;
+ this.valueRegion = null;
+ this.equalRegion = null;
+ }
+
+ /**
+ */
+ void resetRegions() {
+ this.valueSource = getValueSource();
+ removeRegions();
+ }
+
+ /**
+ */
+ void resetRegions(ElementImpl ownerElement) {
+ this.valueSource = getValueSource(ownerElement);
+ removeRegions();
+ }
+
+ /**
+ * setEqualRegion method
+ *
+ * @param equalRegion
+ * com.ibm.sed.structuredDocument.ITextRegion
+ */
+ void setEqualRegion(ITextRegion equalRegion) {
+ this.equalRegion = equalRegion;
+ }
+
+ /**
+ * setName method
+ *
+ * @param name
+ * java.lang.String
+ */
+ protected void setName(String name) {
+ String value = null;
+ int startOffset = 0;
+ if (this.ownerElement != null) {
+ value = getValue();
+ startOffset = this.ownerElement.getStartOffset();
+ this.ownerElement.notify(CHANGE, this, value, null, startOffset);
+ }
+ this.name = name;
+ if (this.ownerElement != null) {
+ this.ownerElement.notify(CHANGE, this, null, value, startOffset);
+ }
+ }
+
+ /**
+ * setNameRegion method
+ *
+ * @param nameRegion
+ * com.ibm.sed.structuredDocument.ITextRegion
+ */
+ void setNameRegion(ITextRegion nameRegion) {
+ this.nameRegion = nameRegion;
+ }
+
+ /**
+ */
+ protected void setNamespaceURI(String namespaceURI) {
+ this.namespaceURI = namespaceURI;
+ }
+
+ /**
+ * setNodeValue method
+ *
+ * @param nodeValue
+ * java.lang.String
+ */
+ public void setNodeValue(String nodeValue) throws DOMException {
+ setValue(nodeValue);
+ }
+
+ /**
+ * setOwnerElement method
+ *
+ * @param ownerElement
+ * org.w3c.dom.Element
+ */
+ protected void setOwnerElement(Element ownerElement) {
+ this.ownerElement = (ElementImpl) ownerElement;
+ }
+
+ /**
+ */
+ public void setPrefix(String prefix) throws DOMException {
+ if (this.ownerElement != null && !this.ownerElement.isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ int prefixLength = (prefix != null ? prefix.length() : 0);
+ String localName = getLocalName();
+ if (prefixLength == 0) {
+ setName(localName);
+ return;
+ }
+ if (localName == null)
+ localName = new String();
+ int localLength = localName.length();
+ StringBuffer buffer = new StringBuffer(prefixLength + 1 + localLength);
+ buffer.append(prefix);
+ buffer.append(':');
+ buffer.append(localName);
+ setName(buffer.toString());
+
+ notifyNameChanged();
+ }
+
+ /**
+ * setValue method
+ *
+ * @param value
+ * java.lang.String
+ */
+ public void setValue(String value) {
+ // Remember: as we account for "floaters" in
+ // future, remember that some are created
+ // in the natural process of implementing
+ // DOM apis.
+ // this "self notification" of about/changed,
+ // is added for this case, because it known to
+ // be called from properties pages. Should be a
+ // added to all DOM Modifiying APIs eventually.
+ try {
+ getModel().aboutToChangeModel();
+ setValueSource(getValueSource(value));
+ } finally {
+ getModel().changedModel();
+ }
+ }
+
+ /**
+ * setValueRegion method
+ *
+ * @param newValueRegion
+ * com.ibm.sed.structuredDocument.ITextRegion
+ */
+ void setValueRegion(ITextRegion valueRegion) {
+ this.valueRegion = valueRegion;
+ if (valueRegion != null)
+ this.valueSource = null;
+ }
+
+ /**
+ */
+ public void setValueSource(String source) {
+ if (this.ownerElement != null && !this.ownerElement.isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ this.valueSource = source;
+
+ notifyValueChanged();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CDATASectionImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CDATASectionImpl.java
new file mode 100644
index 0000000000..3954ca2d40
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CDATASectionImpl.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+
+/**
+ * CDATASectionImpl class
+ */
+public class CDATASectionImpl extends TextImpl implements CDATASection {
+
+ /**
+ * CDATASectionImpl constructor
+ */
+ protected CDATASectionImpl() {
+ super();
+ }
+
+ /**
+ * CDATASectionImpl constructor
+ *
+ * @param that
+ * CDATASectionImpl
+ */
+ protected CDATASectionImpl(CDATASectionImpl that) {
+ super(that);
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ CDATASectionImpl cloned = new CDATASectionImpl(this);
+ return cloned;
+ }
+
+ /**
+ * getData method
+ *
+ * @return java.lang.String
+ */
+ public String getData() throws DOMException {
+ // instead of super(TextImpl).getData(), call getCharacterData()
+ String data = getCharacterData();
+ if (data == null) {
+ data = getData(getStructuredDocumentRegion());
+ if (data == null)
+ data = new String();
+ }
+ return data;
+ }
+
+ /**
+ */
+ private String getData(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return null;
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return null;
+
+ ITextRegion contentRegion = null;
+ StringBuffer buffer = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_CDATA_OPEN || regionType == XMLRegionContext.XML_CDATA_CLOSE) {
+ continue;
+ }
+ if (contentRegion == null) { // first content
+ contentRegion = region;
+ } else { // multiple contents
+ if (buffer == null) {
+ buffer = new StringBuffer(flatNode.getText(contentRegion));
+ }
+ buffer.append(flatNode.getText(region));
+ }
+ }
+
+ if (buffer != null)
+ return buffer.toString();
+ if (contentRegion != null)
+ return flatNode.getText(contentRegion);
+ return null;
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ return "#cdata-section";//$NON-NLS-1$
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return CDATA_SECTION_NODE;
+ }
+
+ /**
+ */
+ public boolean isClosed() {
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return true; // will be generated
+ String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+ return (regionType == XMLRegionContext.XML_CDATA_CLOSE);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CMNodeUtil.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CMNodeUtil.java
new file mode 100644
index 0000000000..44ecfabad5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CMNodeUtil.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+
+/**
+ */
+public class CMNodeUtil {
+
+ /**
+ */
+ public static CMAttributeDeclaration getAttributeDeclaration(Attr attr) {
+ if (attr == null)
+ return null;
+ return ((AttrImpl) attr).getDeclaration();
+ }
+
+ /**
+ */
+ public static CMElementDeclaration getElementDeclaration(Element element) {
+ if (element == null)
+ return null;
+ return ((ElementImpl) element).getDeclaration();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterDataImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterDataImpl.java
new file mode 100644
index 0000000000..4c4a2dbc72
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CharacterDataImpl.java
@@ -0,0 +1,353 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+
+/**
+ * CharacterDataImpl class
+ */
+public abstract class CharacterDataImpl extends NodeImpl implements XMLJSPRegionContexts, CharacterData {
+
+ private String data = null;
+
+ /**
+ * CharacterDataImpl constructor
+ */
+ protected CharacterDataImpl() {
+ super();
+ }
+
+ /**
+ * CharacterDataImpl constructor
+ *
+ * @param that
+ * CharacterDataImpl
+ */
+ protected CharacterDataImpl(CharacterDataImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.data = that.getData();
+ }
+ }
+
+ /**
+ * appendData method
+ *
+ * @param arg
+ * java.lang.String
+ */
+ public void appendData(String arg) throws DOMException {
+ if (arg == null)
+ return;
+
+ String data = getData();
+ if (data == null)
+ data = arg;
+ else
+ data += arg;
+ setData(data);
+ }
+
+ /**
+ * deleteData method
+ *
+ * @param offset
+ * int
+ * @param count
+ * int
+ */
+ public void deleteData(int offset, int count) throws DOMException {
+ if (count == 0)
+ return;
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ if (count < 0 || offset < 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ String data = getData();
+ if (data == null) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ int length = data.length();
+ if (offset > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ if (offset == 0) {
+ if (count > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ if (count == length)
+ data = new String();
+ else
+ data = data.substring(count);
+ } else {
+ int end = offset + count;
+ if (end > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ if (end == length)
+ data = data.substring(0, offset);
+ else
+ data = data.substring(0, offset) + data.substring(end);
+ }
+ setData(data);
+ }
+
+ /**
+ */
+ protected final String getCharacterData() {
+ return this.data;
+ }
+
+ /**
+ * getData method
+ *
+ * @return java.lang.String
+ */
+ public String getData() throws DOMException {
+ return getCharacterData();
+ }
+
+ /**
+ * getLength method
+ *
+ * @return int
+ */
+ public int getLength() {
+ String data = getData();
+ if (data == null)
+ return 0;
+ return data.length();
+ }
+
+ /**
+ * getNodeValue method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeValue() {
+ return getData();
+ }
+
+ /**
+ * insertData method
+ *
+ * @param offset
+ * int
+ * @param arg
+ * java.lang.String
+ */
+ public void insertData(int offset, String arg) throws DOMException {
+ if (arg == null)
+ return;
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ if (offset < 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ String data = getData();
+ if (data == null) {
+ if (offset > 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ data = arg;
+ } else if (offset == 0) {
+ data = arg + data;
+ } else {
+ int length = data.length();
+ if (offset > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ if (offset == length)
+ data += arg;
+ else
+ data = data.substring(0, offset) + arg + data.substring(offset);
+ }
+ setData(data);
+ }
+
+ /**
+ * isJSPContent method
+ *
+ * @return boolean
+ */
+ public boolean isJSPContent() {
+ Node parent = getParentNode();
+ if (parent == null || parent.getNodeType() != Node.ELEMENT_NODE)
+ return false;
+ ElementImpl element = (ElementImpl) parent;
+ return element.isJSPContainer();
+ }
+
+ /**
+ * replaceData method
+ *
+ * @param offset
+ * int
+ * @param count
+ * int
+ * @param arg
+ * java.lang.String
+ */
+ public void replaceData(int offset, int count, String arg) throws DOMException {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ if (arg == null) {
+ deleteData(offset, count);
+ return;
+ }
+ if (count == 0) {
+ insertData(offset, arg);
+ return;
+ }
+ if (offset < 0 || count < 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ String data = getData();
+ if (data == null) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ } else if (offset == 0) {
+ int length = data.length();
+ if (count > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ if (count == length)
+ data = arg;
+ else
+ data = arg + data.substring(count);
+ } else {
+ int length = data.length();
+ int end = offset + count;
+ if (end > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ if (end == length)
+ data = data.substring(0, offset) + arg;
+ else
+ data = data.substring(0, offset) + arg + data.substring(end);
+ }
+ setData(data);
+ }
+
+ /**
+ */
+ void resetStructuredDocumentRegions() {
+ this.data = getData();
+ setStructuredDocumentRegion(null);
+ }
+
+ /**
+ * setData method
+ *
+ * @param data
+ * java.lang.String
+ */
+ public void setData(String data) throws DOMException {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.data = data;
+
+ notifyValueChanged();
+ }
+
+ /**
+ * setNodeValue method
+ *
+ * @param nodeValue
+ * java.lang.String
+ */
+ public void setNodeValue(String nodeValue) throws DOMException {
+ setData(nodeValue);
+ }
+
+ /**
+ */
+ void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ super.setStructuredDocumentRegion(flatNode);
+ if (flatNode != null)
+ this.data = null;
+ }
+
+ /**
+ * substringData method
+ *
+ * @return java.lang.String
+ * @param offset
+ * int
+ * @param count
+ * int
+ */
+ public String substringData(int offset, int count) throws DOMException {
+ if (count == 0)
+ return new String();
+ if (offset < 0 || count < 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ String data = getData();
+ if (data == null) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ int length = data.length();
+ if (offset == 0 && count == length)
+ return data;
+ if (offset > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ int end = offset + count;
+ if (end > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ return data.substring(offset, end);
+ }
+
+ /**
+ * toString method
+ *
+ * @return java.lang.String
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(getNodeName());
+ buffer.append('(');
+ buffer.append(getData());
+ buffer.append(')');
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode != null) {
+ buffer.append('@');
+ buffer.append(flatNode.toString());
+ }
+ return buffer.toString();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CommentImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CommentImpl.java
new file mode 100644
index 0000000000..2d8d257072
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/CommentImpl.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+
+/**
+ * CommentImpl class
+ */
+public class CommentImpl extends CharacterDataImpl implements Comment {
+
+ private boolean isJSPTag = false;
+
+ /**
+ * CommentImpl constructor
+ */
+ protected CommentImpl() {
+ super();
+ }
+
+ /**
+ * CommentImpl constructor
+ *
+ * @param that
+ * CommentImpl
+ */
+ protected CommentImpl(CommentImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.isJSPTag = that.isJSPTag;
+ }
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ CommentImpl cloned = new CommentImpl(this);
+ return cloned;
+ }
+
+ /**
+ * getData method
+ *
+ * @return java.lang.String
+ */
+ public String getData() throws DOMException {
+ String data = getCharacterData();
+ if (data == null) {
+ data = getData(getStructuredDocumentRegion());
+ if (data == null)
+ data = new String();
+ }
+ return data;
+ }
+
+ /**
+ */
+ private String getData(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return null;
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return null;
+
+ ITextRegion contentRegion = null;
+ StringBuffer buffer = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_COMMENT_OPEN || regionType == JSP_COMMENT_OPEN || regionType == XMLRegionContext.XML_COMMENT_CLOSE || regionType == JSP_COMMENT_CLOSE) {
+ continue;
+ }
+ if (contentRegion == null) { // first content
+ contentRegion = region;
+ } else { // multiple contents
+ if (buffer == null) {
+ buffer = new StringBuffer(flatNode.getText(contentRegion));
+ }
+ buffer.append(flatNode.getText(region));
+ }
+ }
+
+ if (buffer != null)
+ return buffer.toString();
+ if (contentRegion != null)
+ return flatNode.getText(contentRegion);
+ return null;
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ return "#comment";//$NON-NLS-1$
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return COMMENT_NODE;
+ }
+
+ /**
+ */
+ public boolean isClosed() {
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return true; // will be generated
+ String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+ return (regionType == XMLRegionContext.XML_COMMENT_CLOSE || regionType == XMLJSPRegionContexts.JSP_COMMENT_CLOSE);
+ }
+
+ /**
+ * isJSP method
+ *
+ * @return boolean
+ */
+ public boolean isJSPTag() {
+ return this.isJSPTag;
+ }
+
+ /**
+ * setJSPTag method
+ *
+ * @param isJSPTag
+ * boolean
+ */
+ public void setJSPTag(boolean isJSPTag) {
+ if (isJSPTag == this.isJSPTag)
+ return;
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ DocumentImpl document = (DocumentImpl) getOwnerDocument();
+ if (isJSPTag) {
+ if (document == null || !document.isJSPType())
+ return;
+ }
+
+ this.isJSPTag = isJSPTag;
+
+ if (getContainerDocument() != null) {
+ // already in the tree, update IStructuredDocument
+ setData(getData()); // calls notifyValueChanged();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentFragmentImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentFragmentImpl.java
new file mode 100644
index 0000000000..06058a549f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentFragmentImpl.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+
+
+/**
+ * DocumentFragmentImpl class
+ */
+public class DocumentFragmentImpl extends NodeContainer implements DocumentFragment {
+
+ /**
+ * DocumentFragmentImpl constructor
+ */
+ protected DocumentFragmentImpl() {
+ super();
+ }
+
+ /**
+ * DocumentFragmentImpl constructor
+ *
+ * @param that
+ * DocumentFragmentImpl
+ */
+ protected DocumentFragmentImpl(DocumentFragmentImpl that) {
+ super(that);
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ DocumentFragmentImpl cloned = new DocumentFragmentImpl(this);
+ if (deep)
+ cloneChildNodes(cloned, deep);
+ return cloned;
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ return "#document-fragment";//$NON-NLS-1$
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return DOCUMENT_FRAGMENT_NODE;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentImpl.java
new file mode 100644
index 0000000000..f4ca2cc236
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentImpl.java
@@ -0,0 +1,1073 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+// for org.apache.xerces 3.2.1
+// import org.apache.xerces.utils.XMLCharacterProperties;
+// DMW modified for XML4J 4.0.1
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.wst.common.contentmodel.CMDocument;
+import org.eclipse.wst.common.contentmodel.CMEntityDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.core.modelhandler.IModelHandler;
+import org.eclipse.wst.xml.core.NameValidator;
+import org.eclipse.wst.xml.core.commentelement.impl.CommentElementRegistry;
+import org.eclipse.wst.xml.core.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.document.JSPTag;
+import org.eclipse.wst.xml.core.document.XMLCharEntity;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Entity;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Notation;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.w3c.dom.ranges.Range;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+import org.w3c.dom.traversal.TreeWalker;
+
+
+/**
+ * DocumentImpl class
+ */
+public class DocumentImpl extends NodeContainer implements XMLDocument {
+
+ /**
+ * Internal-use only class. This class was added to better able to handle
+ * repetetive request for getElementsByTagName. The cache is cleared when
+ * ever the document changes at all, so still not real efficient,
+ */
+ class TagNameCache {
+
+ private boolean active = true;
+
+ private Map cache;
+
+ public TagNameCache() {
+ super();
+ cache = new HashMap();
+ }
+
+ /**
+ * @param b
+ */
+ public void activate(boolean b) {
+ active = b;
+ if (!b)
+ clear();
+ }
+
+ public void addItem(String tagname, NodeListImpl nodelist) {
+ if (tagname == null || nodelist == null)
+ return;
+ cache.put(tagname, nodelist);
+ }
+
+ public void clear() {
+ cache.clear();
+ }
+
+ public NodeListImpl getItem(String tagName) {
+ NodeListImpl result = null;
+ if (active) {
+ result = (NodeListImpl) cache.get(tagName);
+ // if (result != null) {
+ // System.out.println("getElementsByTagname from cache: " +
+ // tagName);
+ // }
+ }
+ return result;
+ }
+
+ }
+
+ // this is a constant just to give compile-time control over
+ // whether or not to use the cache. If, in future, its found that
+ // there are no (or few) "duplicate requests" ... then this cache
+ // is not needed.
+ private static final boolean usetagnamecache = true;
+ private DocumentTypeAdapter documentTypeAdapter = null;
+
+ private XMLModelImpl model = null;
+ private TagNameCache tagNameCache;
+
+ /**
+ * DocumentImpl constructor
+ */
+ protected DocumentImpl() {
+ super();
+ if (usetagnamecache) {
+ tagNameCache = new TagNameCache();
+ }
+ }
+
+ /**
+ * DocumentImpl constructor
+ *
+ * @param that
+ * DocumentImpl
+ */
+ protected DocumentImpl(DocumentImpl that) {
+ super(that);
+ if (usetagnamecache) {
+ tagNameCache = new TagNameCache();
+ }
+ }
+
+ /**
+ * @param b
+ */
+ void activateTagNameCache(boolean b) {
+ tagNameCache.activate(b);
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * Changes the <code>ownerDocument</code> of a node, its children, as
+ * well as the attached attribute nodes if there are any. If the node has
+ * a parent it is first removed from its parent child list. This
+ * effectively allows moving a subtree from one document to another. The
+ * following list describes the specifics for each type of node.
+ * <dl>
+ * <dt>ATTRIBUTE_NODE</dt>
+ * <dd>The <code>ownerElement</code> attribute is set to
+ * <code>null</code> and the <code>specified</code> flag is set to
+ * <code>true</code> on the adopted <code>Attr</code>. The
+ * descendants of the source <code>Attr</code> are recursively adopted.
+ * </dd>
+ * <dt>DOCUMENT_FRAGMENT_NODE</dt>
+ * <dd>The descendants of the source node are recursively adopted.</dd>
+ * <dt>DOCUMENT_NODE</dt>
+ * <dd><code>Document</code> nodes cannot be adopted.</dd>
+ * <dt>DOCUMENT_TYPE_NODE</dt>
+ * <dd><code>DocumentType</code> nodes cannot be adopted.</dd>
+ * <dt>ELEMENT_NODE</dt>
+ * <dd>Specified attribute nodes of the source element are adopted, and
+ * the generated <code>Attr</code> nodes. Default attributes are
+ * discarded, though if the document being adopted into defines default
+ * attributes for this element name, those are assigned. The descendants
+ * of the source element are recursively adopted.</dd>
+ * <dt>ENTITY_NODE</dt>
+ * <dd><code>Entity</code> nodes cannot be adopted.</dd>
+ * <dt>ENTITY_REFERENCE_NODE</dt>
+ * <dd>Only the <code>EntityReference</code> node itself is adopted,
+ * the descendants are discarded, since the source and destination
+ * documents might have defined the entity differently. If the document
+ * being imported into provides a definition for this entity name, its
+ * value is assigned.</dd>
+ * <dt>NOTATION_NODE</dt>
+ * <dd><code>Notation</code> nodes cannot be adopted.</dd>
+ * <dt>PROCESSING_INSTRUCTION_NODE, TEXT_NODE, CDATA_SECTION_NODE,
+ * COMMENT_NODE</dt>
+ * <dd>These nodes can all be adopted. No specifics.</dd>
+ * Should this method simply return null when it fails? How "exceptional"
+ * is failure for this method?Stick with raising exceptions only in
+ * exceptional circumstances, return null on failure (F2F 19 Jun 2000).Can
+ * an entity node really be adopted?No, neither can Notation nodes (Telcon
+ * 13 Dec 2000).Does this affect keys and hashCode's of the adopted
+ * subtree nodes?If so, what about readonly-ness of key and hashCode?if
+ * not, would appendChild affect keys/hashCodes or would it generate
+ * exceptions if key's are duplicate? Update: Hashcodes have been dropped.
+ * Given that the key is only unique within a document an adopted node
+ * needs to be given a new key, but what does it mean for the application?
+ *
+ * @param source
+ * The node to move into this document.
+ * @return The adopted node, or <code>null</code> if this operation
+ * fails, such as when the source node comes from a different
+ * implementation.
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if the source node is of type
+ * <code>DOCUMENT</code>,<code>DOCUMENT_TYPE</code>.
+ * <br>
+ * NO_MODIFICATION_ALLOWED_ERR: Raised when the source node
+ * is readonly.
+ * @since DOM Level 3
+ */
+ public org.w3c.dom.Node adoptNode(org.w3c.dom.Node source) throws org.w3c.dom.DOMException {
+ return null;
+ }
+
+ /**
+ * @param tagName
+ */
+ protected void checkTagNameValidity(String tagName) {
+ if (!isValidName(tagName)) {
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, createDOMExceptionMessage(DOMException.INVALID_CHARACTER_ERR, tagName));
+ }
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ DocumentImpl cloned = new DocumentImpl(this);
+ if (deep)
+ cloned.importChildNodes(this, true);
+ return cloned;
+ }
+
+ /**
+ * createAttribute method
+ *
+ * @return org.w3c.dom.Attr
+ * @param name
+ * java.lang.String
+ */
+ public Attr createAttribute(String name) throws DOMException {
+ AttrImpl attr = new AttrImpl();
+ attr.setOwnerDocument(this);
+ attr.setName(name);
+ return attr;
+ }
+
+ /**
+ */
+ public Attr createAttributeNS(String uri, String name) throws DOMException {
+ AttrImpl attr = new AttrImpl();
+ attr.setOwnerDocument(this);
+ attr.setName(name);
+ attr.setNamespaceURI(uri);
+ return attr;
+ }
+
+ /**
+ * createCDATASection method
+ *
+ * @return org.w3c.dom.CDATASection
+ * @param data
+ * java.lang.String
+ */
+ public CDATASection createCDATASection(String data) throws DOMException {
+ // allow CDATA section
+ // if (!isXMLType()) {
+ // throw new DOMException(DOMException.NOT_SUPPORTED_ERR, new
+ // String());
+ // }
+ CDATASectionImpl cdata = new CDATASectionImpl();
+ cdata.setOwnerDocument(this);
+ if (data != null)
+ cdata.setData(data);
+ return cdata;
+ }
+
+ /**
+ * createComment method
+ *
+ * @return org.w3c.dom.Comment
+ * @param data
+ * java.lang.String
+ */
+ public Comment createComment(String data) {
+ CommentImpl comment = new CommentImpl();
+ comment.setOwnerDocument(this);
+ if (data != null)
+ comment.setData(data);
+ return comment;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.model.xml.XMLDocument#createCommentElement(java.lang.String,
+ * boolean)
+ */
+ public Element createCommentElement(String tagName, boolean isJSPTag) throws DOMException {
+ if (!isJSPType() && isJSPTag) {
+ throw new DOMException(DOMException.INVALID_MODIFICATION_ERR, new String());
+ }
+ ElementImpl element = (ElementImpl) createElement(tagName);
+ element.setJSPTag(isJSPTag);
+ CommentElementRegistry registry = CommentElementRegistry.getInstance();
+ if (registry.setupCommentElement(element)) {
+ return element;
+ } else {
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, new String());
+ }
+ }
+
+ /**
+ * createDoctype method
+ *
+ * @return org.w3c.dom.DocumentType
+ * @param name
+ * java.lang.String
+ */
+ public DocumentType createDoctype(String name) {
+ DocumentTypeImpl docType = new DocumentTypeImpl();
+ docType.setOwnerDocument(this);
+ docType.setName(name);
+ return docType;
+ }
+
+ /**
+ * createDocumentFragment method
+ *
+ * @return org.w3c.dom.DocumentFragment
+ */
+ public DocumentFragment createDocumentFragment() {
+ DocumentFragmentImpl fragment = new DocumentFragmentImpl();
+ fragment.setOwnerDocument(this);
+ return fragment;
+ }
+
+ /**
+ * createElement method
+ *
+ * @return org.w3c.dom.Element
+ * @param tagName
+ * java.lang.String
+ */
+ public Element createElement(String tagName) throws DOMException {
+ checkTagNameValidity(tagName);
+
+ ElementImpl element = new ElementImpl();
+ element.setOwnerDocument(this);
+ element.setTagName(tagName);
+ return element;
+ }
+
+ /**
+ */
+ public Element createElementNS(String uri, String tagName) throws DOMException {
+ if (!isValidName(tagName)) {
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR, new String());
+ }
+
+ ElementImpl element = new ElementImpl();
+ element.setOwnerDocument(this);
+ element.setTagName(tagName);
+ element.setNamespaceURI(uri);
+ return element;
+ }
+
+ /**
+ * createEntity method
+ *
+ * @return org.w3c.dom.Entity
+ * @param name
+ * java.lang.String
+ */
+ public Entity createEntity(String name) {
+ EntityImpl entity = new EntityImpl();
+ entity.setOwnerDocument(this);
+ entity.setName(name);
+ return entity;
+ }
+
+ /**
+ * createEntityReference method
+ *
+ * @return org.w3c.dom.EntityReference
+ * @param name
+ * java.lang.String
+ */
+ public EntityReference createEntityReference(String name) throws DOMException {
+ if (!isXMLType()) {
+ throw new DOMException(DOMException.NOT_SUPPORTED_ERR, new String());
+ }
+
+ EntityReferenceImpl ref = new EntityReferenceImpl();
+ ref.setOwnerDocument(this);
+ ref.setName(name);
+ return ref;
+ }
+
+ /**
+ */
+ public NodeIterator createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) {
+ if (root == null)
+ root = this;
+ return new NodeIteratorImpl(root, whatToShow, filter);
+ }
+
+ /**
+ * createNotation method
+ *
+ * @return org.w3c.dom.Notation
+ * @param name
+ * java.lang.String
+ */
+ public Notation createNotation(String name) {
+ NotationImpl notation = new NotationImpl();
+ notation.setOwnerDocument(this);
+ notation.setName(name);
+ return notation;
+ }
+
+ /**
+ * createProcessingInstruction method
+ *
+ * @return org.w3c.dom.ProcessingInstruction
+ * @param target
+ * java.lang.String
+ * @param data
+ * java.lang.String
+ */
+ public ProcessingInstruction createProcessingInstruction(String target, String data) throws DOMException {
+ ProcessingInstructionImpl pi = new ProcessingInstructionImpl();
+ pi.setOwnerDocument(this);
+ pi.setTarget(target);
+ if (data != null)
+ pi.setData(data);
+ return pi;
+ }
+
+ /**
+ */
+ public Range createRange() {
+ return new RangeImpl();
+ }
+
+ /**
+ * createTextNode method
+ *
+ * @return org.w3c.dom.Text
+ * @param data
+ * java.lang.String
+ */
+ public Text createTextNode(String data) {
+ TextImpl text = new TextImpl();
+ text.setOwnerDocument(this);
+ text.setData(data);
+ return text;
+ }
+
+ /**
+ */
+ public TreeWalker createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) {
+ // not suppoerted
+ return null;
+ }
+
+ private DocumentType findDoctype(Node node) {
+ for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child.getNodeType() == DOCUMENT_TYPE_NODE && child instanceof DocumentType) {
+ return (DocumentType) child;
+ } else if (child.getNodeType() == ELEMENT_NODE && ((XMLElement) child).isCommentTag()) {
+ // search DOCTYPE inside of generic comment element
+ DocumentType docType = findDoctype(child);
+ if (docType != null) {
+ return docType;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private Element findDocumentElement(String docName, Node node, Node[] firstFound) {
+ for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child.getNodeType() != ELEMENT_NODE)
+ continue;
+ ElementImpl element = (ElementImpl) child;
+ if (element.isCommentTag()) {
+ Element docElement = findDocumentElement(docName, element, firstFound);
+ if (docElement != null) {
+ return docElement;
+ } else {
+ // added 'else continue' to better handle cases where
+ // there is "more than one root" element
+ // especially complicated by CommentElements, which are
+ // sometimes treated as elements, but should
+ // be treated as comments in this context.
+ continue;
+ }
+ }
+ // note: the "name" won't match in the event of a jsp tag ... but
+ // incase
+ // the name is null, we do not want the jsp element returned as
+ // documentElement
+ if (element.isJSPTag())
+ continue;
+ if (docName == null)
+ return element;
+ // use local name for namespace
+ String localName = element.getLocalName();
+ if (localName == null)
+ continue;
+ if (isXMLType()) {
+ if (localName.equals(docName))
+ return element;
+ } else {
+ if (localName.equalsIgnoreCase(docName))
+ return element;
+ }
+ if (firstFound[0] == null)
+ firstFound[0] = element;
+ }
+ return null;
+ }
+
+ /**
+ * getCharValue method
+ *
+ * @return java.lang.String
+ * @param name
+ * java.lang.String
+ */
+ protected String getCharValue(String name) {
+ if (name == null)
+ return null;
+ int length = name.length();
+ if (length == 0)
+ return null;
+
+ if (name.charAt(0) == '#') { // character reference
+ if (length == 1)
+ return null;
+ int radix = 10;
+ String s = null;
+ // now allow hexadecimal also for non XML document
+ if (name.charAt(1) == 'x') { // hexadecimal
+ radix = 16;
+ s = name.substring(2);
+ } else { // decimal
+ s = name.substring(1);
+ }
+ if (s == null || s.length() == 0)
+ return null;
+ if (s.charAt(0) == '-')
+ return null; // no minus accepted
+ char c = 0;
+ try {
+ c = (char) Integer.parseInt(s, radix);
+ } catch (NumberFormatException ex) {
+ }
+ if (c == 0)
+ return null;
+ return String.valueOf(c);
+ }
+
+ // implicit character entities for XML
+ if (name.equals(XMLCharEntity.LT_NAME))
+ return XMLCharEntity.LT_VALUE;
+ if (name.equals(XMLCharEntity.GT_NAME))
+ return XMLCharEntity.GT_VALUE;
+ if (name.equals(XMLCharEntity.AMP_NAME))
+ return XMLCharEntity.AMP_VALUE;
+ if (name.equals(XMLCharEntity.QUOT_NAME))
+ return XMLCharEntity.QUOT_VALUE;
+ if (isXMLType()) {
+ if (name.equals(XMLCharEntity.APOS_NAME))
+ return XMLCharEntity.APOS_VALUE;
+ }
+
+ CMDocument cm = getCMDocument();
+ if (cm != null) {
+ CMNamedNodeMap map = cm.getEntities();
+ if (map != null) {
+ CMEntityDeclaration decl = (CMEntityDeclaration) map.getNamedItem(name);
+ if (decl != null) {
+ String value = decl.getValue();
+ if (value == null)
+ return null;
+ int valueLength = value.length();
+ if (valueLength > 1 && value.charAt(0) == '&' && value.charAt(1) == '#' && value.charAt(valueLength - 1) == ';') {
+ // character reference
+ return getCharValue(value.substring(1, valueLength - 1));
+ }
+ return value;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ */
+ protected CMDocument getCMDocument() {
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(this);
+ if (modelQuery == null)
+ return null;
+ return modelQuery.getCorrespondingCMDocument(this);
+ }
+
+ /**
+ * getDoctype method
+ *
+ * @return org.w3c.dom.DocumentType
+ */
+ public DocumentType getDoctype() {
+ return findDoctype(this);
+ }
+
+ /**
+ * getDocumentElement
+ *
+ * @return org.w3c.dom.Element From DOM 2 Spec: documentElement of type
+ * Element [p.62] , readonly This is a convenience [p.119]
+ * attribute that allows direct access to the child node that is
+ * the root element of the document. For HTML documents, this is
+ * the element with the tagName "HTML". Note: we differ from this
+ * definition a little in that we don't necessarily take the first
+ * child but also look to match the name. In a well formed
+ * document, of course, the result is the same, but not
+ * necessarily the same in an ill-formed document.
+ */
+ public Element getDocumentElement() {
+ String name = null;
+ DocumentType docType = getDocumentType();
+ if (docType != null) {
+ name = docType.getName();
+ }
+
+ Element first[] = new Element[1];
+ Element docElement = findDocumentElement(name, this, first);
+ if (docElement == null) {
+ docElement = first[0];
+ }
+
+ return docElement;
+ }
+
+ /**
+ */
+ protected DocumentType getDocumentType() {
+ DocumentTypeAdapter adapter = getDocumentTypeAdapter();
+ if (adapter == null)
+ return getDoctype();
+ return adapter.getDocumentType();
+ }
+
+ /**
+ */
+ protected DocumentTypeAdapter getDocumentTypeAdapter() {
+ if (this.documentTypeAdapter == null) {
+ this.documentTypeAdapter = (DocumentTypeAdapter) getAdapterFor(DocumentTypeAdapter.class);
+ if (this.documentTypeAdapter == null) {
+ // add default adapter
+ this.documentTypeAdapter = new DocumentTypeAdapterImpl(this);
+ addAdapter(this.documentTypeAdapter);
+ }
+ }
+ return this.documentTypeAdapter;
+ }
+
+ /**
+ */
+ public String getDocumentTypeId() {
+ DocumentType docType = getDocumentType();
+ if (docType == null)
+ return null;
+ String id = docType.getPublicId();
+ if (id == null)
+ id = docType.getSystemId();
+ return id;
+ }
+
+ /**
+ */
+ public Element getElementById(String id) {
+ if (id == null)
+ return null;
+ NodeIterator it = createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+ if (it == null)
+ return null;
+
+ for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+ if (node.getNodeType() != ELEMENT_NODE)
+ continue;
+ ElementImpl element = (ElementImpl) node;
+ String value = element.getAttribute("id");//$NON-NLS-1$
+ if (value != null && value.equals(id))
+ return element;
+ }
+
+ return null;
+ }
+
+ /**
+ * getElementsByTagName method
+ *
+ * @return org.w3c.dom.NodeList
+ * @param tagName
+ * java.lang.String
+ */
+ public NodeList getElementsByTagName(String tagName) {
+ if (tagName == null)
+ return new NodeListImpl();
+
+ NodeListImpl elements = null;
+
+ if (usetagnamecache) {
+ elements = tagNameCache.getItem(tagName);
+ }
+
+ if (elements == null) {
+ elements = internalGetElementsByTagName(tagName);
+
+ }
+
+ return elements;
+ }
+
+ /**
+ */
+ public NodeList getElementsByTagNameNS(String uri, String tagName) {
+ if (tagName == null)
+ return new NodeListImpl();
+
+ NodeIterator it = createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+ if (it == null)
+ return new NodeListImpl();
+ NodeListImpl elements = new NodeListImpl();
+
+ if (uri != null && uri.length() == 1 && uri.charAt(0) == '*') {
+ uri = null; // do not care
+ }
+ if (tagName.length() == 1 && tagName.charAt(0) == '*') {
+ tagName = null; // do not care
+ }
+
+ for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+ if (node.getNodeType() != ELEMENT_NODE)
+ continue;
+ ElementImpl element = (ElementImpl) node;
+ if (tagName != null) {
+ String localName = element.getLocalName();
+ if (localName == null || !localName.equals(tagName))
+ continue;
+ }
+ if (uri != null) {
+ String nsURI = element.getNamespaceURI();
+ if (nsURI == null || !nsURI.equals(uri))
+ continue;
+ }
+ elements.appendNode(element);
+ }
+
+ return elements;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the XML declaration, the encoding
+ * of this document. This is <code>null</code> when unspecified.
+ *
+ * @since DOM Level 3
+ */
+ public java.lang.String getEncoding() {
+ return null;
+ }
+
+ /**
+ */
+ public DOMImplementation getImplementation() {
+ return model;
+ }
+
+ /**
+ * other nodes will be referring to this one to get the owning model
+ */
+ public XMLModel getModel() {
+ return model;
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ return "#document";//$NON-NLS-1$
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return DOCUMENT_NODE;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the XML declaration, whether this
+ * document is standalone.
+ *
+ * @since DOM Level 3
+ */
+ public boolean getStandalone() {
+ return false;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying whether errors checking is enforced or not.
+ * When set to <code>false</code>, the implementation is free to not
+ * test every possible error case normally defined on DOM operations, and
+ * not raise any <code>DOMException</code>. In case of error, the
+ * behavior is undefined. This attribute is <code>true</code> by
+ * defaults.
+ *
+ * @since DOM Level 3
+ */
+ public boolean getStrictErrorChecking() {
+ return false;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the XML declaration, the version
+ * number of this document. This is <code>null</code> when unspecified.
+ *
+ * @since DOM Level 3
+ */
+ public String getVersion() {
+ return null;
+ }
+
+ /**
+ */
+ protected boolean ignoreCase() {
+ DocumentTypeAdapter adapter = getDocumentTypeAdapter();
+ if (adapter == null)
+ return false;
+ return (adapter.getTagNameCase() != DocumentTypeAdapter.STRICT_CASE);
+ }
+
+ /**
+ */
+ protected void importChildNodes(Node parent, boolean deep) {
+ if (parent == null)
+ return;
+
+ removeChildNodes();
+
+ for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+ Node imported = importNode(child, deep);
+ if (imported == null)
+ continue;
+ appendChild(imported);
+ }
+ }
+
+ /**
+ */
+ public Node importNode(Node node, boolean deep) throws DOMException {
+ if (node == null)
+ return null;
+ NodeImpl imported = (NodeImpl) node.cloneNode(deep);
+ if (imported == null)
+ return null;
+ imported.setOwnerDocument(this, deep);
+ return imported;
+ }
+
+ private NodeListImpl internalGetElementsByTagName(String tagName) {
+ //System.out.println("getElementsByTagname: " + tagName);
+ NodeIterator it = createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+ if (it == null)
+ return new NodeListImpl();
+ NodeListImpl elements = new NodeListImpl();
+
+ if (tagName.length() == 1 && tagName.charAt(0) == '*') {
+ tagName = null; // do not care
+ }
+
+ for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+ if (node.getNodeType() != ELEMENT_NODE)
+ continue;
+ if (tagName != null) {
+ ElementImpl element = (ElementImpl) node;
+ if (!element.matchTagName(tagName))
+ continue;
+ }
+ elements.appendNode(node);
+ }
+ if (usetagnamecache) {
+ tagNameCache.addItem(tagName, elements);
+ }
+ return elements;
+ }
+
+ /**
+ */
+ public boolean isJSPDocument() {
+ Element element = getDocumentElement();
+ if (element == null)
+ return false;
+ String tagName = element.getTagName();
+ if (tagName == null)
+ return false;
+ return tagName.equals(JSPTag.JSP_ROOT);
+ }
+
+ /**
+ */
+ public boolean isJSPType() {
+ if (this.model == null)
+ return false;
+ IModelHandler handler = this.model.getModelHandler();
+ if (handler == null)
+ return false;
+ String id = handler.getAssociatedContentTypeId();
+ if (id == null)
+ return false;
+ // TODO: -- avoid this semi hardcoded string
+ return id.equals(IContentTypeIdentifier.ContentTypeID_JSP);
+ }
+
+ /**
+ */
+ protected boolean isValidName(String name) {
+ if (name == null || name.length() == 0)
+ return false;
+ // // DMW: modified for XML4J 4.0.1
+ // if (XMLChar.isValidName(name)) return true;
+ if (NameValidator.isValid(name))
+ return true;
+ // special for invalid declaration
+ if (name.length() == 1 && name.charAt(0) == '!')
+ return true;
+ // special for JSP tag in tag name
+ if (name.startsWith(JSPTag.TAG_OPEN))
+ return true;
+ return false;
+ }
+
+ /**
+ */
+ public boolean isXMLType() {
+ DocumentTypeAdapter adapter = getDocumentTypeAdapter();
+ if (adapter == null)
+ return true;
+ return adapter.isXMLType();
+ }
+
+ /**
+ */
+ protected void releaseDocumentType() {
+ if (this.documentTypeAdapter == null)
+ return;
+ this.documentTypeAdapter.release();
+ this.documentTypeAdapter = null;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the XML declaration, the encoding
+ * of this document. This is <code>null</code> when unspecified.
+ *
+ * @since DOM Level 3
+ */
+ public void setEncoding(java.lang.String encoding) {
+ }
+
+ /**
+ * setModel method
+ *
+ * @param model
+ * XMLModel
+ */
+
+ protected void setModel(XMLModel model) {
+ this.model = (XMLModelImpl) model;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the XML declaration, whether this
+ * document is standalone.
+ *
+ * @since DOM Level 3
+ */
+ public void setStandalone(boolean standalone) {
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying whether errors checking is enforced or not.
+ * When set to <code>false</code>, the implementation is free to not
+ * test every possible error case normally defined on DOM operations, and
+ * not raise any <code>DOMException</code>. In case of error, the
+ * behavior is undefined. This attribute is <code>true</code> by
+ * defaults.
+ *
+ * @since DOM Level 3
+ */
+ public void setStrictErrorChecking(boolean strictErrorChecking) {
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the XML declaration, the version
+ * number of this document. This is <code>null</code> when unspecified.
+ *
+ * @since DOM Level 3
+ */
+ public void setVersion(java.lang.String version) {
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapterImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapterImpl.java
new file mode 100644
index 0000000000..8d63d99b79
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeAdapterImpl.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.xml.core.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.w3c.dom.DocumentType;
+
+
+/**
+ */
+public class DocumentTypeAdapterImpl implements DocumentTypeAdapter {
+
+ private XMLDocument document = null;
+ private DocumentType documentType = null;
+
+ /**
+ */
+ protected DocumentTypeAdapterImpl() {
+ super();
+ }
+
+ /**
+ */
+ protected DocumentTypeAdapterImpl(XMLDocument document) {
+ this.document = document;
+ if (document != null) {
+ this.documentType = document.getDoctype();
+ }
+ }
+
+ /**
+ */
+ public int getAttrNameCase() {
+ return STRICT_CASE;
+ }
+
+ /**
+ */
+ protected XMLDocument getDocument() {
+ return this.document;
+ }
+
+ /**
+ */
+ public DocumentType getDocumentType() {
+ return this.documentType;
+ }
+
+ /**
+ */
+ public int getTagNameCase() {
+ return STRICT_CASE;
+ }
+
+ /**
+ */
+ public boolean hasFeature(String feature) {
+ return false;
+ }
+
+ /**
+ */
+ public boolean isAdapterForType(Object type) {
+ return (type == DocumentTypeAdapter.class);
+ }
+
+ /**
+ */
+ public boolean isXMLType() {
+ return true;
+ }
+
+ /**
+ */
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ if (eventType != INodeNotifier.STRUCTURE_CHANGED)
+ return;
+ if (notifier == null || !(notifier instanceof XMLDocument))
+ return;
+ this.documentType = ((XMLDocument) notifier).getDoctype();
+ }
+
+ /**
+ */
+ protected void notifyDocumentTypeChanged() {
+ if (this.document == null)
+ return;
+ XMLModel model = this.document.getModel();
+ if (model == null)
+ return;
+ ((XMLModelImpl) model).documentTypeChanged();
+ }
+
+ /**
+ */
+ public void release() {
+ // nothing to do
+ }
+
+ /**
+ */
+ protected void setDocumentType(DocumentType documentType) {
+ this.documentType = documentType;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeImpl.java
new file mode 100644
index 0000000000..c8137da34b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/DocumentTypeImpl.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.document.XMLDocumentType;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+/**
+ * DocumentType class
+ */
+public class DocumentTypeImpl extends NodeImpl implements XMLDocumentType {
+ private String internalSubset = null;
+
+ private String name = null;
+ private String publicId = null;
+ private String systemId = null;
+
+ /**
+ * DocumentTypeImpl constructor
+ */
+ protected DocumentTypeImpl() {
+ super();
+ }
+
+ /**
+ * DocumentTypeImpl constructor
+ *
+ * @param that
+ * DocumentTypeImpl
+ */
+ protected DocumentTypeImpl(DocumentTypeImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.name = that.name;
+ }
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ DocumentTypeImpl cloned = new DocumentTypeImpl(this);
+ return cloned;
+ }
+
+ /**
+ * getEntities method
+ *
+ * @return org.w3c.dom.NamedNodeMap
+ */
+ public NamedNodeMap getEntities() {
+ return null;
+ }
+
+ /**
+ */
+ public String getInternalSubset() {
+ return this.internalSubset;
+ }
+
+ /**
+ * getName method
+ *
+ * @return java.lang.String
+ */
+ public String getName() {
+ if (this.name == null)
+ return new String();
+ return this.name;
+ }
+
+ /**
+ * getNodeName
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ return getName();
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return DOCUMENT_TYPE_NODE;
+ }
+
+ /**
+ * getNotations method
+ *
+ * @return org.w3c.dom.NamedNodeMap
+ */
+ public NamedNodeMap getNotations() {
+ return null;
+ }
+
+ /**
+ * getPublicId method
+ *
+ * @return java.lang.String
+ */
+ public String getPublicId() {
+ return this.publicId;
+ }
+
+ /**
+ * getSystemId method
+ *
+ * @return java.lang.String
+ */
+ public String getSystemId() {
+ return this.systemId;
+ }
+
+ /**
+ */
+ public boolean isClosed() {
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return true; // will be generated
+ String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+ return (regionType == XMLRegionContext.XML_DOCTYPE_DECLARATION_CLOSE || regionType == XMLRegionContext.XML_DECLARATION_CLOSE);
+ }
+
+ /**
+ */
+ public void setInternalSubset(String internalSubset) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.internalSubset = internalSubset;
+ }
+
+ /**
+ * setName method
+ *
+ * @param name
+ * java.lang.String
+ */
+ protected void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * setPublicId method
+ *
+ * @param publicId
+ * java.lang.String
+ */
+ public void setPublicId(String publicId) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.publicId = publicId;
+
+ notifyValueChanged();
+ }
+
+ /**
+ * setSystemId method
+ *
+ * @param systemId
+ * java.lang.String
+ */
+ public void setSystemId(String systemId) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.systemId = systemId;
+
+ notifyValueChanged();
+ }
+
+ /**
+ * toString method
+ *
+ * @return java.lang.String
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(getName());
+ buffer.append('(');
+ buffer.append(getPublicId());
+ buffer.append(')');
+ buffer.append('(');
+ buffer.append(getSystemId());
+ buffer.append(')');
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode != null) {
+ buffer.append('@');
+ buffer.append(flatNode.toString());
+ }
+ return buffer.toString();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ElementImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ElementImpl.java
new file mode 100644
index 0000000000..fd8d27a8ce
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ElementImpl.java
@@ -0,0 +1,1421 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.core.parser.RegionParser;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.commentelement.CommentElementAdapter;
+import org.eclipse.wst.xml.core.document.JSPTag;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNamespace;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+
+
+/**
+ * ElementImpl class
+ */
+public class ElementImpl extends NodeContainer implements XMLElement {
+
+ private class Attributes implements NamedNodeMap {
+ Attributes() {
+ super();
+ }
+
+ public int getLength() {
+ if (attrNodes == null)
+ return 0;
+ return attrNodes.getLength();
+ }
+
+ public Node getNamedItem(String name) {
+ return getAttributeNode(name);
+ }
+
+ public Node getNamedItemNS(String uri, String name) {
+ return getAttributeNodeNS(uri, name);
+ }
+
+ public Node item(int index) {
+ if (attrNodes == null)
+ return null;
+ return attrNodes.item(index);
+ }
+
+ public Node removeNamedItem(String name) throws DOMException {
+ return removeAttributeNode(name);
+ }
+
+ public Node removeNamedItemNS(String uri, String name) throws DOMException {
+ return removeAttributeNodeNS(uri, name);
+ }
+
+ public Node setNamedItem(Node arg) throws DOMException {
+ return setAttributeNode((AttrImpl) arg);
+ }
+
+ public Node setNamedItemNS(Node arg) throws DOMException {
+ return setAttributeNodeNS((AttrImpl) arg);
+ }
+ }
+
+ NodeListImpl attrNodes = null;
+ private IStructuredDocumentRegion endStructuredDocumentRegion = null;
+ private boolean isCommentTag = false;
+ private boolean isEmptyTag = false;
+ private boolean isJSPTag = false;
+ private String namespaceURI = null;
+
+ private String tagName = null;
+
+ /**
+ * ElementImpl constructor
+ */
+ protected ElementImpl() {
+ super();
+ }
+
+ /**
+ * ElementImpl constructor
+ *
+ * @param that
+ * ElementImpl
+ */
+ protected ElementImpl(ElementImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.tagName = that.tagName;
+ this.isEmptyTag = that.isEmptyTag;
+ this.isJSPTag = that.isJSPTag;
+ this.isCommentTag = that.isCommentTag;
+
+ // clone attributes
+ that.cloneAttributes(this);
+ }
+ }
+
+ /**
+ * addEndTag method
+ *
+ * @param end
+ * org.w3c.dom.Element
+ */
+ protected void addEndTag(Element endTag) {
+ if (endTag == null)
+ return;
+ if (hasEndTag())
+ return;
+ ElementImpl end = (ElementImpl) endTag;
+
+ // move the end flat node from the end tag
+ IStructuredDocumentRegion flatNode = end.getEndStructuredDocumentRegion();
+ if (flatNode == null)
+ return;
+ end.setEndStructuredDocumentRegion(null);
+ setEndStructuredDocumentRegion(flatNode);
+ }
+
+ /**
+ * appendAttibuteNode method
+ *
+ * @return org.w3c.dom.Attr
+ * @param newAttr
+ * org.w3c.dom.Attr
+ */
+ public Attr appendAttributeNode(Attr newAttr) {
+ if (newAttr == null)
+ return null;
+ AttrImpl attr = (AttrImpl) newAttr;
+ if (attr.getOwnerElement() != null)
+ return null;
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ if (this.attrNodes == null)
+ this.attrNodes = new NodeListImpl();
+ this.attrNodes.appendNode(attr);
+ attr.setOwnerElement(this);
+
+ notifyAttrReplaced(attr, null);
+ return attr;
+ }
+
+ /**
+ * cloneAttributes method
+ *
+ * @param newOwner
+ * org.w3c.dom.Element
+ */
+ protected void cloneAttributes(Element newOwner) {
+ if (newOwner == null || newOwner == this)
+ return;
+
+ ElementImpl element = (ElementImpl) newOwner;
+ element.removeAttributes();
+
+ if (this.attrNodes == null)
+ return;
+
+ int length = this.attrNodes.getLength();
+ for (int i = 0; i < length; i++) {
+ Node node = this.attrNodes.item(i);
+ if (node == null)
+ continue;
+ Attr cloned = (Attr) node.cloneNode(false);
+ if (cloned != null)
+ element.appendAttributeNode(cloned);
+ }
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ ElementImpl cloned = new ElementImpl(this);
+ if (deep)
+ cloneChildNodes(cloned, deep);
+ return cloned;
+ }
+
+ /**
+ * getAttribute method
+ *
+ * @return java.lang.String
+ * @param name
+ * java.lang.String
+ */
+ public String getAttribute(String name) {
+ Attr attr = getAttributeNode(name);
+ if (attr == null)
+ return null;
+ return attr.getValue();
+ }
+
+ /**
+ * getAttributeNode method
+ *
+ * @return org.w3c.dom.Attr
+ * @param name
+ * java.lang.String
+ */
+ public Attr getAttributeNode(String name) {
+ if (name == null)
+ return null; // invalid parameter
+ if (this.attrNodes == null)
+ return null; // no attribute
+
+ int length = this.attrNodes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+ if (attr == null)
+ continue;
+ if (attr.matchName(name))
+ return attr; // found
+ }
+
+ return null; // not found
+ }
+
+ /**
+ */
+ public Attr getAttributeNodeNS(String uri, String name) {
+ if (name == null)
+ return null; // invalid parameter
+ if (this.attrNodes == null)
+ return null; // no attribute
+
+ int length = this.attrNodes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+ if (attr == null)
+ continue;
+ String localName = attr.getLocalName();
+ if (localName == null || !localName.equals(name))
+ continue;
+ String nsURI = attr.getNamespaceURI();
+ if (uri == null) {
+ if (nsURI != null)
+ continue;
+ } else {
+ if (nsURI == null || !nsURI.equals(uri))
+ continue;
+ }
+
+ // found
+ return attr;
+ }
+
+ return null; // not found
+ }
+
+ /**
+ */
+ public String getAttributeNS(String uri, String name) {
+ Attr attr = getAttributeNodeNS(uri, name);
+ if (attr == null)
+ return null;
+ return attr.getValue();
+ }
+
+ /**
+ * getAttributes method
+ *
+ * @return org.w3c.dom.NamedNodeMap
+ */
+ public NamedNodeMap getAttributes() {
+ return new Attributes();
+ }
+
+ /**
+ */
+ protected CMElementDeclaration getDeclaration() {
+ Document document = getOwnerDocument();
+ if (document == null)
+ return null;
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+ if (modelQuery == null)
+ return null;
+ return modelQuery.getCMElementDeclaration(this);
+ }
+
+ /**
+ * getElementsByTagName method
+ *
+ * @return org.w3c.dom.NodeList
+ * @param tagName
+ * java.lang.String
+ */
+ public NodeList getElementsByTagName(String tagName) {
+ if (tagName == null)
+ return new NodeListImpl();
+
+ DocumentImpl document = (DocumentImpl) getOwnerDocument();
+ if (document == null)
+ return new NodeListImpl();
+ NodeIterator it = document.createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+ if (it == null)
+ return new NodeListImpl();
+ NodeListImpl elements = new NodeListImpl();
+
+ if (tagName.length() == 1 && tagName.charAt(0) == '*') {
+ tagName = null; // do not care
+ }
+
+ for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+ if (node.getNodeType() != ELEMENT_NODE)
+ continue;
+ if (tagName != null) {
+ ElementImpl element = (ElementImpl) node;
+ if (!element.matchTagName(tagName))
+ continue;
+ }
+ elements.appendNode(node);
+ }
+
+ return elements;
+ }
+
+ /**
+ */
+ public NodeList getElementsByTagNameNS(String uri, String tagName) {
+ if (tagName == null)
+ return new NodeListImpl();
+
+ DocumentImpl document = (DocumentImpl) getOwnerDocument();
+ if (document == null)
+ return new NodeListImpl();
+ NodeIterator it = document.createNodeIterator(this, NodeFilter.SHOW_ALL, null, false);
+ if (it == null)
+ return new NodeListImpl();
+ NodeListImpl elements = new NodeListImpl();
+
+ if (uri != null && uri.length() == 1 && uri.charAt(0) == '*') {
+ uri = null; // do not care
+ }
+ if (tagName.length() == 1 && tagName.charAt(0) == '*') {
+ tagName = null; // do not care
+ }
+
+ for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
+ if (node.getNodeType() != ELEMENT_NODE)
+ continue;
+ ElementImpl element = (ElementImpl) node;
+ if (tagName != null) {
+ String localName = element.getLocalName();
+ if (localName == null || !localName.equals(tagName))
+ continue;
+ }
+ if (uri != null) {
+ String nsURI = element.getNamespaceURI();
+ if (nsURI == null || !nsURI.equals(uri))
+ continue;
+ }
+ elements.appendNode(element);
+ }
+
+ return elements;
+ }
+
+ /**
+ * getEndOffset method
+ *
+ * @return int
+ */
+ public int getEndOffset() {
+ if (this.endStructuredDocumentRegion != null)
+ return this.endStructuredDocumentRegion.getEnd();
+ return super.getEndOffset();
+ }
+
+ /**
+ * getEndStartOffset method
+ *
+ * @return int
+ */
+ public int getEndStartOffset() {
+ if (this.endStructuredDocumentRegion != null)
+ return this.endStructuredDocumentRegion.getStart();
+ return super.getEndOffset();
+ }
+
+ /**
+ * getEndStructuredDocumentRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getEndStructuredDocumentRegion() {
+ return this.endStructuredDocumentRegion;
+ }
+
+ /**
+ */
+ public String getEndTagName() {
+ if (this.endStructuredDocumentRegion == null)
+ return null;
+
+ ITextRegionList regions = this.endStructuredDocumentRegion.getRegions();
+ if (regions == null)
+ return null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_NAME || regionType == XMLJSPRegionContexts.JSP_ROOT_TAG_NAME || regionType == XMLJSPRegionContexts.JSP_DIRECTIVE_NAME) {
+ return this.endStructuredDocumentRegion.getText(region);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * getFirstStructuredDocumentRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode != null)
+ return StructuredDocumentRegionUtil.getStructuredDocumentRegion(flatNode);
+ return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.endStructuredDocumentRegion);
+ }
+
+ /**
+ * getLastStructuredDocumentRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+ if (this.endStructuredDocumentRegion != null)
+ return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.endStructuredDocumentRegion);
+ return StructuredDocumentRegionUtil.getStructuredDocumentRegion(getStructuredDocumentRegion());
+ }
+
+ /**
+ */
+ public String getLocalName() {
+ if (this.tagName == null)
+ return null;
+ int index = this.tagName.indexOf(':');
+ if (index < 0)
+ return this.tagName;
+ return this.tagName.substring(index + 1);
+ }
+
+ /**
+ */
+ public String getNamespaceURI() {
+ String nsAttrName = null;
+ String prefix = getPrefix();
+ if (prefix != null && prefix.length() > 0) {
+ nsAttrName = XMLNamespace.XMLNS_PREFIX + prefix;
+ } else {
+ nsAttrName = XMLNamespace.XMLNS;
+ }
+
+ for (Node node = this; node != null; node = node.getParentNode()) {
+ if (node.getNodeType() != ELEMENT_NODE)
+ break;
+ Element element = (Element) node;
+ Attr attr = element.getAttributeNode(nsAttrName);
+ if (attr != null)
+ return attr.getValue();
+ }
+
+ return this.namespaceURI;
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ return getTagName();
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return ELEMENT_NODE;
+ }
+
+ /**
+ */
+ public String getPrefix() {
+ if (this.tagName == null)
+ return null;
+ int index = this.tagName.indexOf(':');
+ if (index <= 0)
+ return null;
+ // exclude JSP tag in tag name
+ if (this.tagName.charAt(0) == '<')
+ return null;
+ return this.tagName.substring(0, index);
+ }
+
+ /**
+ * getStartEndOffset method
+ *
+ * @return int
+ */
+ public int getStartEndOffset() {
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode != null)
+ return flatNode.getEnd();
+ return super.getStartOffset();
+ }
+
+ /**
+ * getStartOffset method
+ *
+ * @return int
+ */
+ public int getStartOffset() {
+ if (getStartStructuredDocumentRegion() == null && this.endStructuredDocumentRegion != null && !hasChildNodes()) {
+ return this.endStructuredDocumentRegion.getStart();
+ }
+ return super.getStartOffset();
+ }
+
+ /**
+ * getStartStructuredDocumentRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getStartStructuredDocumentRegion() {
+ return getStructuredDocumentRegion();
+ }
+
+ /**
+ * getTagName method
+ *
+ * @return java.lang.String
+ */
+ public String getTagName() {
+ if (this.tagName == null)
+ return new String();
+ return this.tagName;
+ }
+
+ /**
+ */
+ public boolean hasAttribute(String name) {
+ return (getAttributeNode(name) != null);
+ }
+
+ /**
+ */
+ public boolean hasAttributeNS(String uri, String name) {
+ return (getAttributeNodeNS(uri, name) != null);
+ }
+
+ /**
+ */
+ public boolean hasAttributes() {
+ return (this.attrNodes != null && this.attrNodes.getLength() > 0);
+ }
+
+ /**
+ * hasEndTag method
+ *
+ * @return boolean
+ */
+ public boolean hasEndTag() {
+ return (this.endStructuredDocumentRegion != null);
+ }
+
+ /**
+ */
+ protected final boolean hasPrefix() {
+ if (this.tagName == null)
+ return false;
+ if (this.tagName.indexOf(':') <= 0)
+ return false;
+ // exclude JSP tag in tag name
+ if (this.tagName.charAt(0) == '<')
+ return false;
+ return true;
+ }
+
+ /**
+ * hasStartTag method
+ *
+ * @return boolean
+ */
+ public boolean hasStartTag() {
+ return (getStructuredDocumentRegion() != null);
+ }
+
+ /**
+ */
+ protected final boolean ignoreCase() {
+ DocumentImpl document = (DocumentImpl) getOwnerDocument();
+ if (document != null && document.ignoreCase()) {
+ // even in case insensitive document, if having prefix, it's case
+ // sensitive tag
+ return !hasPrefix();
+ }
+ return false;
+ }
+
+ /**
+ */
+ protected Attr insertAttributeNode(Attr newAttr, int index) {
+ if (newAttr == null)
+ return null;
+ AttrImpl attr = (AttrImpl) newAttr;
+ if (attr.getOwnerElement() != null)
+ return null;
+
+ if (this.attrNodes == null)
+ this.attrNodes = new NodeListImpl();
+ this.attrNodes.insertNode(attr, index);
+ attr.setOwnerElement(this);
+
+ notifyAttrReplaced(attr, null);
+ return attr;
+ }
+
+ /**
+ * insertBefore method
+ *
+ * @return org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param refChild
+ * org.w3c.dom.Node
+ */
+ public Node insertBefore(Node newChild, Node refChild) throws DOMException {
+ // should throw DOMException instead of return null?
+ if (newChild == null)
+ return null;
+ if (!isContainer()) { // never be container
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, new String());
+ }
+ if (newChild.getNodeType() != TEXT_NODE) {
+ if (isJSPContainer() || isCDATAContainer()) { // accepts only Text
+ // child
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, new String());
+ }
+ }
+ return super.insertBefore(newChild, refChild);
+ }
+
+ /**
+ */
+ protected boolean isCDATAContainer() {
+ // use BlockMaker instead of CMElementDeclaration
+ // because <style> and <script> in XHTML is not CDATA content type
+ XMLModel model = getModel();
+ if (model == null)
+ return false; // error
+ IStructuredDocument structuredDocument = model.getStructuredDocument();
+ if (structuredDocument == null)
+ return false; // eror
+ RegionParser parser = structuredDocument.getParser();
+ if (parser == null || !(parser instanceof XMLSourceParser))
+ return false;
+ return (((XMLSourceParser) parser).getBlockMarker(this.tagName) != null);
+ /*
+ * CMElementDeclaration decl = getDeclaration(); if (decl == null)
+ * return false; if (decl instanceof CMNodeWrapper) { decl =
+ * (CMElementDeclaration)((CMNodeWrapper)decl).getOriginNode(); if
+ * (decl == null) return false; } if (decl instanceof
+ * TLDElementDeclaration) { String content =
+ * ((TLDElementDeclaration)decl).getBodycontent(); if (content ==
+ * null) return false; return
+ * content.equals(JSP11TLDNames.CONTENT_TAGDEPENDENT); } if
+ * (!isGlobalTag()) return false; return (decl.getContentType() ==
+ * CMElementDeclaration.CDATA);
+ */
+ }
+
+ /**
+ */
+ public boolean isClosed() {
+ IStructuredDocumentRegion flatNode = null;
+ if (isEmptyTag() || !isContainer()) {
+ flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return true; // will be generated
+ } else {
+ flatNode = getEndStructuredDocumentRegion();
+ if (flatNode == null)
+ return false; // must be generated
+ }
+ String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+ if (isCommentTag()) {
+ return (regionType == XMLJSPRegionContexts.JSP_COMMENT_CLOSE || regionType == XMLRegionContext.XML_COMMENT_CLOSE);
+ }
+ if (isJSPTag()) {
+ return (regionType == XMLJSPRegionContexts.JSP_CLOSE || regionType == XMLJSPRegionContexts.JSP_DIRECTIVE_CLOSE);
+ }
+ return (regionType == XMLRegionContext.XML_TAG_CLOSE || regionType == XMLRegionContext.XML_EMPTY_TAG_CLOSE || regionType == XMLRegionContext.XML_DECLARATION_CLOSE);
+ }
+
+ /**
+ */
+ public final boolean isCommentTag() {
+ return this.isCommentTag;
+ }
+
+ /**
+ * isContainer method
+ *
+ * @return boolean
+ */
+ public boolean isContainer() {
+ if (isCommentTag()) {
+ CommentElementAdapter adapter = (CommentElementAdapter) getAdapterFor(CommentElementAdapter.class);
+ if (adapter != null) {
+ return (adapter.isContainer());
+ }
+ return (getDeclaration() == null);
+ }
+ if (isJSPTag()) {
+ // exclude JSP directive
+ return (matchTagName(JSPTag.JSP_SCRIPTLET) || matchTagName(JSPTag.JSP_DECLARATION) || matchTagName(JSPTag.JSP_EXPRESSION));
+ }
+ if (!isXMLTag()) { // non-XML tag
+ CMElementDeclaration decl = getDeclaration();
+ if (decl == null)
+ return false; // undefined tag
+ return (decl.getContentType() != CMElementDeclaration.EMPTY);
+ }
+ return true;
+ }
+
+ /**
+ * isEmptyTag method
+ *
+ * @return boolean
+ */
+ public boolean isEmptyTag() {
+ if (isJSPTag())
+ return false;
+ if (isCommentTag())
+ return false;
+ if (!isXMLTag())
+ return false;
+ return this.isEmptyTag;
+ }
+
+ /**
+ */
+ public boolean isEndTag() {
+ return (hasEndTag() && !hasStartTag() && !hasChildNodes());
+ }
+
+ /**
+ */
+ public boolean isGlobalTag() {
+ return !hasPrefix();
+ }
+
+ /**
+ */
+ public boolean isImplicitTag() {
+ if (hasStartTag() || hasEndTag())
+ return false;
+ // make sure this is in the document tree
+ // because if not in the document tree, no tags are generated yet
+ return (getContainerDocument() != null);
+ }
+
+ /**
+ */
+ public boolean isJSPContainer() {
+ return (isJSPTag() && !isCommentTag() && isContainer());
+ }
+
+ /**
+ * isJSPTag method
+ *
+ * @return boolean
+ */
+ public final boolean isJSPTag() {
+ return this.isJSPTag;
+ }
+
+ /**
+ */
+ public boolean isStartTagClosed() {
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return true; // will be generated
+ String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+ if (isCommentTag()) {
+ return (regionType == XMLJSPRegionContexts.JSP_COMMENT_CLOSE || regionType == XMLRegionContext.XML_COMMENT_CLOSE);
+ }
+ if (isJSPTag()) {
+ if (isContainer())
+ return true; // start tag always has a single region
+ return (regionType == XMLJSPRegionContexts.JSP_DIRECTIVE_CLOSE);
+ }
+ return (regionType == XMLRegionContext.XML_TAG_CLOSE || regionType == XMLRegionContext.XML_EMPTY_TAG_CLOSE || regionType == XMLRegionContext.XML_DECLARATION_CLOSE);
+ }
+
+ /**
+ */
+ public final boolean isXMLTag() {
+ if (isJSPTag())
+ return false;
+ if (isCommentTag())
+ return false;
+ DocumentImpl document = (DocumentImpl) getOwnerDocument();
+ if (document != null && !document.isXMLType()) {
+ // even in non-XML document, if having prefix, it's XML tag
+ return hasPrefix();
+ }
+ return true;
+ }
+
+ /**
+ */
+ protected boolean matchEndTag(Element element) {
+ if (element == null)
+ return false;
+ ElementImpl impl = (ElementImpl) element;
+ if (isJSPTag() && !isCommentTag()) {
+ return (impl.isJSPTag() && !impl.isCommentTag());
+ }
+ return matchTagName(element.getTagName());
+ }
+
+ /**
+ * matchTagName method
+ *
+ * @return boolean
+ * @param tagName
+ * java.lang.String
+ */
+ public boolean matchTagName(String tagName) {
+ if (tagName == null)
+ return (this.tagName == null);
+ if (this.tagName == null)
+ return false;
+ if (!ignoreCase())
+ return this.tagName.equals(tagName);
+ return this.tagName.equalsIgnoreCase(tagName);
+ }
+
+ /**
+ * notifyAttrReplaced method
+ *
+ * @param newAttr
+ * org.w3c.dom.Attr
+ * @param oldAttr
+ * org.w3c.dom.Attr
+ */
+ protected void notifyAttrReplaced(Attr newAttr, Attr oldAttr) {
+ DocumentImpl document = (DocumentImpl) getContainerDocument();
+ if (document == null)
+ return;
+ XMLModelImpl model = (XMLModelImpl) document.getModel();
+ if (model == null)
+ return;
+ model.attrReplaced(this, newAttr, oldAttr);
+ }
+
+ /**
+ * notifyValueChanged method
+ */
+ public void notifyEndTagChanged() {
+ DocumentImpl document = (DocumentImpl) getContainerDocument();
+ if (document == null)
+ return;
+ XMLModelImpl model = (XMLModelImpl) document.getModel();
+ if (model == null)
+ return;
+ model.endTagChanged(this);
+ }
+
+ /**
+ */
+ public void notifyStartTagChanged() {
+ DocumentImpl document = (DocumentImpl) getContainerDocument();
+ if (document == null)
+ return;
+ XMLModelImpl model = (XMLModelImpl) document.getModel();
+ if (model == null)
+ return;
+ model.startTagChanged(this);
+ }
+
+ /**
+ */
+ public boolean preferEmptyTag() {
+ if (hasChildNodes())
+ return false;
+ if (isJSPTag())
+ return false;
+ if (isCommentTag())
+ return false;
+ if (!isXMLTag())
+ return false;
+ CMElementDeclaration decl = getDeclaration();
+ if (decl == null)
+ return false;
+ return (decl.getContentType() == CMElementDeclaration.EMPTY);
+ }
+
+ /**
+ * removeAttribute method
+ *
+ * @param name
+ * java.lang.String
+ */
+ public void removeAttribute(String name) throws DOMException {
+ removeAttributeNode(name);
+ }
+
+ /**
+ * removeAttributeNode method
+ *
+ * @return org.w3c.dom.Attr
+ * @param oldAttr
+ * org.w3c.dom.Attr
+ */
+ public Attr removeAttributeNode(Attr oldAttr) throws DOMException {
+ if (oldAttr == null)
+ return null; // invalid parameter
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ if (this.attrNodes == null) { // no attribute
+ throw new DOMException(DOMException.NOT_FOUND_ERR, new String());
+ }
+
+ int length = this.attrNodes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+ if (attr != oldAttr)
+ continue;
+
+ // found
+ this.attrNodes.removeNode(i);
+ attr.setOwnerElement(null);
+
+ notifyAttrReplaced(null, attr);
+ return attr;
+ }
+
+ // not found
+ throw new DOMException(DOMException.NOT_FOUND_ERR, new String());
+ }
+
+ /**
+ * removeAttributeNode method
+ *
+ * @return org.w3c.dom.Attr
+ * @param name
+ * java.lang.String
+ */
+ public Attr removeAttributeNode(String name) {
+ if (name == null)
+ return null; // invalid parameter
+ if (this.attrNodes == null)
+ return null; // no attribute
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ int length = this.attrNodes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+ if (attr == null)
+ continue;
+ if (!attr.matchName(name))
+ continue;
+
+ // found
+ this.attrNodes.removeNode(i);
+ attr.setOwnerElement(null);
+
+ notifyAttrReplaced(null, attr);
+ return attr;
+ }
+
+ return null; // not found
+ }
+
+ /**
+ */
+ public Attr removeAttributeNodeNS(String uri, String name) {
+ if (name == null)
+ return null; // invalid parameter
+ if (this.attrNodes == null)
+ return null; // no attribute
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ int length = this.attrNodes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+ if (attr == null)
+ continue;
+ String localName = attr.getLocalName();
+ if (localName == null || !localName.equals(name))
+ continue;
+ String nsURI = attr.getNamespaceURI();
+ if (uri == null) {
+ if (nsURI != null)
+ continue;
+ } else {
+ if (nsURI == null || !nsURI.equals(uri))
+ continue;
+ }
+
+ // found
+ this.attrNodes.removeNode(i);
+ attr.setOwnerElement(null);
+
+ notifyAttrReplaced(null, attr);
+ return attr;
+ }
+
+ return null; // not found
+ }
+
+ /**
+ */
+ public void removeAttributeNS(String uri, String name) throws DOMException {
+ removeAttributeNodeNS(uri, name);
+ }
+
+ /**
+ * removeAttributes method
+ */
+ public void removeAttributes() {
+ if (this.attrNodes == null)
+ return;
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ int length = this.attrNodes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+ if (attr != null) {
+ attr.setOwnerElement(null);
+ notifyAttrReplaced(null, attr);
+ }
+ }
+
+ this.attrNodes = null;
+ }
+
+ /**
+ * removeEndTag method
+ *
+ * @return org.w3c.dom.Element
+ */
+ protected Element removeEndTag() {
+ if (!hasEndTag())
+ return null;
+ NodeListImpl attrNodes = this.attrNodes;
+ this.attrNodes = null; // not to copy attributes
+ ElementImpl end = (ElementImpl) cloneNode(false);
+ this.attrNodes = attrNodes;
+ if (end == null)
+ return null;
+
+ // move the end flat node to the end tag
+ IStructuredDocumentRegion flatNode = getEndStructuredDocumentRegion();
+ if (flatNode == null)
+ return null;
+ setEndStructuredDocumentRegion(null);
+ end.setEndStructuredDocumentRegion(flatNode);
+ return end;
+ }
+
+ /**
+ */
+ protected void removeStartTag() {
+ removeAttributes();
+ }
+
+ /**
+ * Resets attribute values from IStructuredDocumentRegion.
+ */
+ void resetStructuredDocumentRegions() {
+ if (this.attrNodes != null) {
+ int length = this.attrNodes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+ if (attr == null)
+ continue;
+ attr.resetRegions();
+ }
+ }
+
+ super.resetStructuredDocumentRegions(); // for children
+
+ this.endStructuredDocumentRegion = null;
+ }
+
+ /**
+ * setAttribute method
+ *
+ * @param name
+ * java.lang.String
+ * @param value
+ * java.lang.String
+ */
+ public void setAttribute(String name, String value) throws DOMException {
+ if (name == null)
+ return;
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ Attr attr = getAttributeNode(name);
+ if (attr != null) {
+ attr.setValue(value); // change value
+ return;
+ }
+
+ // new attribute
+ Document doc = getOwnerDocument();
+ if (doc == null)
+ return;
+ attr = doc.createAttribute(name);
+ if (attr == null)
+ return;
+ attr.setValue(value);
+ appendAttributeNode(attr);
+ }
+
+ /**
+ * setAttributeNode method
+ *
+ * @return org.w3c.dom.Attr
+ * @param newAttr
+ * org.w3c.dom.Attr
+ */
+ public Attr setAttributeNode(Attr newAttr) throws DOMException {
+ if (newAttr == null)
+ return null; // nothing to do
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ AttrImpl attr = (AttrImpl) newAttr;
+ Element owner = attr.getOwnerElement();
+ if (owner != null) {
+ if (owner == this)
+ return null; // nothing to do
+ throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, new String());
+ }
+
+ Attr oldAttr = removeAttributeNode(newAttr.getName());
+ appendAttributeNode(attr);
+ return oldAttr;
+ }
+
+ /**
+ */
+ public Attr setAttributeNodeNS(Attr newAttr) throws DOMException {
+ if (newAttr == null)
+ return null; // nothing to do
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ AttrImpl attr = (AttrImpl) newAttr;
+ Element owner = attr.getOwnerElement();
+ if (owner != null) {
+ if (owner == this)
+ return null; // nothing to do
+ throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, new String());
+ }
+
+ String name = newAttr.getLocalName();
+ String uri = newAttr.getNamespaceURI();
+ Attr oldAttr = removeAttributeNodeNS(uri, name);
+ appendAttributeNode(attr);
+ return oldAttr;
+ }
+
+ /**
+ */
+ public void setAttributeNS(String uri, String name, String value) throws DOMException {
+ if (name == null)
+ return;
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ Attr attr = getAttributeNodeNS(uri, name);
+ if (attr != null) {
+ attr.setValue(value); // change value
+ return;
+ }
+
+ // new attribute
+ Document doc = getOwnerDocument();
+ if (doc == null)
+ return;
+ attr = doc.createAttributeNS(uri, name);
+ if (attr == null)
+ return;
+ attr.setValue(value);
+ appendAttributeNode(attr);
+ }
+
+ /**
+ */
+ public void setCommentTag(boolean isCommentTag) {
+ XMLNode parent = (XMLNode) getParentNode();
+ if (parent != null && !parent.isChildEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.isCommentTag = isCommentTag;
+ }
+
+ /**
+ * setEmptyTag method
+ *
+ * @param isEmptyTag
+ * boolean
+ */
+ public void setEmptyTag(boolean isEmptyTag) {
+ XMLNode parent = (XMLNode) getParentNode();
+ if (parent != null && !parent.isChildEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.isEmptyTag = isEmptyTag;
+ }
+
+ /**
+ * setEndStructuredDocumentRegion method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ void setEndStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ this.endStructuredDocumentRegion = flatNode;
+
+ NodeContainer parent = (NodeContainer) getParentNode();
+ if (parent != null) {
+ parent.syncChildEditableState(this);
+ }
+ }
+
+ /**
+ * setJSPTag method
+ *
+ * @param isJSPTag
+ * boolean
+ */
+ public void setJSPTag(boolean isJSPTag) {
+ XMLNode parent = (XMLNode) getParentNode();
+ if (parent != null && !parent.isChildEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.isJSPTag = isJSPTag;
+ }
+
+ /**
+ */
+ protected void setNamespaceURI(String namespaceURI) {
+ this.namespaceURI = namespaceURI;
+ }
+
+ /**
+ */
+ protected void setOwnerDocument(Document ownerDocument, boolean deep) {
+ super.setOwnerDocument(ownerDocument, deep);
+
+ if (this.attrNodes == null)
+ return;
+
+ int length = this.attrNodes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) this.attrNodes.item(i);
+ if (attr == null)
+ continue;
+ attr.setOwnerDocument(ownerDocument);
+ }
+ }
+
+ /**
+ */
+ public void setPrefix(String prefix) throws DOMException {
+ XMLNode parent = (XMLNode) getParentNode();
+ if (parent != null && !parent.isChildEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ int prefixLength = (prefix != null ? prefix.length() : 0);
+ String localName = getLocalName();
+ if (prefixLength == 0) {
+ if (localName == null || localName.length() == 0) {
+ // invalid local name
+ return;
+ }
+ setTagName(localName);
+ } else {
+ int localLength = (localName != null ? localName.length() : 0);
+ StringBuffer buffer = new StringBuffer(prefixLength + 1 + localLength);
+ buffer.append(prefix);
+ buffer.append(':');
+ if (localName != null)
+ buffer.append(localName);
+ setTagName(buffer.toString());
+ }
+
+ boolean changeEndTag = hasEndTag();
+ notifyStartTagChanged();
+ if (changeEndTag)
+ notifyEndTagChanged();
+ }
+
+ /**
+ * setStartStructuredDocumentRegion method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ void setStartStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ setStructuredDocumentRegion(flatNode);
+ }
+
+ /**
+ * setTagName method
+ *
+ * @param tagName
+ * java.lang.String
+ */
+ protected void setTagName(String tagName) {
+ this.tagName = tagName;
+ }
+
+ /**
+ * toString method
+ *
+ * @return java.lang.String
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ String tagName = getTagName();
+ if (hasStartTag())
+ buffer.append(tagName);
+ if (isEmptyTag())
+ buffer.append('/');
+ if (hasEndTag()) {
+ buffer.append('/');
+ buffer.append(tagName);
+ }
+ if (buffer.length() == 0)
+ buffer.append(tagName);
+
+ IStructuredDocumentRegion startStructuredDocumentRegion = getStartStructuredDocumentRegion();
+ if (startStructuredDocumentRegion != null) {
+ buffer.append('@');
+ buffer.append(startStructuredDocumentRegion.toString());
+ }
+ IStructuredDocumentRegion endStructuredDocumentRegion = getEndStructuredDocumentRegion();
+ if (endStructuredDocumentRegion != null) {
+ buffer.append('@');
+ buffer.append(endStructuredDocumentRegion.toString());
+ }
+ return buffer.toString();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityImpl.java
new file mode 100644
index 0000000000..80e5d6fdbd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityImpl.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Entity;
+import org.w3c.dom.Node;
+
+/**
+ * EntityImpl class
+ */
+public class EntityImpl extends NodeImpl implements Entity {
+
+ private String name = null;
+ private String notationName = null;
+ private String publicId = null;
+ private String systemId = null;
+
+ /**
+ * EntityImpl constructor
+ */
+ protected EntityImpl() {
+ super();
+ }
+
+ /**
+ * EntityImpl constructor
+ *
+ * @param that
+ * EntityImpl
+ */
+ protected EntityImpl(EntityImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.name = that.name;
+ this.publicId = that.publicId;
+ this.systemId = that.systemId;
+ this.notationName = that.notationName;
+ }
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ EntityImpl cloned = new EntityImpl(this);
+ return cloned;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the text declaration, the encoding
+ * of this entity, when it is an external parsed entity. This is
+ * <code>null</code> otherwise.
+ *
+ * @since DOM Level 3
+ */
+ public java.lang.String getEncoding() {
+ return null;
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ if (this.name == null)
+ return new String();
+ return this.name;
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return ENTITY_NODE;
+ }
+
+ /**
+ * getNotationName method
+ *
+ * @return java.lang.String
+ */
+ public String getNotationName() {
+ return this.notationName;
+ }
+
+ /**
+ * getPublicId method
+ *
+ * @return java.lang.String
+ */
+ public String getPublicId() {
+ return this.publicId;
+ }
+
+ /**
+ * getSystemId method
+ *
+ * @return java.lang.String
+ */
+ public String getSystemId() {
+ return this.systemId;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the text declaration, the version
+ * number of this entity, when it is an external parsed entity. This is
+ * <code>null</code> otherwise.
+ *
+ * @since DOM Level 3
+ */
+ public java.lang.String getVersion() {
+ return null;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the text declaration, the encoding
+ * of this entity, when it is an external parsed entity. This is
+ * <code>null</code> otherwise.
+ *
+ * @since DOM Level 3
+ */
+ public void setEncoding(java.lang.String encoding) {
+ }
+
+ /**
+ * setName method
+ *
+ * @param name
+ * java.lang.String
+ */
+ protected void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * setNotationName method
+ *
+ * @param notationName
+ * java.lang.String
+ */
+ public void setNotationName(String notationName) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.notationName = notationName;
+ }
+
+ /**
+ * setPublicId method
+ *
+ * @param publicId
+ * java.lang.String
+ */
+ public void setPublicId(String publicId) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.publicId = publicId;
+ }
+
+ /**
+ * setSystemId method
+ *
+ * @param systemId
+ * java.lang.String
+ */
+ public void setSystemId(String systemId) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.systemId = systemId;
+ }
+
+ /**
+ * <p>
+ * EXPERIMENTAL! Based on the <a
+ * href='http://www.w3.org/TR/2001/WD-DOM-Level-3-Core-20010605'>Document
+ * Object Model (DOM) Level 3 Core Working Draft of 5 June 2001. </a>.
+ * <p>
+ * An attribute specifying, as part of the text declaration, the version
+ * number of this entity, when it is an external parsed entity. This is
+ * <code>null</code> otherwise.
+ *
+ * @since DOM Level 3
+ */
+ public void setVersion(java.lang.String version) {
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityReferenceImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityReferenceImpl.java
new file mode 100644
index 0000000000..366ecc0dbd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/EntityReferenceImpl.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+
+/**
+ * EntityReference class
+ */
+public class EntityReferenceImpl extends NodeImpl implements EntityReference {
+
+ private String name = null;
+
+ /**
+ * EntityReferenceImpl constructor
+ */
+ protected EntityReferenceImpl() {
+ super();
+ }
+
+ /**
+ * EntityReferenceImpl constructor
+ *
+ * @param that
+ * EntityReferenceImpl
+ */
+ protected EntityReferenceImpl(EntityReferenceImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.name = that.name;
+ }
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ EntityReferenceImpl cloned = new EntityReferenceImpl(this);
+ return cloned;
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ if (this.name == null)
+ return new String();
+ return this.name;
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return ENTITY_REFERENCE_NODE;
+ }
+
+ /**
+ * setName method
+ *
+ * @param name
+ * java.lang.String
+ */
+ protected void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ModelParserAdapter.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ModelParserAdapter.java
new file mode 100644
index 0000000000..011079bc31
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ModelParserAdapter.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ */
+public interface ModelParserAdapter extends INodeAdapter {
+
+ /**
+ */
+ public boolean canBeImplicitTag(Element element);
+
+ /**
+ */
+ public boolean canBeImplicitTag(Element element, Node child);
+
+ /**
+ */
+ public boolean canContain(Element element, Node child);
+
+ /**
+ */
+ public Element createCommentElement(Document document, String data, boolean isJSPTag);
+
+ /**
+ */
+ public Element createImplicitElement(Document document, Node parent, Node child);
+
+ /**
+ */
+ public String getFindRootName(String tagName);
+
+ /**
+ */
+ public boolean isEndTag(XMLElement element);
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeContainer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeContainer.java
new file mode 100644
index 0000000000..121d57cb17
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeContainer.java
@@ -0,0 +1,514 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ * NodeContainer class
+ */
+public abstract class NodeContainer extends NodeImpl implements Node, NodeList {
+
+ /**
+ */
+ private class ChildNodesCache implements NodeList {
+ private Node curChild = null;
+ private int curIndex = -1;
+ private int length = 0;
+
+ ChildNodesCache() {
+ initializeCache();
+ }
+
+ public int getLength() {
+ // atomic
+ return this.length;
+ }
+
+ private void initializeCache() {
+ // note we use the outter objects lockobject
+ // (since we are using their "children".
+ synchronized (lockObject) {
+ for (Node child = firstChild; child != null; child = child.getNextSibling()) {
+ this.length++;
+ }
+ }
+ }
+
+ public Node item(int index) {
+ synchronized (lockObject) {
+ if (this.length == 0)
+ return null;
+ if (index < 0)
+ return null;
+ if (index >= this.length)
+ return null;
+
+ if (this.curIndex < 0) { // first time
+ if (index * 2 >= this.length) { // search from the last
+ this.curIndex = this.length - 1;
+ this.curChild = lastChild;
+ } else { // search from the first
+ this.curIndex = 0;
+ this.curChild = firstChild;
+ }
+ }
+
+ if (index == this.curIndex)
+ return this.curChild;
+
+ if (index > this.curIndex) {
+ while (index > this.curIndex) {
+ this.curIndex++;
+ this.curChild = this.curChild.getNextSibling();
+ }
+ } else { // index < this.curIndex
+ while (index < this.curIndex) {
+ this.curIndex--;
+ this.curChild = this.curChild.getPreviousSibling();
+ }
+ }
+
+ return this.curChild;
+ }
+ }
+ }
+
+ private NodeList childNodesCache = null;
+
+ private boolean fChildEditable = true;
+ NodeImpl firstChild = null;
+ NodeImpl lastChild = null;
+
+ Object lockObject = new byte[0];
+
+ /**
+ * NodeContainer constructor
+ */
+ protected NodeContainer() {
+ super();
+ }
+
+ /**
+ * NodeContainer constructor
+ *
+ * @param that
+ * NodeContainer
+ */
+ protected NodeContainer(NodeContainer that) {
+ super(that);
+ }
+
+ /**
+ * appendChild method
+ *
+ * @return org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ */
+ public Node appendChild(Node newChild) throws DOMException {
+ return insertBefore(newChild, null);
+ }
+
+ /**
+ * cloneChildNodes method
+ *
+ * @param container
+ * org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ protected void cloneChildNodes(Node newParent, boolean deep) {
+ if (newParent == null || newParent == this)
+ return;
+ if (!(newParent instanceof NodeContainer))
+ return;
+
+ NodeContainer container = (NodeContainer) newParent;
+ container.removeChildNodes();
+
+ for (Node child = getFirstChild(); child != null; child = child.getNextSibling()) {
+ Node cloned = child.cloneNode(deep);
+ if (cloned != null)
+ container.appendChild(cloned);
+ }
+ }
+
+ /**
+ * getChildNodes method
+ *
+ * @return org.w3c.dom.NodeList
+ */
+ public NodeList getChildNodes() {
+ return this;
+ }
+
+ /**
+ * getFirstChild method
+ *
+ * @return org.w3c.dom.Node
+ */
+ public Node getFirstChild() {
+ return this.firstChild;
+ }
+
+ /**
+ * getLastChild method
+ *
+ * @return org.w3c.dom.Node
+ */
+ public Node getLastChild() {
+ return this.lastChild;
+ }
+
+ /**
+ * getLength method
+ *
+ * @return int
+ */
+ public int getLength() {
+ if (this.firstChild == null)
+ return 0;
+ synchronized (lockObject) {
+ if (this.childNodesCache == null)
+ this.childNodesCache = new ChildNodesCache();
+ return this.childNodesCache.getLength();
+ }
+ }
+
+ /**
+ */
+ public String getSource() {
+ StringBuffer buffer = new StringBuffer();
+
+ IStructuredDocumentRegion startStructuredDocumentRegion = getStartStructuredDocumentRegion();
+ if (startStructuredDocumentRegion != null) {
+ String source = startStructuredDocumentRegion.getText();
+ if (source != null)
+ buffer.append(source);
+ }
+
+ for (NodeImpl child = firstChild; child != null; child = (NodeImpl) child.getNextSibling()) {
+ String source = child.getSource();
+ if (source != null)
+ buffer.append(source);
+ }
+
+ IStructuredDocumentRegion endStructuredDocumentRegion = getEndStructuredDocumentRegion();
+ if (endStructuredDocumentRegion != null) {
+ String source = endStructuredDocumentRegion.getText();
+ if (source != null)
+ buffer.append(source);
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * hasChildNodes method
+ *
+ * @return boolean
+ */
+ public boolean hasChildNodes() {
+ return (this.firstChild != null);
+ }
+
+ /**
+ * insertBefore method
+ *
+ * @return org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param refChild
+ * org.w3c.dom.Node
+ */
+ public Node insertBefore(Node newChild, Node refChild) throws DOMException {
+ if (newChild == null)
+ return null; // nothing to do
+ if (refChild != null && refChild.getParentNode() != this) {
+ throw new DOMException(DOMException.NOT_FOUND_ERR, new String());
+ }
+ if (!isChildEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ if (newChild == refChild)
+ return newChild; // nothing to do
+
+ if (newChild.getNodeType() == DOCUMENT_FRAGMENT_NODE) {
+ // insert child nodes instead
+ for (Node child = newChild.getFirstChild(); child != null; child = newChild.getFirstChild()) {
+ newChild.removeChild(child);
+ insertBefore(child, refChild);
+ }
+ return newChild;
+ }
+ // synchronized in case another thread is getting item, or length
+ synchronized (lockObject) {
+ this.childNodesCache = null; // invalidate child nodes cache
+ }
+
+ NodeImpl child = (NodeImpl) newChild;
+ NodeImpl next = (NodeImpl) refChild;
+ NodeImpl prev = null;
+ Node oldParent = child.getParentNode();
+ if (oldParent != null)
+ oldParent.removeChild(child);
+ if (next == null) {
+ prev = this.lastChild;
+ this.lastChild = child;
+ } else {
+ prev = (NodeImpl) next.getPreviousSibling();
+ next.setPreviousSibling(child);
+ }
+ if (prev == null)
+ this.firstChild = child;
+ else
+ prev.setNextSibling(child);
+ child.setPreviousSibling(prev);
+ child.setNextSibling(next);
+ child.setParentNode(this);
+ // make sure having the same owner document
+ if (child.getOwnerDocument() == null) {
+ if (getNodeType() == DOCUMENT_NODE) {
+ child.setOwnerDocument((Document) this);
+ } else {
+ child.setOwnerDocument(getOwnerDocument());
+ }
+ }
+
+ notifyChildReplaced(child, null);
+
+ return child;
+ }
+
+ public boolean isChildEditable() {
+ if (!fChildEditable) {
+ XMLModelImpl model = (XMLModelImpl) getModel();
+ if (model != null && model.isReparsing()) {
+ return true;
+ }
+ }
+ return fChildEditable;
+ }
+
+ /**
+ * isContainer method
+ *
+ * @return boolean
+ */
+ public boolean isContainer() {
+ return true;
+ }
+
+ /**
+ * item method
+ *
+ * @return org.w3c.dom.Node
+ * @param index
+ * int
+ */
+ public Node item(int index) {
+ if (this.firstChild == null)
+ return null;
+ synchronized (lockObject) {
+ if (this.childNodesCache == null)
+ this.childNodesCache = new ChildNodesCache();
+ return this.childNodesCache.item(index);
+ }
+ }
+
+ /**
+ * notifyChildReplaced method
+ *
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param oldChild
+ * org.w3c.dom.Node
+ */
+ protected void notifyChildReplaced(Node newChild, Node oldChild) {
+ DocumentImpl document = (DocumentImpl) getContainerDocument();
+ if (document == null)
+ return;
+
+ syncChildEditableState(newChild);
+
+ XMLModelImpl model = (XMLModelImpl) document.getModel();
+ if (model == null)
+ return;
+ model.childReplaced(this, newChild, oldChild);
+ }
+
+ /**
+ * removeChild method
+ *
+ * @return org.w3c.dom.Node
+ * @param oldChild
+ * org.w3c.dom.Node
+ */
+ public Node removeChild(Node oldChild) throws DOMException {
+ if (oldChild == null)
+ return null;
+ if (oldChild.getParentNode() != this) {
+ throw new DOMException(DOMException.NOT_FOUND_ERR, new String());
+ }
+
+ if (!isChildEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ // synchronized in case another thread is getting item, or length
+ synchronized (lockObject) {
+ this.childNodesCache = null; // invalidate child nodes cache
+ }
+
+ NodeImpl child = (NodeImpl) oldChild;
+ NodeImpl prev = (NodeImpl) child.getPreviousSibling();
+ NodeImpl next = (NodeImpl) child.getNextSibling();
+
+ child.setEditable(true, true); // clear ReadOnly flags
+
+ if (prev == null)
+ this.firstChild = next;
+ else
+ prev.setNextSibling(next);
+ if (next == null)
+ this.lastChild = prev;
+ else
+ next.setPreviousSibling(prev);
+ child.setPreviousSibling(null);
+ child.setNextSibling(null);
+ child.setParentNode(null);
+
+ notifyChildReplaced(null, child);
+
+ return child;
+ }
+
+ /**
+ * removeChildNodes method
+ */
+ public void removeChildNodes() {
+ if (!isChildEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ Node nextChild = null;
+ for (Node child = getFirstChild(); child != null; child = nextChild) {
+ nextChild = child.getNextSibling();
+ removeChild(child);
+ }
+ }
+
+ /**
+ * removeChildNodes method
+ *
+ * @return org.w3c.dom.DocumentFragment
+ * @param firstChild
+ * org.w3c.dom.Node
+ * @param lastChild
+ * org.w3c.dom.Node
+ */
+ public DocumentFragment removeChildNodes(Node firstChild, Node lastChild) {
+ if (!hasChildNodes())
+ return null;
+ if (!isChildEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ Document document = null;
+ if (getNodeType() == DOCUMENT_NODE)
+ document = (Document) this;
+ else
+ document = getOwnerDocument();
+ if (document == null)
+ return null;
+ DocumentFragment fragment = document.createDocumentFragment();
+ if (fragment == null)
+ return null;
+
+ if (firstChild == null)
+ firstChild = getFirstChild();
+ if (lastChild == null)
+ lastChild = getLastChild();
+ Node nextChild = null;
+ for (Node child = firstChild; child != null; child = nextChild) {
+ nextChild = child.getNextSibling();
+ removeChild(child);
+ fragment.appendChild(child);
+ if (child == lastChild)
+ break;
+ }
+
+ return fragment;
+ }
+
+ /**
+ * replaceChild method
+ *
+ * @return org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param oldChild
+ * org.w3c.dom.Node
+ */
+ public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
+ if (!isChildEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ if (oldChild == null)
+ return newChild;
+ if (newChild != null)
+ insertBefore(newChild, oldChild);
+ return removeChild(oldChild);
+ }
+
+ public void setChildEditable(boolean editable) {
+ if (fChildEditable == editable) {
+ return;
+ }
+
+ ReadOnlyController roc = ReadOnlyController.getInstance();
+ Node node;
+ if (editable) {
+ for (node = getFirstChild(); node != null; node = node.getNextSibling()) {
+ roc.unlockNode((XMLNode) node);
+ }
+ } else {
+ for (node = getFirstChild(); node != null; node = node.getNextSibling()) {
+ roc.lockNode((XMLNode) node);
+ }
+ }
+
+ fChildEditable = editable;
+ notifyEditableChanged();
+ }
+
+ protected void syncChildEditableState(Node child) {
+ ReadOnlyController roc = ReadOnlyController.getInstance();
+ if (fChildEditable) {
+ roc.unlockNode((NodeImpl) child);
+ } else {
+ roc.lockNode((NodeImpl) child);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeImpl.java
new file mode 100644
index 0000000000..0ea5dde799
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeImpl.java
@@ -0,0 +1,809 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.AbstractNotifier;
+import org.eclipse.wst.sse.core.IFactoryRegistry;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.document.InvalidCharacterException;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+
+/**
+ * NodeImpl class
+ */
+public abstract class NodeImpl extends AbstractNotifier implements XMLNode {
+ // define one empty nodelist, for repeated use
+ private final static NodeList EMPTY_NODE_LIST = new NodeListImpl();
+
+ private boolean fDataEditable = true;
+ private IStructuredDocumentRegion flatNode = null;
+ private NodeImpl nextSibling = null;
+
+ private DocumentImpl ownerDocument = null;
+ private NodeImpl parentNode = null;
+ private NodeImpl previousSibling = null;
+
+ /**
+ * NodeImpl constructor
+ */
+ protected NodeImpl() {
+ super();
+ }
+
+ /**
+ * NodeImpl constructor
+ *
+ * @param that
+ * NodeImpl
+ */
+ protected NodeImpl(NodeImpl that) {
+ if (that != null) {
+ this.ownerDocument = that.ownerDocument;
+ }
+ }
+
+ /**
+ * appendChild method
+ *
+ * @return org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ */
+ public Node appendChild(Node newChild) throws DOMException {
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, new String());
+ }
+
+ /**
+ * contains method
+ *
+ * @return boolean
+ * @param offset
+ * int
+ */
+ public boolean contains(int offset) {
+ return (offset >= getStartOffset() && offset < getEndOffset());
+ }
+
+ /**
+ * @param s
+ * @param tagName
+ * @return
+ */
+ protected String createDOMExceptionMessage(short s, String tagName) {
+ String result = null;
+ // TODO: Should localize these messages, and provide /u escaped
+ // version of tagName
+ result = lookupMessage(s) + " " + tagName; //$NON-NLS-1$
+ return result;
+ }
+
+ /**
+ * getAttributes method
+ *
+ * @return org.w3c.dom.NamedNodeMap
+ */
+ public NamedNodeMap getAttributes() {
+ return null;
+ }
+
+ /**
+ */
+ protected String getCharValue(String name) {
+ DocumentImpl document = (DocumentImpl) getOwnerDocument();
+ if (document == null)
+ return null;
+ return document.getCharValue(name);
+ }
+
+ /**
+ * getChildNodes method
+ *
+ * @return org.w3c.dom.NodeList
+ */
+ public NodeList getChildNodes() {
+ // As per DOM spec, correct behavior for getChildNodes is to return a
+ // zero length NodeList, not null, when there are no children.
+ // We'll use a common instance of an empty node list, just to prevent
+ // creating a trival object many many times.
+
+ return EMPTY_NODE_LIST;
+ }
+
+ /**
+ * getCommonAncestor method
+ *
+ * @return org.w3c.dom.Node
+ * @param node
+ * org.w3c.dom.Node
+ */
+ public Node getCommonAncestor(Node node) {
+ if (node == null)
+ return null;
+
+ for (Node na = node; na != null; na = na.getParentNode()) {
+ for (Node ta = this; ta != null; ta = ta.getParentNode()) {
+ if (ta == na)
+ return ta;
+ }
+ }
+
+ return null; // not found
+ }
+
+ /**
+ * getContainerDocument method
+ *
+ * @return org.w3c.dom.Document
+ */
+ public Document getContainerDocument() {
+ for (Node node = this; node != null; node = node.getParentNode()) {
+ if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ return (Document) node;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * getEndOffset method
+ *
+ * @return int
+ */
+ public int getEndOffset() {
+ Node node = this;
+ while (node != null) {
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) node;
+ IStructuredDocumentRegion endStructuredDocumentRegion = element.getEndStructuredDocumentRegion();
+ if (endStructuredDocumentRegion != null)
+ return endStructuredDocumentRegion.getEnd();
+ }
+
+ Node last = node.getLastChild();
+ if (last != null) { // dig into the last
+ node = last;
+ continue;
+ }
+
+ IStructuredDocumentRegion lastStructuredDocumentRegion = ((NodeImpl) node).getStructuredDocumentRegion();
+ if (lastStructuredDocumentRegion != null)
+ return lastStructuredDocumentRegion.getEnd();
+
+ Node prev = node.getPreviousSibling();
+ if (prev != null) { // move to the previous
+ node = prev;
+ continue;
+ }
+
+ Node parent = node.getParentNode();
+ node = null;
+ while (parent != null) {
+ if (parent.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) parent;
+ IStructuredDocumentRegion startStructuredDocumentRegion = element.getStartStructuredDocumentRegion();
+ if (startStructuredDocumentRegion != null)
+ return startStructuredDocumentRegion.getEnd();
+ }
+ Node parentPrev = parent.getPreviousSibling();
+ if (parentPrev != null) { // move to the previous
+ node = parentPrev;
+ break;
+ }
+ parent = parent.getParentNode();
+ }
+ }
+ return 0;
+ }
+
+ public IStructuredDocumentRegion getEndStructuredDocumentRegion() {
+ return null;
+ }
+
+ /**
+ */
+ public IFactoryRegistry getFactoryRegistry() {
+ XMLModel model = getModel();
+ if (model != null) {
+ IFactoryRegistry reg = model.getFactoryRegistry();
+ if (reg != null)
+ return reg;
+ }
+ return null;
+ }
+
+ /**
+ * getFirstChild method
+ *
+ * @return org.w3c.dom.Node
+ */
+ public Node getFirstChild() {
+ return null;
+ }
+
+ /**
+ * getFirstStructuredDocumentRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+ return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.flatNode);
+ }
+
+ /**
+ */
+ public int getIndex() {
+ Node parent = getParentNode();
+ if (parent == null)
+ return -1; // error
+ int index = 0;
+ for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child == this)
+ return index;
+ index++;
+ }
+ return -1; // error
+ }
+
+ /**
+ * getLastChild method
+ *
+ * @return org.w3c.dom.Node
+ */
+ public Node getLastChild() {
+ return null;
+ }
+
+ /**
+ * getLastStructuredDocumentRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+ return StructuredDocumentRegionUtil.getStructuredDocumentRegion(this.flatNode);
+ }
+
+ /**
+ */
+ public String getLocalName() {
+ return null;
+ }
+
+ /**
+ * the default implementation can just refer to the owning document
+ */
+ public XMLModel getModel() {
+ if (this.ownerDocument == null)
+ return null;
+ return this.ownerDocument.getModel();
+ }
+
+ /**
+ * all but attr return null
+ */
+ public ITextRegion getNameRegion() {
+ return null;
+ }
+
+ /**
+ */
+ public String getNamespaceURI() {
+ return null;
+ }
+
+ /**
+ * getNextSibling method
+ *
+ * @return org.w3c.dom.Node
+ */
+ public Node getNextSibling() {
+ return this.nextSibling;
+ }
+
+ /**
+ * getNodeAt method
+ *
+ * @return org.w3c.dom.Node
+ * @param offset
+ * int
+ */
+ Node getNodeAt(int offset) {
+ XMLNode parent = this;
+ XMLNode child = (XMLNode) getFirstChild();
+ while (child != null) {
+ if (child.getEndOffset() <= offset) {
+ child = (XMLNode) child.getNextSibling();
+ continue;
+ }
+ if (child.getStartOffset() > offset) {
+ break;
+ }
+
+ IStructuredDocumentRegion startStructuredDocumentRegion = child.getStartStructuredDocumentRegion();
+ if (startStructuredDocumentRegion != null) {
+ if (startStructuredDocumentRegion.getEnd() > offset)
+ return child;
+ }
+
+ // dig more
+ parent = child;
+ child = (XMLNode) parent.getFirstChild();
+ }
+
+ return parent;
+ }
+
+ /**
+ * getNodeValue method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeValue() throws DOMException {
+ return null;
+ }
+
+ /**
+ * getOwnerDocument method
+ *
+ * @return org.w3c.dom.Document
+ */
+ public Document getOwnerDocument() {
+ return this.ownerDocument;
+ }
+
+ /**
+ * getParentNode method
+ *
+ * @return org.w3c.dom.Node
+ */
+ public Node getParentNode() {
+ return this.parentNode;
+ }
+
+ /**
+ */
+ public String getPrefix() {
+ return null;
+ }
+
+ /**
+ * getPreviousSibling method
+ *
+ * @return org.w3c.dom.Node
+ */
+ public Node getPreviousSibling() {
+ return this.previousSibling;
+ }
+
+ /**
+ */
+ public String getSource() {
+ if (this.flatNode == null)
+ return new String();
+ return this.flatNode.getText();
+ }
+
+ /**
+ * getStartOffset method
+ *
+ * @return int
+ */
+ public int getStartOffset() {
+ if (this.flatNode != null)
+ return this.flatNode.getStart();
+ NodeImpl prev = (NodeImpl) getPreviousSibling();
+ if (prev != null)
+ return prev.getEndOffset();
+ Node parent = getParentNode();
+ if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) parent;
+ if (element.hasStartTag())
+ return element.getStartEndOffset();
+ return element.getStartOffset();
+ }
+ // final fallback to look into first child
+ NodeImpl child = (NodeImpl) getFirstChild();
+ while (child != null) {
+ IStructuredDocumentRegion childStructuredDocumentRegion = child.getStructuredDocumentRegion();
+ if (childStructuredDocumentRegion != null)
+ return childStructuredDocumentRegion.getStart();
+ child = (NodeImpl) child.getFirstChild();
+ }
+ return 0;
+ }
+
+ public IStructuredDocumentRegion getStartStructuredDocumentRegion() {
+ return getFirstStructuredDocumentRegion();
+ }
+
+ /**
+ * Every node (indirectly) knows its structuredDocument
+ */
+ public IStructuredDocument getStructuredDocument() {
+ return getModel().getStructuredDocument();
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion getStructuredDocumentRegion() {
+ return this.flatNode;
+ }
+
+ /**
+ * all but attr return null
+ */
+ public ITextRegion getValueRegion() {
+ return null;
+ }
+
+ /**
+ */
+ public String getValueSource() {
+ return getNodeValue();
+ }
+
+ /**
+ */
+ public boolean hasAttributes() {
+ return false;
+ }
+
+ /**
+ * hasChildNodes method
+ *
+ * @return boolean
+ */
+ public boolean hasChildNodes() {
+ return false;
+ }
+
+ /**
+ * hasProperties method
+ *
+ * @return boolean
+ */
+ public boolean hasProperties() {
+ return false;
+ }
+
+ /**
+ * insertBefore method
+ *
+ * @return org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param refChild
+ * org.w3c.dom.Node
+ */
+ public Node insertBefore(Node newChild, Node refChild) throws DOMException {
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, new String());
+ }
+
+ public boolean isChildEditable() {
+ return false;
+ }
+
+ /**
+ */
+ public boolean isClosed() {
+ return true;
+ }
+
+ /**
+ * isContainer method
+ *
+ * @return boolean
+ */
+ public boolean isContainer() {
+ return false;
+ }
+
+ public boolean isDataEditable() {
+ if (!fDataEditable) {
+ XMLModelImpl model = (XMLModelImpl) getModel();
+ if (model != null && model.isReparsing()) {
+ return true;
+ }
+ }
+ return fDataEditable;
+ }
+
+ /**
+ */
+ public boolean isSupported(String feature, String version) {
+ if (this.ownerDocument == null)
+ return false;
+ DOMImplementation impl = this.ownerDocument.getImplementation();
+ if (impl == null)
+ return false;
+ return impl.hasFeature(feature, version);
+ }
+
+ /**
+ * @param s
+ * @return
+ */
+ private String lookupMessage(short s) {
+ // TODO: make localized version
+ String result = null;
+ switch (s) {
+ case DOMException.INVALID_CHARACTER_ERR :
+ result = "INVALID_CHARACTER_ERR"; //$NON-NLS-1$
+ break;
+
+ default :
+ result = new String();
+ break;
+ }
+ return result;
+ }
+
+ /**
+ * normalize method
+ */
+ public void normalize() {
+ TextImpl prevText = null;
+ for (Node child = getFirstChild(); child != null; child = child.getNextSibling()) {
+ switch (child.getNodeType()) {
+ case TEXT_NODE : {
+ if (prevText == null) {
+ prevText = (TextImpl) child;
+ break;
+ }
+ Text text = (Text) child;
+ removeChild(text);
+ prevText.appendText(text);
+ child = prevText;
+ break;
+ }
+ case ELEMENT_NODE : {
+ Element element = (Element) child;
+ element.normalize();
+ prevText = null;
+ break;
+ }
+ default :
+ prevText = null;
+ break;
+ }
+ }
+ }
+
+ protected void notifyEditableChanged() {
+ DocumentImpl document = (DocumentImpl) getContainerDocument();
+ if (document == null)
+ return;
+ XMLModelImpl model = (XMLModelImpl) document.getModel();
+ if (model == null)
+ return;
+ model.editableChanged(this);
+ }
+
+ /**
+ * notifyValueChanged method
+ */
+ protected void notifyValueChanged() {
+ DocumentImpl document = (DocumentImpl) getContainerDocument();
+ if (document == null)
+ return;
+
+ syncDataEditableState();
+
+ XMLModelImpl model = (XMLModelImpl) document.getModel();
+ if (model == null)
+ return;
+ model.valueChanged(this);
+ }
+
+ /**
+ * removeChild method
+ *
+ * @return org.w3c.dom.Node
+ * @param oldChild
+ * org.w3c.dom.Node
+ */
+ public Node removeChild(Node oldChild) throws DOMException {
+ throw new DOMException(DOMException.NOT_FOUND_ERR, new String());
+ }
+
+ /**
+ * removeChildNodes method
+ */
+ public void removeChildNodes() {
+ }
+
+ /**
+ * removeChildNodes method
+ *
+ * @return org.w3c.dom.DocumentFragment
+ * @param firstChild
+ * org.w3c.dom.Node
+ * @param lastChild
+ * org.w3c.dom.Node
+ */
+ public DocumentFragment removeChildNodes(Node firstChild, Node lastChild) {
+ return null;
+ }
+
+ /**
+ * replaceChild method
+ *
+ * @return org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param oldChild
+ * org.w3c.dom.Node
+ */
+ public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
+ throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, new String());
+ }
+
+ /**
+ * Resets children values from IStructuredDocumentRegion.
+ */
+ void resetStructuredDocumentRegions() {
+ for (NodeImpl child = (NodeImpl) getFirstChild(); child != null; child = (NodeImpl) child.getNextSibling()) {
+ child.resetStructuredDocumentRegions();
+ }
+ this.flatNode = null;
+ }
+
+ public void setChildEditable(boolean editable) {
+ // nop
+ }
+
+ public void setDataEditable(boolean editable) {
+ if (fDataEditable == editable) {
+ return;
+ }
+
+ ReadOnlyController roc = ReadOnlyController.getInstance();
+ if (editable) {
+ roc.unlockData(this);
+ } else {
+ roc.lockData(this);
+ }
+
+ fDataEditable = editable;
+
+ notifyEditableChanged();
+ }
+
+ public void setEditable(boolean editable, boolean deep) {
+ if (deep) {
+ XMLNode node = (XMLNode) getFirstChild();
+ while (node != null) {
+ node.setEditable(editable, deep);
+ node = (XMLNode) node.getNextSibling();
+ }
+ }
+ setChildEditable(editable);
+ setDataEditable(editable);
+ }
+
+ /**
+ * setNextSibling method
+ *
+ * @param nextSibling
+ * org.w3c.dom.Node
+ */
+ protected void setNextSibling(Node nextSibling) {
+ this.nextSibling = (NodeImpl) nextSibling;
+ }
+
+ /**
+ * setNodeValue method
+ *
+ * @param nodeValue
+ * java.lang.String
+ */
+ public void setNodeValue(String nodeValue) throws DOMException {
+ }
+
+ /**
+ * setOwnerDocument method
+ *
+ * @param ownerDocument
+ * org.w3c.dom.Document
+ */
+ protected void setOwnerDocument(Document ownerDocument) {
+ this.ownerDocument = (DocumentImpl) ownerDocument;
+ }
+
+ /**
+ */
+ protected void setOwnerDocument(Document ownerDocument, boolean deep) {
+ this.ownerDocument = (DocumentImpl) ownerDocument;
+
+ if (deep) {
+ for (NodeImpl child = (NodeImpl) getFirstChild(); child != null; child = (NodeImpl) child.getNextSibling()) {
+ child.setOwnerDocument(ownerDocument, deep);
+ }
+ }
+ }
+
+ /**
+ * setParentNode method
+ *
+ * @param parentNode
+ * org.w3c.dom.Node
+ */
+ protected void setParentNode(Node parentNode) {
+ this.parentNode = (NodeImpl) parentNode;
+ }
+
+ /**
+ */
+ public void setPrefix(String prefix) throws DOMException {
+ }
+
+ /**
+ * setPreviousSibling method
+ *
+ * @param previousSibling
+ * org.w3c.dom.Node
+ */
+ protected void setPreviousSibling(Node previousSibling) {
+ this.previousSibling = (NodeImpl) previousSibling;
+ }
+
+ /**
+ */
+ public void setSource(String source) throws InvalidCharacterException {
+ // not supported
+ }
+
+ /**
+ */
+ void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ this.flatNode = flatNode;
+ }
+
+ /**
+ */
+ public void setValueSource(String source) {
+ setNodeValue(source);
+ }
+
+ protected void syncDataEditableState() {
+ ReadOnlyController roc = ReadOnlyController.getInstance();
+ if (fDataEditable) {
+ roc.unlockData(this);
+ } else {
+ roc.lockData(this);
+ }
+ }
+
+ /**
+ * toString method
+ *
+ * @return java.lang.String
+ */
+ public String toString() {
+ return getNodeName();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeIteratorImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeIteratorImpl.java
new file mode 100644
index 0000000000..c4a278b694
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeIteratorImpl.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+
+/**
+ * NodeIteratorImpl class
+ */
+public class NodeIteratorImpl implements NodeIterator {
+ private NodeFilter filter = null;
+ private Node nextNode = null;
+
+ private Node rootNode = null;
+ private int whatToShow = NodeFilter.SHOW_ALL;
+
+ /**
+ * NodeIteratorImpl constructor
+ *
+ * @param rootNode
+ * org.w3c.dom.Node
+ */
+ NodeIteratorImpl(Node rootNode, int whatToShow, NodeFilter filter) {
+ this.rootNode = rootNode;
+ this.nextNode = rootNode;
+ this.whatToShow = whatToShow;
+ this.filter = filter;
+ }
+
+ /**
+ */
+ private final boolean acceptNode(Node node) {
+ if (this.whatToShow != NodeFilter.SHOW_ALL) {
+ if (node == null)
+ return false;
+ short nodeType = node.getNodeType();
+ switch (this.whatToShow) {
+ case NodeFilter.SHOW_ELEMENT :
+ if (nodeType != Node.ELEMENT_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_ATTRIBUTE :
+ if (nodeType != Node.ATTRIBUTE_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_TEXT :
+ if (nodeType != Node.TEXT_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_CDATA_SECTION :
+ if (nodeType != Node.CDATA_SECTION_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_ENTITY_REFERENCE :
+ if (nodeType != Node.ENTITY_REFERENCE_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_ENTITY :
+ if (nodeType != Node.ENTITY_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_PROCESSING_INSTRUCTION :
+ if (nodeType != Node.PROCESSING_INSTRUCTION_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_COMMENT :
+ if (nodeType != Node.COMMENT_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_DOCUMENT :
+ if (nodeType != Node.DOCUMENT_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_DOCUMENT_TYPE :
+ if (nodeType != Node.DOCUMENT_TYPE_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_DOCUMENT_FRAGMENT :
+ if (nodeType != Node.DOCUMENT_FRAGMENT_NODE)
+ return false;
+ break;
+ case NodeFilter.SHOW_NOTATION :
+ if (nodeType != Node.NOTATION_NODE)
+ return false;
+ break;
+ default :
+ return false;
+ }
+ }
+ if (this.filter != null) {
+ return (this.filter.acceptNode(node) == NodeFilter.FILTER_ACCEPT);
+ }
+ return true;
+ }
+
+ /**
+ * Detaches the <code>NodeIterator</code> from the set which it iterated
+ * over, releasing any computational resources and placing the iterator in
+ * the INVALID state. After <code>detach</code> has been invoked, calls
+ * to <code>nextNode</code> or <code>previousNode</code> will raise
+ * the exception INVALID_STATE_ERR.
+ */
+ public void detach() {
+ this.rootNode = null;
+ this.nextNode = null;
+ this.filter = null;
+ }
+
+ /**
+ * The value of this flag determines whether the children of entity
+ * reference nodes are visible to the iterator. If false, they and their
+ * descendants will be rejected. Note that this rejection takes precedence
+ * over <code>whatToShow</code> and the filter. Also note that this is
+ * currently the only situation where <code>NodeIterators</code> may
+ * reject a complete subtree rather than skipping individual nodes. <br>
+ * <br>
+ * To produce a view of the document that has entity references expanded
+ * and does not expose the entity reference node itself, use the
+ * <code>whatToShow</code> flags to hide the entity reference node and
+ * set <code>expandEntityReferences</code> to true when creating the
+ * iterator. To produce a view of the document that has entity reference
+ * nodes but no entity expansion, use the <code>whatToShow</code> flags
+ * to show the entity reference node and set
+ * <code>expandEntityReferences</code> to false.
+ */
+ public boolean getExpandEntityReferences() {
+ // not supported
+ return false;
+ }
+
+ /**
+ * The <code>NodeFilter</code> used to screen nodes.
+ */
+ public NodeFilter getFilter() {
+ return this.filter;
+ }
+
+ /**
+ */
+ private final Node getNextNode() {
+ if (this.nextNode == null)
+ return null;
+ Node oldNext = this.nextNode;
+ Node child = this.nextNode.getFirstChild();
+ if (child != null) {
+ this.nextNode = child;
+ return oldNext;
+ }
+ for (Node node = this.nextNode; node != null && node != this.rootNode; node = node.getParentNode()) {
+ Node next = node.getNextSibling();
+ if (next != null) {
+ this.nextNode = next;
+ return oldNext;
+ }
+ }
+ this.nextNode = null;
+ return oldNext;
+ }
+
+ /**
+ */
+ private final Node getPreviousNode() {
+ if (this.nextNode == this.rootNode)
+ return null;
+ Node prev = null;
+ if (this.nextNode == null) {
+ prev = this.rootNode; // never null
+ } else {
+ prev = this.nextNode.getPreviousSibling();
+ if (prev == null) {
+ this.nextNode = this.nextNode.getParentNode();
+ return this.nextNode;
+ }
+ }
+ Node last = prev.getLastChild();
+ while (last != null) {
+ prev = last;
+ last = prev.getLastChild();
+ }
+ this.nextNode = prev;
+ return this.nextNode;
+ }
+
+ /**
+ * The root node of the <code>NodeIterator</code>, as specified when it
+ * was created.
+ */
+ public Node getRoot() {
+ return this.rootNode;
+ }
+
+ /**
+ * This attribute determines which node types are presented via the
+ * iterator. The available set of constants is defined in the
+ * <code>NodeFilter</code> interface. Nodes not accepted by
+ * <code>whatToShow</code> will be skipped, but their children may still
+ * be considered. Note that this skip takes precedence over the filter, if
+ * any.
+ */
+ public int getWhatToShow() {
+ return this.whatToShow;
+ }
+
+ /**
+ * Returns the next node in the set and advances the position of the
+ * iterator in the set. After a <code>NodeIterator</code> is created,
+ * the first call to <code>nextNode()</code> returns the first node in
+ * the set.
+ *
+ * @return The next <code>Node</code> in the set being iterated over, or
+ * <code>null</code> if there are no more members in that set.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if this method is called after
+ * the <code>detach</code> method was invoked.
+ */
+ public Node nextNode() throws DOMException {
+ for (Node node = getNextNode(); node != null; node = getNextNode()) {
+ if (acceptNode(node))
+ return node;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the previous node in the set and moves the position of the
+ * <code>NodeIterator</code> backwards in the set.
+ *
+ * @return The previous <code>Node</code> in the set being iterated
+ * over, or <code>null</code> if there are no more members in
+ * that set.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if this method is called after
+ * the <code>detach</code> method was invoked.
+ */
+ public Node previousNode() throws DOMException {
+ for (Node node = getPreviousNode(); node != null; node = getPreviousNode()) {
+ if (acceptNode(node))
+ return node;
+ }
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeListImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeListImpl.java
new file mode 100644
index 0000000000..4bfed52901
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NodeListImpl.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Vector;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * NodeListImpl class
+ */
+public class NodeListImpl implements NodeList {
+
+ Object lockObject = new byte[0];
+
+ private Vector nodes = null;
+
+ /**
+ * NodeListImpl constructor
+ */
+ public NodeListImpl() {
+ super();
+ }
+
+ /**
+ * appendNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param node
+ * org.w3c.dom.Node
+ */
+ protected Node appendNode(Node node) {
+ if (node == null)
+ return null;
+ if (this.nodes == null)
+ this.nodes = new Vector();
+ this.nodes.addElement(node);
+ return node;
+ }
+
+ /**
+ * getLength method
+ *
+ * @return int
+ */
+ public int getLength() {
+ synchronized (lockObject) {
+ if (this.nodes == null)
+ return 0;
+ return this.nodes.size();
+ }
+ }
+
+ /**
+ */
+ protected Node insertNode(Node node, int index) {
+ if (node == null)
+ return null;
+ if (this.nodes == null || index >= this.nodes.size()) {
+ return appendNode(node);
+ }
+ this.nodes.insertElementAt(node, index);
+ return node;
+ }
+
+ /**
+ * item method
+ *
+ * @return org.w3c.dom.Node
+ */
+ public Node item(int index) {
+ synchronized (lockObject) {
+ if (this.nodes == null)
+ return null;
+ if (index < 0 || index >= this.nodes.size())
+ return null;
+ return (Node) this.nodes.elementAt(index);
+ }
+ }
+
+ /**
+ * removeNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param index
+ * int
+ */
+ protected Node removeNode(int index) {
+ if (this.nodes == null)
+ return null; // no node
+ if (index < 0 || index >= this.nodes.size())
+ return null; // invalid parameter
+
+ Node removed = (Node) this.nodes.elementAt(index);
+ this.nodes.removeElementAt(index);
+ return removed;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NotationImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NotationImpl.java
new file mode 100644
index 0000000000..e0489499ed
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/NotationImpl.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.Notation;
+
+/**
+ * NotationImpl class
+ */
+public class NotationImpl extends NodeImpl implements Notation {
+
+ private String name = null;
+ private String publicId = null;
+ private String systemId = null;
+
+ /**
+ * NotationImpl constructor
+ */
+ protected NotationImpl() {
+ super();
+ }
+
+ /**
+ * NotationImpl constructor
+ *
+ * @param that
+ * NotationImpl
+ */
+ protected NotationImpl(NotationImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.name = that.name;
+ this.publicId = that.publicId;
+ this.systemId = that.systemId;
+ }
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ NotationImpl cloned = new NotationImpl(this);
+ return cloned;
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ if (this.name == null)
+ return new String();
+ return this.name;
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return NOTATION_NODE;
+ }
+
+ /**
+ * getPublicId method
+ *
+ * @return java.lang.String
+ */
+ public String getPublicId() {
+ return this.publicId;
+ }
+
+ /**
+ * getSystemId method
+ *
+ * @return java.lang.String
+ */
+ public String getSystemId() {
+ return this.systemId;
+ }
+
+ /**
+ * setName method
+ *
+ * @param name
+ * java.lang.String
+ */
+ protected void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * setPublicId method
+ *
+ * @param publicId
+ * java.lang.String
+ */
+ public void setPublicId(String publicId) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ this.publicId = publicId;
+ }
+
+ /**
+ * setSystemId method
+ *
+ * @param systemId
+ * java.lang.String
+ */
+ public void setSystemId(String systemId) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ this.systemId = systemId;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ProcessingInstructionImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ProcessingInstructionImpl.java
new file mode 100644
index 0000000000..de9a4fe014
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ProcessingInstructionImpl.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Iterator;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+
+
+/**
+ * ProcessingInstructionImpl class
+ */
+public class ProcessingInstructionImpl extends NodeImpl implements XMLJSPRegionContexts, ProcessingInstruction {
+ private String data = null;
+
+ private String target = null;
+
+ /**
+ * ProcessingInstructionImpl constructor
+ */
+ protected ProcessingInstructionImpl() {
+ super();
+ }
+
+ /**
+ * ProcessingInstructionImpl constructor
+ *
+ * @param that
+ * ProcessingInstructionImpl
+ */
+ protected ProcessingInstructionImpl(ProcessingInstructionImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.target = that.target;
+ this.data = that.getData();
+ }
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ ProcessingInstructionImpl cloned = new ProcessingInstructionImpl(this);
+ return cloned;
+ }
+
+ /**
+ * getData method
+ *
+ * @return java.lang.String
+ */
+ public String getData() {
+ if (this.data != null)
+ return this.data;
+
+ IStructuredDocumentRegion flatNode = getFirstStructuredDocumentRegion();
+ if (flatNode == null)
+ return new String();
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return new String();
+
+ ITextRegion targetRegion = null;
+ ITextRegion dataRegion = null;
+ ITextRegion closeRegion = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_PI_OPEN)
+ continue;
+ if (regionType == XMLRegionContext.XML_PI_CLOSE) {
+ closeRegion = region;
+ } else {
+ if (targetRegion == null)
+ targetRegion = region;
+ else if (dataRegion == null)
+ dataRegion = region;
+ }
+ }
+ if (dataRegion == null)
+ return new String();
+ int offset = dataRegion.getStart();
+ int end = flatNode.getLength();
+ if (closeRegion != null)
+ end = closeRegion.getStart();
+ String source = flatNode.getText();
+ return source.substring(offset, end);
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ return getTarget();
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return PROCESSING_INSTRUCTION_NODE;
+ }
+
+ /**
+ * getNodeValue method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeValue() {
+ return getData();
+ }
+
+ /**
+ * getTarget method
+ *
+ * @return java.lang.String
+ */
+ public String getTarget() {
+ if (this.target == null)
+ return new String();
+ return this.target;
+ }
+
+ /**
+ */
+ public boolean isClosed() {
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return true; // will be generated
+ String regionType = StructuredDocumentRegionUtil.getLastRegionType(flatNode);
+ return (regionType == XMLRegionContext.XML_PI_CLOSE);
+ }
+
+ /**
+ */
+ void resetStructuredDocumentRegions() {
+ this.data = getData();
+ setStructuredDocumentRegion(null);
+ }
+
+ /**
+ * setData method
+ *
+ * @param data
+ * java.lang.String
+ */
+ public void setData(String data) throws DOMException {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.data = data;
+
+ notifyValueChanged();
+ }
+
+ /**
+ * setNodeValue method
+ *
+ * @param nodeValue
+ * java.lang.String
+ */
+ public void setNodeValue(String nodeValue) throws DOMException {
+ setData(nodeValue);
+ }
+
+ /**
+ */
+ void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ super.setStructuredDocumentRegion(flatNode);
+ if (flatNode != null)
+ this.data = null;
+ }
+
+ /**
+ * setTarget method
+ *
+ * @param target
+ * java.lang.String
+ */
+ protected void setTarget(String target) {
+ this.target = target;
+ }
+
+ /**
+ * toString method
+ *
+ * @return java.lang.String
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(getTarget());
+ buffer.append('(');
+ buffer.append(getData());
+ buffer.append(')');
+ return buffer.toString();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/RangeImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/RangeImpl.java
new file mode 100644
index 0000000000..1c54ba53d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/RangeImpl.java
@@ -0,0 +1,630 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.ranges.Range;
+import org.w3c.dom.ranges.RangeException;
+
+
+/**
+ */
+public class RangeImpl implements Range {
+ private Node endContainer = null;
+ private int endOffset = 0;
+
+ private Node startContainer = null;
+ private int startOffset = 0;
+
+ /**
+ */
+ protected RangeImpl() {
+ super();
+ }
+
+ /**
+ */
+ protected RangeImpl(RangeImpl that) {
+ super();
+
+ if (that != null) {
+ this.startContainer = that.startContainer;
+ this.startOffset = that.startOffset;
+ this.endContainer = that.endContainer;
+ this.endOffset = that.endOffset;
+ }
+ }
+
+ /**
+ * Duplicates the contents of a Range
+ *
+ * @return A DocumentFragment that contains content equivalent to this
+ * Range.
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if a DocumentType node
+ * would be extracted into the new DocumentFragment. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public DocumentFragment cloneContents() throws DOMException {
+ // not supported
+ return null;
+ }
+
+ /**
+ * Produces a new Range whose boundary-points are equal to the
+ * boundary-points of the Range.
+ *
+ * @return The duplicated Range.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public Range cloneRange() throws DOMException {
+ return new RangeImpl(this);
+ }
+
+ /**
+ * Collapse a Range onto one of its boundary-points
+ *
+ * @param toStartIf
+ * TRUE, collapses the Range onto its start; if FALSE,
+ * collapses it onto its end.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void collapse(boolean toStart) throws DOMException {
+ if (toStart) {
+ this.endContainer = this.startContainer;
+ this.endOffset = this.startOffset;
+ } else {
+ this.startContainer = this.endContainer;
+ this.startOffset = this.endOffset;
+ }
+ }
+
+ /**
+ * Compare the boundary-points of two Ranges in a document.
+ *
+ * @param howA
+ * code representing the type of comparison, as defined above.
+ * @param sourceRangeThe
+ * <code>Range</code> on which this current
+ * <code>Range</code> is compared to.
+ * @return -1, 0 or 1 depending on whether the corresponding
+ * boundary-point of the Range is respectively before, equal to,
+ * or after the corresponding boundary-point of
+ * <code>sourceRange</code>.
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in
+ * the same Document or DocumentFragment. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public short compareBoundaryPoints(short how, Range sourceRange) throws DOMException {
+ if (sourceRange == null)
+ return (short) 0; // error
+
+ Node container1 = null;
+ int offset1 = 0;
+ Node container2 = null;
+ int offset2 = 0;
+
+ switch (how) {
+ case START_TO_START :
+ container1 = this.startContainer;
+ offset1 = this.startOffset;
+ container2 = sourceRange.getStartContainer();
+ offset2 = sourceRange.getStartOffset();
+ break;
+ case START_TO_END :
+ container1 = this.startContainer;
+ offset1 = this.startOffset;
+ container2 = sourceRange.getEndContainer();
+ offset2 = sourceRange.getEndOffset();
+ break;
+ case END_TO_END :
+ container1 = this.endContainer;
+ offset1 = this.endOffset;
+ container2 = sourceRange.getEndContainer();
+ offset2 = sourceRange.getEndOffset();
+ break;
+ case END_TO_START :
+ container1 = this.endContainer;
+ offset1 = this.endOffset;
+ container2 = sourceRange.getStartContainer();
+ offset2 = sourceRange.getStartOffset();
+ break;
+ default :
+ return (short) 0; // error
+ }
+
+ return comparePoints(container1, offset1, container2, offset2);
+ }
+
+ /*
+ */
+ protected short comparePoints(Node container1, int offset1, Node container2, int offset2) {
+ if (container1 == null || container2 == null)
+ return (short) 0; // error
+
+ if (container1 == container2) {
+ if (offset1 > offset2)
+ return (short) 1;
+ if (offset1 < offset2)
+ return (short) -1;
+ return 0;
+ }
+
+ // get node offsets
+ XMLNode node1 = null;
+ if (container1.hasChildNodes()) {
+ Node child = container1.getFirstChild();
+ for (int i = 0; i < offset1; i++) {
+ Node next = child.getNextSibling();
+ if (next == null)
+ break;
+ child = next;
+ }
+ node1 = (XMLNode) child;
+ offset1 = 0;
+ } else {
+ node1 = (XMLNode) container1;
+ }
+ int nodeOffset1 = node1.getStartOffset();
+ XMLNode node2 = null;
+ if (container2.hasChildNodes()) {
+ Node child = container2.getFirstChild();
+ for (int i = 0; i < offset2; i++) {
+ Node next = child.getNextSibling();
+ if (next == null)
+ break;
+ child = next;
+ }
+ node2 = (XMLNode) child;
+ offset2 = 0;
+ } else {
+ node2 = (XMLNode) container1;
+ }
+ int nodeOffset2 = node2.getStartOffset();
+
+ if (nodeOffset1 > nodeOffset2)
+ return (short) 1;
+ if (nodeOffset1 < nodeOffset2)
+ return (short) -1;
+ if (offset1 > offset2)
+ return (short) 1;
+ if (offset1 < offset2)
+ return (short) -1;
+ return (short) 0;
+ }
+
+ /**
+ * Removes the contents of a Range from the containing document or
+ * document fragment without returning a reference to the removed content.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of
+ * the content of the Range is read-only or any of the
+ * nodes that contain any of the content of the Range are
+ * read-only. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void deleteContents() throws DOMException {
+ // not supported
+ }
+
+ /**
+ * Called to indicate that the Range is no longer in use and that the
+ * implementation may relinquish any resources associated with this Range.
+ * Subsequent calls to any methods or attribute getters on this Range will
+ * result in a <code>DOMException</code> being thrown with an error code
+ * of <code>INVALID_STATE_ERR</code>.
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void detach() throws DOMException {
+ this.startContainer = null;
+ this.startOffset = 0;
+ this.endContainer = null;
+ this.endOffset = 0;
+ }
+
+ /**
+ * Moves the contents of a Range from the containing document or document
+ * fragment to a new DocumentFragment.
+ *
+ * @return A DocumentFragment containing the extracted contents.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of
+ * the content of the Range is read-only or any of the
+ * nodes which contain any of the content of the Range are
+ * read-only. <br>
+ * HIERARCHY_REQUEST_ERR: Raised if a DocumentType node
+ * would be extracted into the new DocumentFragment. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public DocumentFragment extractContents() throws DOMException {
+ // not supported
+ return null;
+ }
+
+ /**
+ * TRUE if the Range is collapsed
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public boolean getCollapsed() throws DOMException {
+ if (this.startContainer == this.endContainer && this.startOffset == this.endOffset)
+ return true;
+ return false;
+ }
+
+ /**
+ * The deepest common ancestor container of the Range's two
+ * boundary-points.
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public Node getCommonAncestorContainer() throws DOMException {
+ if (this.startContainer == null)
+ return null;
+ return ((NodeImpl) this.startContainer).getCommonAncestor(this.endContainer);
+ }
+
+ /**
+ * Node within which the Range ends
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public Node getEndContainer() throws DOMException {
+ return this.endContainer;
+ }
+
+ /**
+ * Offset within the ending node of the Range.
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public int getEndOffset() throws DOMException {
+ return this.endOffset;
+ }
+
+ /**
+ * Node within which the Range begins
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public Node getStartContainer() throws DOMException {
+ return this.startContainer;
+ }
+
+ /**
+ * Offset within the starting node of the Range.
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public int getStartOffset() throws DOMException {
+ return this.startOffset;
+ }
+
+ /**
+ * Inserts a node into the Document or DocumentFragment at the start of
+ * the Range. If the container is a Text node, this will be split at the
+ * start of the Range (as if the Text node's splitText method was
+ * performed at the insertion point) and the insertion will occur between
+ * the two resulting Text nodes. Adjacent Text nodes will not be
+ * automatically merged. If the node to be inserted is a DocumentFragment
+ * node, the children will be inserted rather than the DocumentFragment
+ * node itself.
+ *
+ * @param newNodeThe
+ * node to insert at the start of the Range
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor
+ * container of the start of the Range is read-only. <br>
+ * WRONG_DOCUMENT_ERR: Raised if <code>newNode</code> and
+ * the container of the start of the Range were not created
+ * from the same document. <br>
+ * HIERARCHY_REQUEST_ERR: Raised if the container of the
+ * start of the Range is of a type that does not allow
+ * children of the type of <code>newNode</code> or if
+ * <code>newNode</code> is an ancestor of the container.
+ * <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if <code>newNode</code>
+ * is an Attr, Entity, Notation, or Document node.
+ */
+ public void insertNode(Node newNode) throws RangeException, DOMException {
+ // not supported
+ }
+
+ /**
+ * Select a node and its contents
+ *
+ * @param refNodeThe
+ * node to select.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if an ancestor of
+ * <code>refNode</code> is an Entity, Notation or
+ * DocumentType node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void selectNode(Node refNode) throws RangeException, DOMException {
+ if (refNode == null)
+ return;
+ Node parent = refNode.getParentNode();
+ if (parent == null)
+ return;
+ int index = ((NodeImpl) refNode).getIndex();
+ if (index < 0)
+ return;
+ setStart(parent, index);
+ setEnd(parent, index + 1);
+ }
+
+ /**
+ * Select the contents within a node
+ *
+ * @param refNodeNode
+ * to select from
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code>
+ * or an ancestor of <code>refNode</code> is an Entity,
+ * Notation or DocumentType node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void selectNodeContents(Node refNode) throws RangeException, DOMException {
+ if (refNode == null)
+ return;
+ if (refNode.getNodeType() == Node.TEXT_NODE) {
+ Text text = (Text) refNode;
+ setStart(refNode, 0);
+ setEnd(refNode, text.getLength());
+ } else {
+ NodeList childNodes = refNode.getChildNodes();
+ int length = (childNodes != null ? childNodes.getLength() : 0);
+ setStart(refNode, 0);
+ setEnd(refNode, length);
+ }
+ }
+
+ /**
+ * Sets the attributes describing the end of a Range.
+ *
+ * @param refNodeThe
+ * <code>refNode</code> value. This parameter must be
+ * different from <code>null</code>.
+ * @param offsetThe
+ * <code>endOffset</code> value.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code>
+ * or an ancestor of <code>refNode</code> is an Entity,
+ * Notation, or DocumentType node.
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if <code>offset</code> is
+ * negative or greater than the number of child units in
+ * <code>refNode</code>. Child units are 16-bit units if
+ * <code>refNode</code> is a type of CharacterData node
+ * (e.g., a Text or Comment node) or a
+ * ProcessingInstruction node. Child units are Nodes in all
+ * other cases. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setEnd(Node refNode, int offset) throws RangeException, DOMException {
+ this.endContainer = refNode;
+ this.endOffset = offset;
+ }
+
+ /**
+ * Sets the end of a Range to be after a node
+ *
+ * @param refNodeRange
+ * ends after <code>refNode</code>.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if the root container of
+ * <code>refNode</code> is not an Attr, Document or
+ * DocumentFragment node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setEndAfter(Node refNode) throws RangeException, DOMException {
+ if (refNode == null)
+ return;
+ Node parent = refNode.getParentNode();
+ if (parent == null)
+ return;
+ int index = ((NodeImpl) refNode).getIndex();
+ if (index < 0)
+ return;
+ setEnd(parent, index + 1);
+ }
+
+ /**
+ * Sets the end position to be before a node.
+ *
+ * @param refNodeRange
+ * ends before <code>refNode</code>
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if the root container of
+ * <code>refNode</code> is not an Attr, Document, or
+ * DocumentFragment node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setEndBefore(Node refNode) throws RangeException, DOMException {
+ if (refNode == null)
+ return;
+ Node parent = refNode.getParentNode();
+ if (parent == null)
+ return;
+ int index = ((NodeImpl) refNode).getIndex();
+ if (index < 0)
+ return;
+ setEnd(parent, index);
+ }
+
+ /**
+ * Sets the attributes describing the start of the Range.
+ *
+ * @param refNodeThe
+ * <code>refNode</code> value. This parameter must be
+ * different from <code>null</code>.
+ * @param offsetThe
+ * <code>startOffset</code> value.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code>
+ * or an ancestor of <code>refNode</code> is an Entity,
+ * Notation, or DocumentType node.
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if <code>offset</code> is
+ * negative or greater than the number of child units in
+ * <code>refNode</code>. Child units are 16-bit units if
+ * <code>refNode</code> is a type of CharacterData node
+ * (e.g., a Text or Comment node) or a
+ * ProcessingInstruction node. Child units are Nodes in all
+ * other cases. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setStart(Node refNode, int offset) throws RangeException, DOMException {
+ this.startContainer = refNode;
+ this.startOffset = offset;
+ }
+
+ /**
+ * Sets the start position to be after a node
+ *
+ * @param refNodeRange
+ * starts after <code>refNode</code>
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if the root container of
+ * <code>refNode</code> is not an Attr, Document, or
+ * DocumentFragment node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setStartAfter(Node refNode) throws RangeException, DOMException {
+ if (refNode == null)
+ return;
+ Node parent = refNode.getParentNode();
+ if (parent == null)
+ return;
+ int index = ((NodeImpl) refNode).getIndex();
+ if (index < 0)
+ return;
+ setStart(parent, index + 1);
+ }
+
+ /**
+ * Sets the start position to be before a node
+ *
+ * @param refNodeRange
+ * starts before <code>refNode</code>
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if the root container of
+ * <code>refNode</code> is not an Attr, Document, or
+ * DocumentFragment node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setStartBefore(Node refNode) throws RangeException, DOMException {
+ if (refNode == null)
+ return;
+ Node parent = refNode.getParentNode();
+ if (parent == null)
+ return;
+ int index = ((NodeImpl) refNode).getIndex();
+ if (index < 0)
+ return;
+ setStart(parent, index);
+ }
+
+ /**
+ * Reparents the contents of the Range to the given node and inserts the
+ * node at the position of the start of the Range.
+ *
+ * @param newParentThe
+ * node to surround the contents with.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor
+ * container of either boundary-point of the Range is
+ * read-only. <br>
+ * WRONG_DOCUMENT_ERR: Raised if <code> newParent</code>
+ * and the container of the start of the Range were not
+ * created from the same document. <br>
+ * HIERARCHY_REQUEST_ERR: Raised if the container of the
+ * start of the Range is of a type that does not allow
+ * children of the type of <code>newParent</code> or if
+ * <code>newParent</code> is an ancestor of the container
+ * or if <code>node</code> would end up with a child node
+ * of a type not allowed by the type of <code>node</code>.
+ * <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ * @exception RangeException
+ * BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially
+ * selects a non-text node. <br>
+ * INVALID_NODE_TYPE_ERR: Raised if <code> node</code> is
+ * an Attr, Entity, DocumentType, Notation, Document, or
+ * DocumentFragment node.
+ */
+ public void surroundContents(Node newParent) throws RangeException, DOMException {
+ // not supported
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ReadOnlyController.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ReadOnlyController.java
new file mode 100644
index 0000000000..67aa59c493
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/ReadOnlyController.java
@@ -0,0 +1,334 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.document.XMLText;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Node;
+
+
+class ReadOnlyController {
+
+ class Span {
+ int length;
+ int offset;
+
+ Span(int offset, int length) {
+ this.offset = offset;
+ this.length = length;
+ }
+ }
+
+ private static ReadOnlyController fInstance;
+
+ static synchronized ReadOnlyController getInstance() {
+ if (fInstance == null) {
+ fInstance = new ReadOnlyController();
+ }
+ return fInstance;
+ }
+
+ static private void lock(IStructuredDocument doc, int offset, int length, boolean canInsertBefore, boolean canInsertAfter) {
+ if (doc == null) {
+ return;
+ }
+ doc.makeReadOnly(offset, length);
+ }
+
+ static private void lock(IStructuredDocumentRegion node, boolean canInsertBefore, boolean canInsertAfter) {
+ if (node == null) {
+ return;
+ }
+ IStructuredDocument doc = node.getParentDocument();
+ if (doc == null) {
+ return;
+ }
+ doc.makeReadOnly(node.getStart(), node.getLength());
+ }
+
+ static private void unlock(IStructuredDocumentRegion node) {
+ if (node == null) {
+ return;
+ }
+ IStructuredDocument doc = node.getParentDocument();
+ if (doc == null) {
+ return;
+ }
+ doc.clearReadOnly(node.getStart(), node.getLength());
+ }
+
+ private ReadOnlyController() {
+ super();
+ }
+
+ private Span getDataSpan(XMLNode node) {
+ switch (node.getNodeType()) {
+ case Node.ELEMENT_NODE :
+ return getDataSpanForElement((XMLElement) node);
+ case Node.TEXT_NODE :
+ return getDataSpanForText((XMLText) node);
+ default :
+ return new Span(0, -1);
+ }
+ }
+
+ private Span getDataSpanForElement(XMLElement node) {
+ IStructuredDocumentRegion docRegion = node.getStartStructuredDocumentRegion();
+ if (docRegion == null) {
+ return new Span(0, -1);
+ }
+
+ ITextRegionList regions = docRegion.getRegions();
+ if (regions == null) {
+ return new Span(0, -1);
+ }
+
+ String startType;
+ String endType;
+ if (node.isCommentTag()) {
+ startType = XMLRegionContext.XML_COMMENT_OPEN;
+ endType = XMLRegionContext.XML_COMMENT_CLOSE;
+ } else {
+ startType = XMLRegionContext.XML_TAG_NAME;
+ endType = XMLRegionContext.XML_TAG_CLOSE;
+ }
+
+ int startOffset = -1;
+ int endOffset = -1;
+ ITextRegion prevRegion = null;
+ ITextRegion region;
+ for (int i = 0; i < regions.size(); i++) {
+ region = regions.get(i);
+ String type = region.getType();
+ if (type == startType) {
+ startOffset = region.getEnd();
+ } else if (type == endType && prevRegion != null) {
+ endOffset = prevRegion.getTextEnd();
+ }
+ prevRegion = region;
+ }
+
+ if (0 <= startOffset && 0 <= endOffset) {
+ return new Span(startOffset, endOffset - startOffset);
+ } else {
+ return new Span(0, -1);
+ }
+ }
+
+ private Span getDataSpanForText(XMLText node) {
+ IStructuredDocumentRegion docRegion = ((NodeImpl) node).getStructuredDocumentRegion();
+ if (docRegion == null) {
+ return new Span(0, -1);
+ }
+ return new Span(0, docRegion.getLength());
+ }
+
+ /**
+ * This method is used from parent's setChildEditable()
+ *
+ * case 1:<parent><node attr="value"/> <node2></parent>
+ * x####################x case 2:<parent><node attr="value"> <child>
+ * </child> </node> </parent> x###################? ?#######x (? :
+ * editable if node.isEditable() == true)
+ */
+ void lockBoth(XMLNode node) {
+ if (node == null) {
+ return;
+ }
+
+ IStructuredDocumentRegion flatNode;
+ boolean canInsert = false;
+
+ // end node (element)
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ flatNode = node.getEndStructuredDocumentRegion();
+ if (flatNode != null) {
+ canInsert = node.isChildEditable();
+ lock(flatNode, canInsert, false);
+ }
+ }
+ // start node
+ flatNode = node.getStartStructuredDocumentRegion();
+ if (flatNode != null) {
+ lock(flatNode, false, canInsert);
+ }
+ }
+
+ void lockData(XMLNode node) {
+ if (node == null) {
+ return;
+ }
+
+ Span span = getDataSpan(node);
+ if (0 <= span.length) {
+ lock(node.getModel().getStructuredDocument(), node.getStartOffset() + span.offset, span.length, false, false);
+ }
+ }
+
+ /**
+ * lock itself and all descendants
+ */
+ void lockDeep(XMLNode node) {
+ if (node == null) {
+ return;
+ }
+
+ int offset = node.getStartOffset();
+ int length = node.getEndOffset() - offset;
+
+ boolean canInsert = true;
+ XMLNode parent = (XMLNode) node.getParentNode();
+ if (parent != null && !parent.isChildEditable()) {
+ canInsert = false;
+ }
+ lock(node.getStructuredDocument(), offset, length, canInsert, canInsert);
+ }
+
+ /**
+ * This method is used from parent's setChildEditable()
+ *
+ * case 1:<parent><node attr="value"/> <node2></parent> x######x x##x
+ * case 2:<parent><node attr="value"> <child></child> </node> </parent>
+ * x######x x#? ?#######x (? : editable if node.isEditable() == true)
+ */
+ void lockNode(XMLNode node) {
+ if (node == null) {
+ return;
+ }
+ if (!node.isDataEditable()) {
+ lockBoth(node);
+ return;
+ }
+
+ IStructuredDocumentRegion flatNode;
+ boolean canInsert = false;
+
+ // end node (element)
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ flatNode = node.getEndStructuredDocumentRegion();
+ if (flatNode != null) {
+ canInsert = node.isChildEditable();
+ lock(flatNode, canInsert, false);
+ }
+ }
+ // start node
+ flatNode = node.getStartStructuredDocumentRegion();
+ if (flatNode != null) {
+ Span span = getDataSpan(node);
+ if (0 <= span.length) {
+ IStructuredDocument structuredDocument = flatNode.getParentDocument();
+ int offset, length;
+ offset = flatNode.getStart();
+ length = span.offset;
+ lock(structuredDocument, offset, length, false, false);
+ offset = offset + span.offset + span.length;
+ length = flatNode.getEnd() - offset;
+ lock(structuredDocument, offset, length, canInsert, false);
+ } else {
+ lock(flatNode, false, canInsert);
+ }
+ }
+ }
+
+ private void unlock(IStructuredDocument doc, int offset, int length) {
+ if (doc == null) {
+ return;
+ }
+ doc.clearReadOnly(offset, length);
+ }
+
+ void unlockBoth(XMLNode node) {
+ if (node == null) {
+ return;
+ }
+
+ IStructuredDocumentRegion flatNode;
+ // start node
+ flatNode = node.getStartStructuredDocumentRegion();
+ if (flatNode != null) {
+ unlock(flatNode);
+ }
+ // end node
+ flatNode = node.getEndStructuredDocumentRegion();
+ if (flatNode != null) {
+ unlock(flatNode);
+ }
+ }
+
+ void unlockData(XMLNode node) {
+ if (node == null) {
+ return;
+ }
+
+ Span span = getDataSpan(node);
+ if (0 <= span.length) {
+ unlock(node.getModel().getStructuredDocument(), span.offset, span.length);
+ }
+ }
+
+ void unlockDeep(XMLNode node) {
+ if (node == null) {
+ return;
+ }
+
+ int offset = node.getStartOffset();
+ int length = node.getEndOffset() - offset;
+
+ unlock(node.getStructuredDocument(), offset, length);
+ }
+
+ void unlockNode(XMLNode node) {
+ if (node == null) {
+ return;
+ }
+
+ IStructuredDocumentRegion flatNode;
+ // end node
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ flatNode = node.getEndStructuredDocumentRegion();
+ if (flatNode != null) {
+ unlock(flatNode);
+ }
+ }
+
+ // start node
+ flatNode = node.getStartStructuredDocumentRegion();
+ if (flatNode != null) {
+ if (node.isDataEditable()) {
+ unlock(flatNode);
+ } else {
+ Span span = getDataSpan(node);
+ if (span.length <= 0) {
+ unlock(flatNode);
+ } else {
+ IStructuredDocument structuredDocument = flatNode.getParentDocument();
+ int offset, length;
+ offset = flatNode.getStart();
+ length = span.offset - offset;
+ unlock(structuredDocument, offset, length);
+ offset = span.offset + span.length;
+ length = flatNode.getEnd() - span.offset;
+ unlock(structuredDocument, offset, length);
+ }
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/SourceValidator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/SourceValidator.java
new file mode 100644
index 0000000000..3b3d941c6c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/SourceValidator.java
@@ -0,0 +1,351 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.internal.nls.ResourceHandler1;
+import org.eclipse.wst.xml.core.document.InvalidCharacterException;
+import org.eclipse.wst.xml.core.document.JSPTag;
+import org.eclipse.wst.xml.core.document.XMLCharEntity;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+
+/**
+ */
+public class SourceValidator {
+
+ private NodeImpl node = null;
+
+ /**
+ */
+ public SourceValidator(Node node) {
+ super();
+
+ if (node != null) {
+ this.node = (NodeImpl) node;
+ }
+ }
+
+ /**
+ */
+ public String convertSource(String source) {
+ if (source == null)
+ return null;
+ if (this.node == null)
+ return null; // error
+
+ // setup conversion conditions
+ boolean acceptTag = false;
+ boolean acceptClose = false;
+ boolean acceptQuote = false;
+ boolean acceptAmpersand = false;
+ boolean acceptEntityRef = true;
+ boolean acceptJSPEnd = true;
+ String endTagName = null;
+ if (this.node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ XMLDocument document = (XMLDocument) this.node.getOwnerDocument();
+ if (document != null && document.isJSPType())
+ acceptTag = true;
+ if (acceptTag) {
+ Attr attr = (Attr) this.node;
+ ElementImpl element = (ElementImpl) attr.getOwnerElement();
+ if (element != null && element.isJSPTag())
+ acceptTag = false;
+ }
+ // if the source does not include single quote,
+ // double quote is valid
+ acceptQuote = (source.indexOf('\'') < 0);
+ } else if (this.node.getNodeType() == Node.TEXT_NODE) {
+ TextImpl text = (TextImpl) this.node;
+ if (text.isJSPContent()) {
+ int index = source.indexOf(JSPTag.TAG_CLOSE);
+ if (index < 0)
+ return source;
+ acceptTag = true;
+ acceptClose = true;
+ acceptQuote = true;
+ acceptAmpersand = true;
+ acceptJSPEnd = false;
+ } else if (text.isCDATAContent()) {
+ endTagName = text.getParentNode().getNodeName();
+ if (endTagName == null)
+ return null; // error
+ acceptTag = true;
+ acceptClose = true;
+ acceptQuote = true;
+ acceptAmpersand = true;
+ }
+ } else {
+ XMLDocument document = null;
+ if (this.node.getNodeType() == Node.DOCUMENT_NODE) {
+ document = (XMLDocument) this.node;
+ } else {
+ document = (XMLDocument) this.node.getOwnerDocument();
+ }
+ if (document != null && document.isJSPType())
+ acceptTag = true;
+ }
+
+ StringBuffer buffer = null;
+ int copiedLength = 0;
+ int length = source.length();
+ for (int i = 0; i < length; i++) {
+ String ref = null;
+ char c = source.charAt(i);
+ switch (c) {
+ case '<' :
+ if (acceptTag) {
+ if (endTagName != null) {
+ if (!matchEndTag(source, i + 1, endTagName))
+ continue;
+ } else {
+ int skip = skipTag(source, i + 1);
+ if (skip >= 0) {
+ i += skip;
+ continue;
+ }
+ }
+ // invalid JSP tag
+ }
+ ref = XMLCharEntity.LT_REF;
+ break;
+ case '>' :
+ if (acceptClose)
+ continue;
+ ref = XMLCharEntity.GT_REF;
+ break;
+ case '&' :
+ if (acceptAmpersand)
+ continue;
+ if (acceptEntityRef) {
+ int skip = skipEntityRef(source, i + 1);
+ if (skip >= 0) {
+ i += skip;
+ continue;
+ }
+ }
+ ref = XMLCharEntity.AMP_REF;
+ break;
+ case '"' :
+ if (acceptQuote)
+ continue;
+ ref = XMLCharEntity.QUOT_REF;
+ break;
+ case '%' :
+ if (acceptJSPEnd)
+ continue;
+ if (source.charAt(i + 1) != '>')
+ continue;
+ i++;
+ ref = XMLCharEntity.GT_REF;
+ break;
+ default :
+ continue;
+ }
+
+ if (ref != null) {
+ if (buffer == null) {
+ buffer = new StringBuffer(length + 8);
+ }
+ if (i > copiedLength) {
+ buffer.append(source.substring(copiedLength, i));
+ }
+ buffer.append(ref);
+ copiedLength = i + 1; // skip this character
+ }
+ }
+
+ if (buffer != null) {
+ if (copiedLength < length) {
+ buffer.append(source.substring(copiedLength, length));
+ }
+ return buffer.toString();
+ }
+ return source;
+ }
+
+ /**
+ */
+ private final boolean matchEndTag(String source, int offset, String endTagName) {
+ if (source == null || endTagName == null)
+ return false;
+ int length = source.length();
+ if (offset < 0 || offset >= length)
+ return false;
+ if (source.charAt(offset) != '/')
+ return false;
+ offset++;
+ int end = offset + endTagName.length();
+ if (end > length)
+ return false;
+ return endTagName.equalsIgnoreCase(source.substring(offset, end));
+ }
+
+ /**
+ */
+ private final int skipEntityRef(String source, int offset) {
+ if (source == null)
+ return -1;
+ if (offset < 0 || offset >= source.length())
+ return -1;
+ DocumentImpl document = (DocumentImpl) this.node.getOwnerDocument();
+ if (document == null)
+ return -1; // error
+
+ int end = source.indexOf(';', offset);
+ if (end < 0 || end == offset)
+ return -1;
+ String name = source.substring(offset, end);
+ if (name == null || document.getCharValue(name) == null)
+ return -1;
+ return (end + 1 - offset);
+ }
+
+ /**
+ */
+ private final int skipTag(String source, int offset) {
+ if (source == null)
+ return -1;
+ if (offset < 0 || offset >= source.length())
+ return -1;
+
+ int end = offset;
+ if (source.charAt(offset) == '%') {
+ // JSP tag
+ int found = source.indexOf(JSPTag.TAG_CLOSE, offset + 1);
+ if (found < 0)
+ return -1; // invalid JSP tag
+ end = found + 2;
+ } else {
+ // normal tag
+ int found = source.indexOf('>', offset);
+ if (found < 0)
+ return -1; // invalid tag
+ end = found + 1;
+ }
+ return (end - offset);
+ }
+
+ /**
+ */
+ public boolean validateSource(String source) throws InvalidCharacterException {
+ if (source == null)
+ return true;
+ if (this.node == null)
+ return false; // error
+ String message = null;
+
+ // setup validation conditions
+ boolean acceptTag = false;
+ boolean acceptClose = false;
+ boolean acceptQuote = true;
+ boolean acceptEntityRef = true;
+ String endTagName = null;
+ if (this.node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ XMLDocument document = (XMLDocument) this.node.getOwnerDocument();
+ if (document != null && document.isJSPType())
+ acceptTag = true;
+ if (acceptTag) {
+ Attr attr = (Attr) this.node;
+ ElementImpl element = (ElementImpl) attr.getOwnerElement();
+ if (element != null && element.isJSPTag())
+ acceptTag = false;
+ }
+ // if the source does not include single quote,
+ // double quote is valid
+ acceptQuote = (source.indexOf('\'') < 0);
+ } else if (this.node.getNodeType() == Node.TEXT_NODE) {
+ TextImpl text = (TextImpl) this.node;
+ if (text.isJSPContent()) {
+ int index = source.indexOf(JSPTag.TAG_CLOSE);
+ if (index < 0)
+ return true;
+ message = ResourceHandler1.getString("Invalid_character_('>')_fo_ERROR_"); //$NON-NLS-1$ = "Invalid character ('>') found"
+ throw new InvalidCharacterException(message, '>', index + 1);
+ } else if (text.isCDATAContent()) {
+ endTagName = text.getParentNode().getNodeName();
+ if (endTagName == null)
+ return false; // error
+ acceptTag = true;
+ acceptClose = true;
+ }
+ } else {
+ XMLDocument document = null;
+ if (this.node.getNodeType() == Node.DOCUMENT_NODE) {
+ document = (XMLDocument) this.node;
+ } else {
+ document = (XMLDocument) this.node.getOwnerDocument();
+ }
+ if (document != null && document.isJSPType())
+ acceptTag = true;
+ }
+
+ char c = 0;
+ int length = source.length();
+ for (int i = 0; i < length; i++) {
+ c = source.charAt(i);
+ switch (c) {
+ case '<' :
+ if (acceptTag) {
+ if (endTagName != null) {
+ if (!matchEndTag(source, i + 1, endTagName))
+ continue;
+ } else {
+ int skip = skipTag(source, i + 1);
+ if (skip >= 0) {
+ i += skip;
+ continue;
+ }
+ }
+ // invalid tag
+ }
+ message = ResourceHandler1.getString("Invalid_character_('<')_fo_ERROR_"); //$NON-NLS-1$ = "Invalid character ('<') found"
+ break;
+ case '>' :
+ if (acceptClose)
+ continue;
+ message = ResourceHandler1.getString("Invalid_character_('>')_fo_ERROR_"); //$NON-NLS-1$ = "Invalid character ('>') found"
+ break;
+ case '&' :
+ if (acceptEntityRef) {
+ if (endTagName != null)
+ continue;
+ int skip = skipEntityRef(source, i + 1);
+ if (skip >= 0) {
+ i += skip;
+ continue;
+ }
+ // invalid entity reference
+ }
+ message = ResourceHandler1.getString("Invalid_character_('&')_fo_ERROR_"); //$NON-NLS-1$ = "Invalid character ('&') found"
+ break;
+ case '"' :
+ if (acceptQuote)
+ continue;
+ message = ResourceHandler1.getString("Invalid_character_('__')_f_EXC_"); //$NON-NLS-1$ = "Invalid character ('\"') found"
+ break;
+ default :
+ continue;
+ }
+
+ if (message != null) {
+ throw new InvalidCharacterException(message, c, i);
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionChecker.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionChecker.java
new file mode 100644
index 0000000000..47a50fd2c8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionChecker.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.w3c.dom.Node;
+
+
+/**
+ * This class is only for debug purpose.
+ */
+public class StructuredDocumentRegionChecker {
+ String EOL = System.getProperty("line.separator"); //$NON-NLS-1$
+
+ private int offset = 0;
+ Writer testWriter = null;
+
+ /**
+ */
+ public StructuredDocumentRegionChecker() {
+ super();
+ }
+
+ public StructuredDocumentRegionChecker(Writer writer) {
+ super();
+ testWriter = writer;
+ }
+
+ /**
+ */
+ private void checkChildNodes(Node node) {
+ for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ checkNode(child);
+ }
+ }
+
+ /**
+ */
+ public void checkModel(XMLModel model) {
+ checkChildNodes(model.getDocument());
+ }
+
+ /**
+ */
+ private void checkNode(Node node) {
+ checkStructuredDocumentRegion(((NodeImpl) node).getStructuredDocumentRegion());
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ checkChildNodes(node);
+ checkStructuredDocumentRegion(((ElementImpl) node).getEndStructuredDocumentRegion());
+ }
+ }
+
+ /**
+ */
+ private void checkStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return;
+
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int n = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < n; i++) {
+ IStructuredDocumentRegion c = container.getStructuredDocumentRegion(i);
+ if (c == null) {
+ reportError("null"); //$NON-NLS-1$
+ continue;
+ }
+ checkStructuredDocumentRegion(c);
+ }
+ return;
+ }
+
+ int start = flatNode.getStart();
+ if (start < this.offset)
+ reportError("overwrap"); //$NON-NLS-1$
+ if (start > this.offset)
+ reportError("gap"); //$NON-NLS-1$
+ int end = flatNode.getEnd();
+ this.offset = end;
+
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+ IStructuredDocumentRegion p = proxy.getStructuredDocumentRegion();
+ if (p == null) {
+ reportError("null"); //$NON-NLS-1$
+ return;
+ }
+ int s = p.getStart();
+ int e = p.getEnd();
+ if (s > start || e < end)
+ reportError("out"); //$NON-NLS-1$
+ if (s == start && e == end)
+ reportWarning("vain"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ */
+ private void reportError(String message) {
+ String msg = "StructuredDocumentRegionChecker : error : " + message; //$NON-NLS-1$
+ if (testWriter != null) {
+ try {
+ testWriter.write(msg + EOL);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ System.out.println(msg);
+ }
+ throw new StructuredDocumentRegionManagementException();
+ }
+
+ /**
+ */
+ private void reportWarning(String message) {
+ String msg = "StructuredDocumentRegionChecker : warning : " + message; //$NON-NLS-1$
+ if (testWriter != null) {
+ try {
+ testWriter.write(msg + EOL);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ System.out.println(msg);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionContainer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionContainer.java
new file mode 100644
index 0000000000..166d8c67b1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionContainer.java
@@ -0,0 +1,605 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Vector;
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+
+
+class StructuredDocumentRegionContainer implements IStructuredDocumentRegion {
+
+ private Vector flatNodes = new Vector(2);
+
+ /**
+ */
+ StructuredDocumentRegionContainer() {
+ super();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#addRegion(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public void addRegion(ITextRegion aRegion) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjust(int)
+ */
+ public void adjust(int i) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustLengthWith(int)
+ */
+ public void adjustLengthWith(int i) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustStart(int)
+ */
+ public void adjustStart(int i) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /**
+ */
+ void appendStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return;
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ if (container.getStructuredDocumentRegionCount() > 0) {
+ this.flatNodes.addAll(container.flatNodes);
+ }
+ } else {
+ this.flatNodes.addElement(flatNode);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#containsOffset(int)
+ */
+ public boolean containsOffset(int i) {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#containsOffset(com.ibm.sed.structured.text.ITextRegion,
+ * int)
+ */
+ public boolean containsOffset(ITextRegion region, int i) {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#equatePositions(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public void equatePositions(ITextRegion region) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getDeepestRegionAtCharacterOffset(int)
+ */
+ public ITextRegion getDeepestRegionAtCharacterOffset(int offset) {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ public int getEnd() {
+ IStructuredDocumentRegion last = getLastStructuredDocumentRegion();
+ if (last == null)
+ return 0;
+ return last.getEnd();
+ }
+
+ /**
+ */
+ public int getEndOffset() {
+ return getEnd();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getEndOffset(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public int getEndOffset(ITextRegion containedRegion) {
+ // XXX Auto-generated method stub
+ return 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getFirstRegion()
+ */
+ public ITextRegion getFirstRegion() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+ if (this.flatNodes.isEmpty())
+ return null;
+ return (IStructuredDocumentRegion) this.flatNodes.elementAt(0);
+ }
+
+ /**
+ */
+ public String getFullText() {
+ return getText();
+ }
+
+ /**
+ */
+ public String getFullText(ITextRegion aRegion) {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public String getFullText(String context) {
+ // not supported
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getLastRegion()
+ */
+ public ITextRegion getLastRegion() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+ int size = this.flatNodes.size();
+ if (size == 0)
+ return null;
+ return (IStructuredDocumentRegion) this.flatNodes.elementAt(size - 1);
+ }
+
+ /**
+ */
+ public int getLength() {
+ return (getEnd() - getStart());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#getNext()
+ */
+ public IStructuredDocumentRegion getNext() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ public int getNumberOfRegions() {
+ // not supported
+ return 0;
+ }
+
+ /**
+ */
+ public ITextRegionContainer getParent() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#getParentDocument()
+ */
+ public IStructuredDocument getParentDocument() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#getPrevious()
+ */
+ public IStructuredDocumentRegion getPrevious() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ public ITextRegion getRegionAtCharacterOffset(int offset) {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public ITextRegionList getRegions() {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public int getStart() {
+ IStructuredDocumentRegion first = getFirstStructuredDocumentRegion();
+ if (first == null)
+ return 0;
+ return first.getStart();
+ }
+
+ /**
+ */
+ public int getStartOffset() {
+ return getStart();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getStartOffset(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public int getStartOffset(ITextRegion containedRegion) {
+ // XXX Auto-generated method stub
+ return 0;
+ }
+
+ /**
+ */
+ public IStructuredDocument getStructuredDocument() {
+ IStructuredDocumentRegion first = getFirstStructuredDocumentRegion();
+ if (first == null)
+ return null;
+ return first.getParentDocument();
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion getStructuredDocumentRegion(int index) {
+ if (index < 0 || index >= this.flatNodes.size())
+ return null;
+ return (IStructuredDocumentRegion) this.flatNodes.elementAt(index);
+ }
+
+ /**
+ */
+ int getStructuredDocumentRegionCount() {
+ return this.flatNodes.size();
+ }
+
+ /**
+ */
+ public String getText() {
+ int size = this.flatNodes.size();
+ if (size == 0)
+ return new String();
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < size; i++) {
+ IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) this.flatNodes.elementAt(i);
+ if (flatNode == null)
+ continue;
+ buffer.append(flatNode.getText());
+ }
+ return buffer.toString();
+ }
+
+ /**
+ */
+ public String getText(ITextRegion aRegion) {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public String getText(String context) {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public int getTextEnd() {
+ return getEnd();
+ }
+
+ /**
+ */
+ public int getTextEndOffset() {
+ return getTextEnd();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getTextEndOffset(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public int getTextEndOffset(ITextRegion containedRegion) {
+ // XXX Auto-generated method stub
+ return 0;
+ }
+
+ /**
+ * The text length is equal to length if there is no white space at the
+ * end of a region. Otherwise it is smaller than length.
+ */
+ public int getTextLength() {
+ return (getTextEnd() - getStart());
+ }
+
+ /**
+ */
+ public String getType() {
+ return "StructuredDocumentRegionContainer";//$NON-NLS-1$
+ }
+
+ /**
+ */
+ void insertStructuredDocumentRegion(IStructuredDocumentRegion flatNode, int index) {
+ if (flatNode == null)
+ return;
+ if (index < 0)
+ return;
+ int size = this.flatNodes.size();
+ if (index > size)
+ return;
+ if (index == size) {
+ appendStructuredDocumentRegion(flatNode);
+ return;
+ }
+ this.flatNodes.insertElementAt(flatNode, index);
+ }
+
+ public boolean isDeleted() {
+ // I'll assume never really needed here
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#isEnded()
+ */
+ public boolean isEnded() {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion removeStructuredDocumentRegion(int index) {
+ if (index < 0 || index >= this.flatNodes.size())
+ return null;
+ IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) this.flatNodes.elementAt(index);
+ this.flatNodes.removeElementAt(index);
+ return flatNode;
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion removeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+ if (oldStructuredDocumentRegion == null)
+ return null;
+ int size = this.flatNodes.size();
+ for (int i = 0; i < size; i++) {
+ IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) this.flatNodes.elementAt(i);
+ if (flatNode == oldStructuredDocumentRegion) {
+ this.flatNodes.removeElementAt(i);
+ return flatNode;
+ }
+ }
+ return null; // not found
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion replaceStructuredDocumentRegion(IStructuredDocumentRegion flatNode, int index) {
+ if (flatNode == null)
+ return removeStructuredDocumentRegion(index);
+ if (index < 0 || index >= this.flatNodes.size())
+ return null;
+ IStructuredDocumentRegion oldStructuredDocumentRegion = (IStructuredDocumentRegion) this.flatNodes.elementAt(index);
+ this.flatNodes.setElementAt(flatNode, index);
+ return oldStructuredDocumentRegion;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#sameAs(com.ibm.sed.structured.text.IStructuredDocumentRegion,
+ * int)
+ */
+ public boolean sameAs(IStructuredDocumentRegion region, int shift) {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ /**
+ */
+ public boolean sameAs(ITextRegion region, int shift) {
+ // not support
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#sameAs(com.ibm.sed.structured.text.ITextRegion,
+ * com.ibm.sed.structured.text.IStructuredDocumentRegion,
+ * com.ibm.sed.structured.text.ITextRegion, int)
+ */
+ public boolean sameAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ public void setDeleted(boolean deleted) {
+ // I'll assume never really needed here
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setEnded(boolean)
+ */
+ public void setEnded(boolean hasEnd) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setLength(int)
+ */
+ public void setLength(int newLength) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setNext(com.ibm.sed.structured.text.IStructuredDocumentRegion)
+ */
+ public void setNext(IStructuredDocumentRegion newNext) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setParentDocument(com.ibm.sed.structured.text.IStructuredDocument)
+ */
+ public void setParentDocument(IStructuredDocument document) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setPrevious(com.ibm.sed.structured.text.IStructuredDocumentRegion)
+ */
+ public void setPrevious(IStructuredDocumentRegion newPrevious) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /**
+ */
+ public void setRegions(ITextRegionList embeddedRegions) {
+ // not supported
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setStart(int)
+ */
+ public void setStart(int newStart) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /**
+ * toString method
+ *
+ * @return java.lang.String
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('{');
+ int count = getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ if (i != 0)
+ buffer.append(',');
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion(i);
+ if (flatNode == null)
+ buffer.append("null");//$NON-NLS-1$
+ else
+ buffer.append(flatNode.toString());
+ }
+ buffer.append('}');
+ return buffer.toString();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#updateModel(java.lang.Object,
+ * com.ibm.sed.structured.text.IStructuredDocumentRegion,
+ * java.lang.String, int, int)
+ */
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion flatnode, String changes, int start, int end) {
+ // XXX Auto-generated method stub
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionManagementException.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionManagementException.java
new file mode 100644
index 0000000000..0057dd537f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionManagementException.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+
+
+
+/**
+ */
+public class StructuredDocumentRegionManagementException extends SourceEditingRuntimeException {
+
+ /**
+ * StructuredDocumentRegionManagementException constructor
+ */
+ public StructuredDocumentRegionManagementException() {
+ super("IStructuredDocumentRegion management failed.");//$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionProxy.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionProxy.java
new file mode 100644
index 0000000000..1503845032
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionProxy.java
@@ -0,0 +1,548 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+
+
+class StructuredDocumentRegionProxy implements IStructuredDocumentRegion {
+ private IStructuredDocumentRegion flatNode = null;
+ private int length = 0;
+
+ private int offset = 0;
+
+ /**
+ */
+ StructuredDocumentRegionProxy() {
+ super();
+ }
+
+ /**
+ */
+ StructuredDocumentRegionProxy(int offset, int length) {
+ super();
+
+ this.offset = offset;
+ this.length = length;
+ }
+
+ /**
+ */
+ StructuredDocumentRegionProxy(int offset, int length, IStructuredDocumentRegion flatNode) {
+ super();
+
+ this.offset = offset;
+ this.length = length;
+ this.flatNode = flatNode;
+ if (this.flatNode != null)
+ this.offset -= this.flatNode.getStart();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#addRegion(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public void addRegion(ITextRegion aRegion) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjust(int)
+ */
+ public void adjust(int i) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustLengthWith(int)
+ */
+ public void adjustLengthWith(int i) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustStart(int)
+ */
+ public void adjustStart(int i) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#containsOffset(int)
+ */
+ public boolean containsOffset(int i) {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#containsOffset(com.ibm.sed.structured.text.ITextRegion,
+ * int)
+ */
+ public boolean containsOffset(ITextRegion region, int i) {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#equatePositions(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public void equatePositions(ITextRegion region) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getDeepestRegionAtCharacterOffset(int)
+ */
+ public ITextRegion getDeepestRegionAtCharacterOffset(int offset) {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ public int getEnd() {
+ int flatNodeOffset = 0;
+ if (this.flatNode != null)
+ flatNodeOffset = this.flatNode.getStart();
+ return flatNodeOffset + this.offset + this.length;
+ }
+
+ /**
+ */
+ public int getEndOffset() {
+ return getEnd();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getEndOffset(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public int getEndOffset(ITextRegion containedRegion) {
+ // XXX Auto-generated method stub
+ return 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getFirstRegion()
+ */
+ public ITextRegion getFirstRegion() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ public String getFullText() {
+ return getText();
+ }
+
+ /**
+ */
+ public String getFullText(ITextRegion aRegion) {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public String getFullText(String context) {
+ // not supported
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getLastRegion()
+ */
+ public ITextRegion getLastRegion() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ public int getLength() {
+ return this.length;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#getNext()
+ */
+ public IStructuredDocumentRegion getNext() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ public int getNumberOfRegions() {
+ // not supported
+ return 0;
+ }
+
+ /**
+ */
+ int getOffset() {
+ int flatNodeOffset = 0;
+ if (this.flatNode != null)
+ flatNodeOffset = this.flatNode.getStart();
+ return flatNodeOffset + this.offset;
+ }
+
+ /**
+ */
+ public ITextRegionContainer getParent() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#getParentDocument()
+ */
+ public IStructuredDocument getParentDocument() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#getPrevious()
+ */
+ public IStructuredDocumentRegion getPrevious() {
+ // XXX Auto-generated method stub
+ return null;
+ }
+
+ /**
+ */
+ public ITextRegion getRegionAtCharacterOffset(int offset) {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public ITextRegionList getRegions() {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public int getStart() {
+ int flatNodeOffset = 0;
+ if (this.flatNode != null)
+ flatNodeOffset = this.flatNode.getStart();
+ return flatNodeOffset + this.offset;
+ }
+
+ /**
+ */
+ public int getStartOffset() {
+ return getStart();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getStartOffset(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public int getStartOffset(ITextRegion containedRegion) {
+ // XXX Auto-generated method stub
+ return 0;
+ }
+
+ /**
+ */
+ public IStructuredDocument getStructuredDocument() {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion getStructuredDocumentRegion() {
+ return this.flatNode;
+ }
+
+ /**
+ */
+ public String getText() {
+ if (this.flatNode == null)
+ return new String();
+ String text = this.flatNode.getText();
+ if (text == null)
+ return new String();
+ int end = this.offset + this.length;
+ return text.substring(this.offset, end);
+ }
+
+ /**
+ */
+ public String getText(ITextRegion aRegion) {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public String getText(String context) {
+ // not supported
+ return null;
+ }
+
+ /**
+ */
+ public int getTextEnd() {
+ return getEnd();
+ }
+
+ /**
+ */
+ public int getTextEndOffset() {
+ return getTextEnd();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getTextEndOffset(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public int getTextEndOffset(ITextRegion containedRegion) {
+ // XXX Auto-generated method stub
+ return 0;
+ }
+
+ /**
+ * The text length is equal to length if there is no white space at the
+ * end of a region. Otherwise it is smaller than length.
+ */
+ public int getTextLength() {
+ return getLength();
+ }
+
+ /**
+ */
+ public String getType() {
+ return "StructuredDocumentRegionProxy";//$NON-NLS-1$
+ }
+
+ public boolean isDeleted() {
+ // I'll assume never really needed here
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#isEnded()
+ */
+ public boolean isEnded() {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#sameAs(com.ibm.sed.structured.text.IStructuredDocumentRegion,
+ * int)
+ */
+ public boolean sameAs(IStructuredDocumentRegion region, int shift) {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ /**
+ */
+ public boolean sameAs(ITextRegion region, int shift) {
+ // not supported
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#sameAs(com.ibm.sed.structured.text.ITextRegion,
+ * com.ibm.sed.structured.text.IStructuredDocumentRegion,
+ * com.ibm.sed.structured.text.ITextRegion, int)
+ */
+ public boolean sameAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
+ // XXX Auto-generated method stub
+ return false;
+ }
+
+ public void setDeleted(boolean deleted) {
+ // I'll assume never really needed here
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setEnded(boolean)
+ */
+ public void setEnded(boolean hasEnd) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /**
+ * had to make public, due to API transition.
+ */
+ public void setLength(int length) {
+ this.length = length;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setNext(com.ibm.sed.structured.text.IStructuredDocumentRegion)
+ */
+ public void setNext(IStructuredDocumentRegion newNext) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /**
+ */
+ void setOffset(int offset) {
+ this.offset = offset;
+ if (this.flatNode != null)
+ this.offset -= this.flatNode.getStart();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setParentDocument(com.ibm.sed.structured.text.IStructuredDocument)
+ */
+ public void setParentDocument(IStructuredDocument document) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setPrevious(com.ibm.sed.structured.text.IStructuredDocumentRegion)
+ */
+ public void setPrevious(IStructuredDocumentRegion newPrevious) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /**
+ */
+ public void setRegions(ITextRegionList embeddedRegions) {
+ // not supported
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#setStart(int)
+ */
+ public void setStart(int newStart) {
+ // XXX Auto-generated method stub
+
+ }
+
+ /**
+ */
+ void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ if (this.flatNode != null)
+ this.offset += this.flatNode.getStart();
+ this.flatNode = flatNode;
+ if (this.flatNode != null)
+ this.offset -= flatNode.getStart();
+ }
+
+ /**
+ * toString method
+ *
+ * @return java.lang.String
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('[');
+ buffer.append(getStart());
+ buffer.append(',');
+ buffer.append(getEnd());
+ buffer.append(']');
+ buffer.append('(');
+ if (this.flatNode != null)
+ buffer.append(this.flatNode.toString());
+ else
+ buffer.append("null");//$NON-NLS-1$
+ buffer.append(')');
+ return buffer.toString();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#updateModel(java.lang.Object,
+ * com.ibm.sed.structured.text.IStructuredDocumentRegion,
+ * java.lang.String, int, int)
+ */
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion flatnode, String changes, int start, int end) {
+ // XXX Auto-generated method stub
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionUtil.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionUtil.java
new file mode 100644
index 0000000000..82c848d940
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/StructuredDocumentRegionUtil.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+/**
+ * Provides convenient functions to handle IStructuredDocumentRegion and
+ * ITextRegion.
+ */
+class StructuredDocumentRegionUtil implements XMLJSPRegionContexts {
+
+ /**
+ * Extracts contents enclosed with quotes. Quotes may be double or single.
+ */
+ static String getAttrValue(IStructuredDocumentRegion flatNode, ITextRegion region) {
+ if (region == null)
+ return null;
+ if (flatNode == null)
+ return null;
+ String value = flatNode.getText(region);
+ if (value == null)
+ return null;
+ int length = value.length();
+ if (length == 0)
+ return value;
+ char firstChar = value.charAt(0);
+ if (firstChar == '"' || firstChar == '\'') {
+ if (length == 1)
+ return null;
+ if (value.charAt(length - 1) == firstChar)
+ length--;
+ return value.substring(1, length);
+ }
+ return value;
+ }
+
+ /**
+ * Extracts the name without heading '&' and tailing ';'.
+ */
+ static String getEntityRefName(IStructuredDocumentRegion flatNode, ITextRegion region) {
+ if (region == null)
+ return null;
+ String ref = flatNode.getText(region);
+ int length = ref.length();
+ if (length == 0)
+ return ref;
+ int offset = 0;
+ if (ref.charAt(0) == '&')
+ offset = 1;
+ if (ref.charAt(length - 1) == ';')
+ length--;
+ if (offset >= length)
+ return null;
+ return ref.substring(offset, length);
+ }
+
+ /**
+ * Returns the first region.
+ */
+ static ITextRegion getFirstRegion(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return null;
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null || regions.size() == 0)
+ return null;
+ return regions.get(0);
+ }
+
+ /**
+ * Returns the type of the first region.
+ */
+ static String getFirstRegionType(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return XMLRegionContext.UNDEFINED;
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null || regions.size() == 0)
+ return XMLRegionContext.UNDEFINED;
+ ITextRegion region = regions.get(0);
+ return region.getType();
+ }
+
+ /**
+ */
+ static IStructuredDocumentRegion getFirstStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return null;
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ flatNode = ((StructuredDocumentRegionContainer) flatNode).getFirstStructuredDocumentRegion();
+ }
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ flatNode = ((StructuredDocumentRegionProxy) flatNode).getStructuredDocumentRegion();
+ }
+ return flatNode;
+ }
+
+ /**
+ * Returns the last region.
+ */
+ static ITextRegion getLastRegion(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return null;
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null || regions.size() == 0)
+ return null;
+ return regions.get(regions.size() - 1);
+ }
+
+ /**
+ * Returns the type of the first region.
+ */
+ static String getLastRegionType(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return XMLRegionContext.UNDEFINED;
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null || regions.size() == 0)
+ return XMLRegionContext.UNDEFINED;
+ ITextRegion region = regions.get(regions.size() - 1);
+ return region.getType();
+ }
+
+ /**
+ */
+ static IStructuredDocumentRegion getLastStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return null;
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ flatNode = ((StructuredDocumentRegionContainer) flatNode).getLastStructuredDocumentRegion();
+ }
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ flatNode = ((StructuredDocumentRegionProxy) flatNode).getStructuredDocumentRegion();
+ }
+ return flatNode;
+ }
+
+ /**
+ */
+ static IStructuredDocumentRegion getStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return null;
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ flatNode = ((StructuredDocumentRegionProxy) flatNode).getStructuredDocumentRegion();
+ }
+ return flatNode;
+ }
+
+ StructuredDocumentRegionUtil() {
+ super();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TextImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TextImpl.java
new file mode 100644
index 0000000000..826fe54b3b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/TextImpl.java
@@ -0,0 +1,1107 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.document.InvalidCharacterException;
+import org.eclipse.wst.xml.core.document.XMLGenerator;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLText;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+/**
+ * TextImpl class
+ */
+public class TextImpl extends CharacterDataImpl implements XMLText {
+
+ /**
+ */
+ private class StringPair {
+ private String fFirst = null;
+ private String fSecond = null;
+
+ StringPair(String first, String second) {
+ this.fFirst = first;
+ this.fSecond = second;
+ }
+
+ String getFirst() {
+ return this.fFirst;
+ }
+
+ String getSecond() {
+ return this.fSecond;
+ }
+ }
+
+ private String fSource = null;
+
+ /**
+ * TextImpl constructor
+ */
+ protected TextImpl() {
+ super();
+ }
+
+ /**
+ * TextImpl constructor
+ *
+ * @param that
+ * TextImpl
+ */
+ protected TextImpl(TextImpl that) {
+ super(that);
+
+ if (that != null) {
+ this.fSource = that.getSource();
+ }
+ }
+
+ /**
+ * appendData method
+ *
+ * @param arg
+ * java.lang.String
+ */
+ public void appendData(String arg) throws DOMException {
+ if (arg == null || arg.length() == 0)
+ return;
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ String newSource = getSource(arg);
+ if (newSource == null)
+ return;
+ String source = getSource();
+ if (source != null)
+ setTextSource(source + newSource);
+ else
+ setTextSource(newSource);
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion appendStructuredDocumentRegion(IStructuredDocumentRegion newStructuredDocumentRegion) {
+ if (newStructuredDocumentRegion == null)
+ return null;
+
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null) {
+ setStructuredDocumentRegion(newStructuredDocumentRegion);
+ return newStructuredDocumentRegion;
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ container.appendStructuredDocumentRegion(newStructuredDocumentRegion);
+ } else {
+ StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer();
+ container.appendStructuredDocumentRegion(flatNode);
+ container.appendStructuredDocumentRegion(newStructuredDocumentRegion);
+ setStructuredDocumentRegion(container);
+ }
+
+ return newStructuredDocumentRegion;
+ }
+
+ /**
+ * appendText method
+ *
+ * @param text
+ * org.w3c.dom.Text
+ */
+ public void appendText(Text newText) {
+ if (newText == null)
+ return;
+
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ TextImpl text = (TextImpl) newText;
+ String newSource = text.getSource();
+ if (newSource == null && newSource.length() == 0)
+ return;
+ String source = getSource();
+ if (source != null)
+ setTextSource(source + newSource);
+ else
+ setTextSource(newSource);
+ }
+
+ /**
+ * cloneNode method
+ *
+ * @return org.w3c.dom.Node
+ * @param deep
+ * boolean
+ */
+ public Node cloneNode(boolean deep) {
+ TextImpl cloned = new TextImpl(this);
+ return cloned;
+ }
+
+ /**
+ * deleteData method
+ *
+ * @param offset
+ * int
+ * @param count
+ * int
+ */
+ public void deleteData(int offset, int count) throws DOMException {
+ if (count == 0)
+ return;
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ if (count < 0 || offset < 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ String source = getSource();
+ if (source == null || source.length() == 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ StringPair pair = substringSourceExcluded(source, offset, count);
+ if (pair == null)
+ return;
+ source = null;
+ String first = pair.getFirst();
+ if (first != null)
+ source = first;
+ String second = pair.getSecond();
+ if (second != null) {
+ if (source != null)
+ source += second;
+ else
+ source = second;
+ }
+ if (source == null)
+ source = new String(); // delete all
+ setTextSource(source);
+ }
+
+ /**
+ * getData method
+ *
+ * @return java.lang.String
+ */
+ public String getData() throws DOMException {
+ if (this.fSource != null)
+ return getData(this.fSource);
+ String data = super.getData();
+ if (data != null)
+ return data;
+ return getData(getStructuredDocumentRegion());
+ }
+
+ /**
+ */
+ private String getData(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return new String();
+
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int length = container.getLength();
+ if (length < 16)
+ length = 16; // default
+ StringBuffer buffer = new StringBuffer(length);
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ String data = getData(content);
+ if (data == null)
+ continue;
+ buffer.append(data);
+ }
+ return buffer.toString();
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ return flatNode.getText();
+ }
+
+ ITextRegion region = StructuredDocumentRegionUtil.getFirstRegion(flatNode);
+ if (region != null) {
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_ENTITY_REFERENCE || regionType == XMLRegionContext.XML_CHAR_REFERENCE) {
+ String name = StructuredDocumentRegionUtil.getEntityRefName(flatNode, region);
+ if (name != null) {
+ DocumentImpl document = (DocumentImpl) getOwnerDocument();
+ if (document != null) {
+ String value = document.getCharValue(name);
+ if (value != null)
+ return value;
+ }
+ }
+ }
+ }
+
+ return flatNode.getText();
+ }
+
+ /**
+ * Returns data for the source
+ */
+ private String getData(String source) {
+ if (source == null)
+ return null;
+ StringBuffer buffer = null;
+ int offset = 0;
+ int length = source.length();
+ int ref = source.indexOf('&');
+ while (ref >= 0) {
+ int end = source.indexOf(';', ref + 1);
+ if (end > ref + 1) {
+ String name = source.substring(ref + 1, end);
+ String value = getCharValue(name);
+ if (value != null) {
+ if (buffer == null)
+ buffer = new StringBuffer(length);
+ if (ref > offset)
+ buffer.append(source.substring(offset, ref));
+ buffer.append(value);
+ offset = end + 1;
+ ref = end;
+ }
+ }
+ ref = source.indexOf('&', ref + 1);
+ }
+ if (buffer == null)
+ return source;
+ if (length > offset)
+ buffer.append(source.substring(offset));
+ return buffer.toString();
+ }
+
+ /**
+ * getFirstStructuredDocumentRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+ return StructuredDocumentRegionUtil.getFirstStructuredDocumentRegion(getStructuredDocumentRegion());
+ }
+
+ /**
+ * getLastStructuredDocumentRegion method
+ *
+ * @return com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+ return StructuredDocumentRegionUtil.getLastStructuredDocumentRegion(getStructuredDocumentRegion());
+ }
+
+ /**
+ * getNodeName method
+ *
+ * @return java.lang.String
+ */
+ public String getNodeName() {
+ return "#text";//$NON-NLS-1$
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return short
+ */
+ public short getNodeType() {
+ return TEXT_NODE;
+ }
+
+ /**
+ */
+ public String getSource() {
+ if (this.fSource != null)
+ return this.fSource;
+ String data = super.getData();
+ if (data != null && data.length() > 0) {
+ String source = getSource(data);
+ if (source != null)
+ return source;
+ }
+ return super.getSource();
+ }
+
+ /**
+ * Returns source for the data
+ */
+ private String getSource(String data) {
+ if (data == null)
+ return null;
+ XMLModel model = getModel();
+ if (model == null)
+ return null; // error
+ XMLGenerator generator = model.getGenerator();
+ if (generator == null)
+ return null; // error
+ return generator.generateTextData(this, data);
+ }
+
+ /**
+ */
+ String getTextSource() {
+ return this.fSource;
+ }
+
+ /**
+ */
+ public String getValueSource() {
+ return getSource();
+ }
+
+ /**
+ */
+ boolean hasStructuredDocumentRegion(IStructuredDocumentRegion askedStructuredDocumentRegion) {
+ if (askedStructuredDocumentRegion == null)
+ return false;
+
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return false;
+
+ if (flatNode == askedStructuredDocumentRegion)
+ return true;
+
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+ if (proxy.getStructuredDocumentRegion() == askedStructuredDocumentRegion)
+ return true;
+ return false;
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == null)
+ continue;
+ if (content == askedStructuredDocumentRegion)
+ return true;
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ if (proxy.getStructuredDocumentRegion() == askedStructuredDocumentRegion)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ return false;
+ }
+
+ /**
+ * insertData method
+ *
+ * @param offset
+ * int
+ * @param arg
+ * java.lang.String
+ */
+ public void insertData(int offset, String arg) throws DOMException {
+ if (arg == null || arg.length() == 0)
+ return;
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ if (offset < 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ String source = getSource();
+ if (source == null || source.length() == 0) {
+ if (offset > 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ source = getSource(arg);
+ if (source != null)
+ setTextSource(source);
+ return;
+ }
+
+ StringPair pair = substringSourceExcluded(source, offset, 0);
+ if (pair == null)
+ return; // error
+ StringBuffer buffer = new StringBuffer(source.length() + arg.length());
+ String first = pair.getFirst();
+ if (first != null)
+ buffer.append(first);
+ source = getSource(arg);
+ if (source != null)
+ buffer.append(source);
+ String second = pair.getSecond();
+ if (second != null)
+ buffer.append(second);
+ setTextSource(buffer.toString());
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion insertStructuredDocumentRegion(IStructuredDocumentRegion newStructuredDocumentRegion, IStructuredDocumentRegion nextStructuredDocumentRegion) {
+ if (newStructuredDocumentRegion == null)
+ return null;
+ if (nextStructuredDocumentRegion == null)
+ return appendStructuredDocumentRegion(newStructuredDocumentRegion);
+
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return null; // error
+
+ if (flatNode == nextStructuredDocumentRegion) {
+ StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer();
+ container.appendStructuredDocumentRegion(newStructuredDocumentRegion);
+ container.appendStructuredDocumentRegion(flatNode);
+ setStructuredDocumentRegion(container);
+ return newStructuredDocumentRegion;
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == nextStructuredDocumentRegion) {
+ container.insertStructuredDocumentRegion(newStructuredDocumentRegion, i);
+ return newStructuredDocumentRegion;
+ }
+ }
+ return null; // error
+ }
+
+ return null; // error
+ }
+
+ /**
+ * insertText method
+ *
+ * @param text
+ * org.w3c.dom.Text
+ * @param offset
+ * int
+ */
+ public void insertText(Text newText, int offset) throws DOMException {
+ if (newText == null)
+ return;
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ TextImpl text = (TextImpl) newText;
+ String newSource = text.getSource();
+ if (newSource == null && newSource.length() == 0)
+ return;
+ if (offset < 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ String source = getSource();
+ if (source == null || source.length() == 0) {
+ if (offset > 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ setTextSource(newSource);
+ return;
+ }
+
+ StringPair pair = substringSourceExcluded(source, offset, 0);
+ if (pair == null)
+ return; // error
+ StringBuffer buffer = new StringBuffer(source.length() + newSource.length());
+ String first = pair.getFirst();
+ if (first != null)
+ buffer.append(first);
+ buffer.append(newSource);
+ String second = pair.getSecond();
+ if (second != null)
+ buffer.append(second);
+ setTextSource(buffer.toString());
+ }
+
+ /**
+ * isCDATAContent method
+ *
+ * @return boolean
+ */
+ public boolean isCDATAContent() {
+ Node parent = getParentNode();
+ if (parent == null || parent.getNodeType() != Node.ELEMENT_NODE)
+ return false;
+ ElementImpl element = (ElementImpl) parent;
+ return element.isCDATAContainer();
+ }
+
+ /**
+ */
+ public boolean isInvalid() {
+ return isInvalid(getStructuredDocumentRegion());
+ }
+
+ /**
+ */
+ private boolean isInvalid(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return false;
+
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (isInvalid(content))
+ return true;
+ }
+ return false;
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+ return isInvalid(proxy.getStructuredDocumentRegion());
+ }
+
+ String regionType = StructuredDocumentRegionUtil.getFirstRegionType(flatNode);
+ if (regionType != XMLRegionContext.XML_CONTENT && regionType != JSP_CONTENT && regionType != XMLRegionContext.XML_ENTITY_REFERENCE && regionType != XMLRegionContext.XML_CHAR_REFERENCE && regionType != XMLRegionContext.BLOCK_TEXT && regionType != XMLRegionContext.WHITE_SPACE) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ */
+ boolean isSharingStructuredDocumentRegion(IStructuredDocumentRegion sharedStructuredDocumentRegion) {
+ if (sharedStructuredDocumentRegion == null)
+ return false;
+
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return false;
+
+ if (flatNode == sharedStructuredDocumentRegion)
+ return false;
+
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+ if (proxy.getStructuredDocumentRegion() == sharedStructuredDocumentRegion)
+ return true;
+ return false;
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == null)
+ continue;
+ if (content == sharedStructuredDocumentRegion)
+ return false;
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ if (proxy.getStructuredDocumentRegion() == sharedStructuredDocumentRegion)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ return false;
+ }
+
+ /**
+ */
+ public boolean isWhitespace() {
+ String data = getData();
+ if (data == null)
+ return true;
+ int length = data.length();
+ for (int i = 0; i < length; i++) {
+ if (!Character.isWhitespace(data.charAt(i)))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion removeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+ if (oldStructuredDocumentRegion == null)
+ return null;
+
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return null; // error
+
+ if (flatNode == oldStructuredDocumentRegion) {
+ setStructuredDocumentRegion(null);
+ return oldStructuredDocumentRegion;
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+ if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+ // removed with proxy
+ setStructuredDocumentRegion(null);
+ return oldStructuredDocumentRegion;
+ }
+ return null; // error
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == oldStructuredDocumentRegion) {
+ container.removeStructuredDocumentRegion(i);
+ if (container.getStructuredDocumentRegionCount() == 1) {
+ // get back to single IStructuredDocumentRegion
+ setStructuredDocumentRegion(container.getStructuredDocumentRegion(0));
+ }
+ return oldStructuredDocumentRegion;
+ }
+
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+ // removed with proxy
+ container.removeStructuredDocumentRegion(i);
+ if (container.getStructuredDocumentRegionCount() == 1) {
+ // get back to single IStructuredDocumentRegion
+ setStructuredDocumentRegion(container.getStructuredDocumentRegion(0));
+ }
+ return oldStructuredDocumentRegion;
+ }
+ }
+ }
+ return null; // error
+ }
+
+ return null; // error
+ }
+
+ /**
+ * replaceData method
+ *
+ * @param offset
+ * int
+ * @param count
+ * int
+ * @param arg
+ * java.lang.String
+ */
+ public void replaceData(int offset, int count, String arg) throws DOMException {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ if (arg == null || arg.length() == 0) {
+ deleteData(offset, count);
+ return;
+ }
+ if (count == 0) {
+ insertData(offset, arg);
+ return;
+ }
+ if (offset < 0 || count < 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ String source = getSource();
+ if (source == null || source.length() == 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ StringPair pair = substringSourceExcluded(source, offset, count);
+ if (pair == null)
+ return; // error
+ StringBuffer buffer = new StringBuffer(source.length() + arg.length());
+ String first = pair.getFirst();
+ if (first != null)
+ buffer.append(first);
+ source = getSource(arg);
+ if (source != null)
+ buffer.append(source);
+ String second = pair.getSecond();
+ if (second != null)
+ buffer.append(second);
+ setTextSource(buffer.toString());
+ }
+
+ /**
+ */
+ IStructuredDocumentRegion replaceStructuredDocumentRegion(IStructuredDocumentRegion newStructuredDocumentRegion, IStructuredDocumentRegion oldStructuredDocumentRegion) {
+ if (oldStructuredDocumentRegion == null)
+ return null;
+ if (newStructuredDocumentRegion == null)
+ return removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null)
+ return null; // error
+
+ if (flatNode == oldStructuredDocumentRegion) {
+ setStructuredDocumentRegion(newStructuredDocumentRegion);
+ return oldStructuredDocumentRegion;
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+ if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+ if (newStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+ // proxy must not be nested
+ setStructuredDocumentRegion(newStructuredDocumentRegion);
+ } else {
+ proxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+ }
+ return oldStructuredDocumentRegion;
+ }
+ return null; // error
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == null)
+ continue; // error
+ if (content == oldStructuredDocumentRegion) {
+ container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+ return oldStructuredDocumentRegion;
+ }
+
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+ if (newStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+ // proxy must not be nested
+ container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+ } else {
+ proxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+ }
+ return oldStructuredDocumentRegion;
+ }
+ }
+ }
+ return null; // error
+ }
+
+ return null; // error
+ }
+
+ /**
+ */
+ void resetStructuredDocumentRegions() {
+ String source = getSource();
+ if (source != null && source.length() > 0)
+ this.fSource = source;
+ super.resetStructuredDocumentRegions();
+ }
+
+ /**
+ * getData method
+ *
+ * @return java.lang.String
+ */
+ public void setData(String data) throws DOMException {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.fSource = null;
+ super.setData(data);
+ }
+
+ /**
+ */
+ public void setSource(String source) throws InvalidCharacterException {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ SourceValidator validator = new SourceValidator(this);
+ if (validator.validateSource(source))
+ setTextSource(source);
+ }
+
+ /**
+ */
+ void setStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ super.setStructuredDocumentRegion(flatNode);
+ if (flatNode != null)
+ this.fSource = null;
+ }
+
+ /**
+ */
+ public void setTextSource(String source) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ this.fSource = source;
+
+ notifyValueChanged();
+ }
+
+ /**
+ */
+ public void setValueSource(String source) {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+
+ SourceValidator validator = new SourceValidator(this);
+ setTextSource(validator.convertSource(source));
+ }
+
+ /**
+ * splitText method
+ *
+ * @return org.w3c.dom.Text
+ * @param offset
+ * int
+ */
+ public Text splitText(int offset) throws DOMException {
+ if (!isDataEditable()) {
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, new String());
+ }
+ if (offset < 0) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ int length = getLength();
+ if (offset > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ Document document = getOwnerDocument();
+ if (document == null)
+ return null;
+
+ String source = null;
+ if (offset < length) {
+ int count = length - offset;
+ source = substringSource(offset, count);
+ deleteData(offset, count);
+ }
+ TextImpl text = (TextImpl) document.createTextNode(null);
+ if (source != null)
+ text.setTextSource(source);
+
+ Node parent = getParentNode();
+ if (parent != null)
+ parent.insertBefore(text, getNextSibling());
+
+ return text;
+ }
+
+ /**
+ */
+ Text splitText(IStructuredDocumentRegion nextStructuredDocumentRegion) {
+ if (nextStructuredDocumentRegion == null)
+ return null;
+
+ IStructuredDocumentRegion flatNode = getStructuredDocumentRegion();
+ if (flatNode == null || !(flatNode instanceof StructuredDocumentRegionContainer))
+ return null; // error
+
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int count = container.getStructuredDocumentRegionCount();
+ int index = 0;
+ for (; index < count; index++) {
+ if (container.getStructuredDocumentRegion(index) == nextStructuredDocumentRegion)
+ break;
+ }
+ if (index >= count) {
+ // this is the case nextStructuredDocumentRegion is a new
+ // IStructuredDocumentRegion
+ // search gap by offset
+ int offset = nextStructuredDocumentRegion.getStart();
+ for (index = 0; index < count; index++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(index);
+ if (content == null)
+ continue; // error
+ if (content.getStart() >= offset)
+ break;
+ }
+ if (index >= count)
+ return null; // error
+ }
+ if (index == 0)
+ return this; // nothing to do
+
+ Document document = getOwnerDocument();
+ if (document == null)
+ return null; // error
+ Node parent = getParentNode();
+ if (parent == null)
+ return null; // error
+ TextImpl nextText = (TextImpl) document.createTextNode(null);
+ if (nextText == null)
+ return null; // error
+
+ for (; index < count; count--) {
+ nextText.appendStructuredDocumentRegion(container.removeStructuredDocumentRegion(index));
+ }
+
+ // normalize IStructuredDocumentRegion
+ if (index == 1) {
+ setStructuredDocumentRegion(container.getStructuredDocumentRegion(0));
+ }
+
+ parent.insertBefore(nextText, getNextSibling());
+ return nextText;
+ }
+
+ /**
+ * Retruns data for the range
+ */
+ private String substringData(String data, int offset, int count) throws DOMException {
+ // sure offset and count are non-negative
+ if (count == 0)
+ return new String();
+ if (data == null) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ int length = data.length();
+ if (offset > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ int end = offset + count;
+ if (end > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+ return data.substring(offset, end);
+ }
+
+ /**
+ * Returns source for the range specified by: offset: data offset count:
+ * data count
+ */
+ private String substringSource(int offset, int count) throws DOMException {
+ // sure offset and count are non-negative
+ if (this.fSource != null)
+ return substringSource(this.fSource, offset, count);
+
+ String data = super.getData();
+ if (data != null && data.length() > 0) {
+ data = substringData(data, offset, count);
+ if (data == null)
+ return new String();
+ String source = getSource(data);
+ if (source != null)
+ return source;
+ }
+
+ return substringSource(getSource(), offset, count);
+ }
+
+ /**
+ * Returns source for the range specified by: offset: data offset count:
+ * data count
+ */
+ private String substringSource(String source, int offset, int count) throws DOMException {
+ // sure offset and count are non-negative
+ if (count == 0)
+ return new String();
+ if (source == null) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ int length = source.length();
+ int end = offset + count;
+
+ // find character reference
+ int ref = source.indexOf('&');
+ while (ref >= 0) {
+ if (ref >= end)
+ break;
+ int refEnd = source.indexOf(';', ref + 1);
+ if (refEnd > ref + 1) {
+ String name = source.substring(ref + 1, refEnd);
+ if (getCharValue(name) != null) {
+ // found, shift for source offsets
+ int refCount = refEnd - ref;
+ if (ref < offset)
+ offset += refCount;
+ if (ref < end)
+ end += refCount;
+ ref = refEnd;
+ }
+ }
+ ref = source.indexOf('&', ref + 1);
+ }
+
+ if (offset > length || end > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ return source.substring(offset, end);
+ }
+
+ /**
+ * Returns sources before and after the range specified by: offset: data
+ * offset count: data count
+ */
+ private StringPair substringSourceExcluded(String source, int offset, int count) throws DOMException {
+ // sure offset and count are non-negative
+ if (source == null) {
+ if (offset == 0 && count == 0)
+ return new StringPair(null, null);
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ int length = source.length();
+ int end = offset + count;
+
+ // find character reference
+ int ref = source.indexOf('&');
+ while (ref >= 0) {
+ if (ref >= end)
+ break;
+ int refEnd = source.indexOf(';', ref + 1);
+ if (refEnd > ref + 1) {
+ String name = source.substring(ref + 1, refEnd);
+ if (getCharValue(name) != null) {
+ // found, shift for source offsets
+ int refCount = refEnd - ref;
+ if (ref < offset)
+ offset += refCount;
+ if (ref < end)
+ end += refCount;
+ ref = refEnd;
+ }
+ }
+ ref = source.indexOf('&', ref + 1);
+ }
+
+ if (offset > length || end > length) {
+ throw new DOMException(DOMException.INDEX_SIZE_ERR, new String());
+ }
+
+ String first = (offset > 0 ? source.substring(0, offset) : null);
+ String second = (end < length ? source.substring(end, length) : null);
+ return new StringPair(first, second);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLGeneratorImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLGeneratorImpl.java
new file mode 100644
index 0000000000..5000a4d009
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLGeneratorImpl.java
@@ -0,0 +1,738 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMDataType;
+import org.eclipse.wst.xml.core.commentelement.impl.CommentElementRegistry;
+import org.eclipse.wst.xml.core.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.document.JSPTag;
+import org.eclipse.wst.xml.core.document.TagAdapter;
+import org.eclipse.wst.xml.core.document.XMLAttr;
+import org.eclipse.wst.xml.core.document.XMLCharEntity;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLGenerator;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+/**
+ */
+public class XMLGeneratorImpl implements XMLGenerator {
+ private static final String CDATA_CLOSE = "]]>";//$NON-NLS-1$
+ private static final String CDATA_OPEN = "<![CDATA[";//$NON-NLS-1$
+ private static final String COMMENT_CLOSE = "-->";//$NON-NLS-1$
+ private static final String COMMENT_OPEN = "<!--";//$NON-NLS-1$
+ private static final String DOCTYPE_OPEN = "<!DOCTYPE";//$NON-NLS-1$
+ private static final String EMPTY_CLOSE = " />";//$NON-NLS-1$
+ private static final String END_OPEN = "</";//$NON-NLS-1$
+
+ private static XMLGeneratorImpl instance = null;
+ private static final String PI_CLOSE = "?>";//$NON-NLS-1$
+ private static final String PI_OPEN = "<?";//$NON-NLS-1$
+ private static final String PUBLIC_ID = "PUBLIC";//$NON-NLS-1$
+ private static final String SSI_PREFIX = "ssi";//$NON-NLS-1$
+ //private static final String SSI_FEATURE = "SSI";//$NON-NLS-1$
+ private static final String SSI_TOKEN = "#";//$NON-NLS-1$
+ private static final String SYSTEM_ID = "SYSTEM";//$NON-NLS-1$
+ private static final String TAG_CLOSE = ">";//$NON-NLS-1$
+
+ /**
+ */
+ public synchronized static XMLGenerator getInstance() {
+ if (instance == null)
+ instance = new XMLGeneratorImpl();
+ return instance;
+ }
+
+ /**
+ */
+ //private boolean isCommentTag(XMLElement element) {
+ // if (element == null) return false;
+ // DocumentImpl document = (DocumentImpl)element.getOwnerDocument();
+ // if (document == null) return false;
+ // DocumentTypeAdapter adapter = document.getDocumentTypeAdapter();
+ // if (adapter == null) return false;
+ // if (!adapter.hasFeature(SSI_FEATURE)) return false;
+ // String prefix = element.getPrefix();
+ // return (prefix != null && prefix.equals(SSI_PREFIX));
+ //}
+ /**
+ * Helper to modify the tag name in sub-classes
+ */
+ private static void setTagName(Element element, String tagName) {
+ if (element == null || tagName == null)
+ return;
+ ((ElementImpl) element).setTagName(tagName);
+ }
+
+ /**
+ * XMLModelGenerator constructor
+ */
+ private XMLGeneratorImpl() {
+ super();
+ }
+
+ /**
+ */
+ public String generateAttrName(Attr attr) {
+ if (attr == null)
+ return null;
+ String attrName = attr.getName();
+ if (attrName == null)
+ return null;
+ if (attrName.startsWith(JSPTag.TAG_OPEN)) {
+ if (!attrName.endsWith(JSPTag.TAG_CLOSE)) {
+ // close JSP
+ return (attrName + JSPTag.TAG_CLOSE);
+ }
+ }
+ if (((XMLAttr) attr).isGlobalAttr() && CMNodeUtil.getAttributeDeclaration(attr) != null) {
+ switch (getAttrNameCase(attr)) {
+ case DocumentTypeAdapter.UPPER_CASE :
+ attrName = attrName.toUpperCase();
+ break;
+ case DocumentTypeAdapter.LOWER_CASE :
+ attrName = attrName.toLowerCase();
+ break;
+ default :
+ // ASIS_CASE
+ break;
+ }
+ }
+ return attrName;
+ }
+
+ /**
+ */
+ public String generateAttrValue(Attr attr) {
+ return generateAttrValue(attr, (char) 0); // no quote preference
+ }
+
+ /**
+ */
+ public String generateAttrValue(Attr attr, char quote) {
+ if (attr == null)
+ return null;
+ String name = attr.getName();
+ SourceValidator validator = new SourceValidator(attr);
+ String value = validator.convertSource(((XMLNode) attr).getValueSource());
+ if (value == null || value.length() == 0) {
+ if (name != null && name.startsWith(JSPTag.TAG_OPEN))
+ return null;
+ if (isBooleanAttr(attr)) {
+ if (((AttrImpl) attr).isXMLAttr()) {
+ // generate the name as value
+ value = attr.getName();
+ } else {
+ // not to generate '=' and value for HTML boolean
+ return null;
+ }
+ }
+ }
+ return generateAttrValue(value, quote);
+ }
+
+ /**
+ */
+ public String generateAttrValue(String value, char quote) {
+ // assume the valid is already validated not to include both quotes
+ if (quote == '"') {
+ if ((value != null) && (value.indexOf('"') >= 0))
+ quote = '\''; // force
+ } else if (quote == '\'') {
+ if ((value != null) && (value.indexOf('\'') >= 0))
+ quote = '"'; // force
+ } else { // no preference
+ if ((value != null) && (value.indexOf('"') < 0))
+ quote = '"';
+ else
+ quote = '\'';
+ }
+
+ int length = (value == null ? 0 : value.length());
+ StringBuffer buffer = new StringBuffer(length + 2);
+ buffer.append(quote);
+ if (value != null)
+ buffer.append(value);
+ buffer.append(quote);
+ return buffer.toString();
+ }
+
+ /**
+ * generateCDATASection method
+ *
+ * @return java.lang.String
+ * @param comment
+ * org.w3c.dom.CDATASection
+ */
+ public String generateCDATASection(CDATASection cdata) {
+ if (cdata == null)
+ return null;
+
+ String data = cdata.getData();
+ int length = (data != null ? data.length() : 0);
+ StringBuffer buffer = new StringBuffer(length + 16);
+ buffer.append(CDATA_OPEN);
+ if (data != null)
+ buffer.append(data);
+ buffer.append(CDATA_CLOSE);
+ return buffer.toString();
+ }
+
+ /**
+ * generateChild method
+ *
+ * @return java.lang.String
+ * @param org.w3c.dom.Node
+ */
+ public String generateChild(Node parentNode) {
+ if (parentNode == null)
+ return null;
+ if (!parentNode.hasChildNodes())
+ return null;
+
+ StringBuffer buffer = new StringBuffer();
+ for (Node child = parentNode.getFirstChild(); child != null; child = child.getNextSibling()) {
+ String childSource = generateSource(child);
+ if (childSource != null)
+ buffer.append(childSource);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ */
+ public String generateCloseTag(Node node) {
+ if (node == null)
+ return null;
+
+ switch (node.getNodeType()) {
+ case Node.ELEMENT_NODE : {
+ ElementImpl element = (ElementImpl) node;
+ if (element.isCommentTag()) {
+ if (element.isJSPTag())
+ return JSPTag.COMMENT_CLOSE;
+ return COMMENT_CLOSE;
+ }
+ if (element.isJSPTag())
+ return JSPTag.TAG_CLOSE;
+ if (element.isEmptyTag())
+ return EMPTY_CLOSE;
+ return TAG_CLOSE;
+ }
+ case Node.COMMENT_NODE : {
+ CommentImpl comment = (CommentImpl) node;
+ if (comment.isJSPTag())
+ return JSPTag.COMMENT_CLOSE;
+ return COMMENT_CLOSE;
+ }
+ case Node.DOCUMENT_TYPE_NODE :
+ return TAG_CLOSE;
+ case Node.PROCESSING_INSTRUCTION_NODE :
+ return PI_CLOSE;
+ case Node.CDATA_SECTION_NODE :
+ return CDATA_CLOSE;
+ default :
+ break;
+ }
+
+ return null;
+ }
+
+ /**
+ * generateComment method
+ *
+ * @return java.lang.String
+ * @param comment
+ * org.w3c.dom.Comment
+ */
+ public String generateComment(Comment comment) {
+ if (comment == null)
+ return null;
+
+ String data = comment.getData();
+ int length = (data != null ? data.length() : 0);
+ StringBuffer buffer = new StringBuffer(length + 8);
+ CommentImpl impl = (CommentImpl) comment;
+ if (!impl.isJSPTag())
+ buffer.append(COMMENT_OPEN);
+ else
+ buffer.append(JSPTag.COMMENT_OPEN);
+ if (data != null)
+ buffer.append(data);
+ if (!impl.isJSPTag())
+ buffer.append(COMMENT_CLOSE);
+ else
+ buffer.append(JSPTag.COMMENT_CLOSE);
+ return buffer.toString();
+ }
+
+ /**
+ * generateDoctype method
+ *
+ * @return java.lang.String
+ * @param docType
+ * org.w3c.dom.DocumentType
+ */
+ public String generateDoctype(DocumentType docType) {
+ if (docType == null)
+ return null;
+
+ String name = docType.getName();
+ int length = (name != null ? name.length() : 0);
+ StringBuffer buffer = new StringBuffer(length + 16);
+ buffer.append(DOCTYPE_OPEN);
+ buffer.append(' ');
+ if (name != null)
+ buffer.append(name);
+ DocumentTypeImpl dt = (DocumentTypeImpl) docType;
+ String publicID = dt.getPublicId();
+ String systemID = dt.getSystemId();
+ if (publicID != null) {
+ buffer.append(' ');
+ buffer.append(PUBLIC_ID);
+ buffer.append(' ');
+ buffer.append('"');
+ buffer.append(publicID);
+ buffer.append('"');
+ if (systemID != null) {
+ buffer.append(' ');
+ buffer.append('"');
+ buffer.append(systemID);
+ buffer.append('"');
+ }
+ } else {
+ if (systemID != null) {
+ buffer.append(' ');
+ buffer.append(SYSTEM_ID);
+ buffer.append(' ');
+ buffer.append('"');
+ buffer.append(systemID);
+ buffer.append('"');
+ }
+ }
+ buffer.append('>');
+ return buffer.toString();
+ }
+
+ /**
+ * generateElement method
+ *
+ * @return java.lang.String
+ * @param element
+ * Element
+ */
+ public String generateElement(Element element) {
+ if (element == null)
+ return null;
+
+ // if empty tag is preferrable, generate as empty tag
+ ElementImpl impl = (ElementImpl) element;
+ if (impl.preferEmptyTag())
+ impl.setEmptyTag(true);
+
+ StringBuffer buffer = new StringBuffer();
+ String startTag = generateStartTag(element);
+ if (startTag != null)
+ buffer.append(startTag);
+ String child = generateChild(element);
+ if (child != null)
+ buffer.append(child);
+ String endTag = generateEndTag(element);
+ if (endTag != null)
+ buffer.append(endTag);
+ return buffer.toString();
+ }
+
+ /**
+ * generateEndTag method
+ *
+ * @return java.lang.String
+ * @param element
+ * org.w3c.dom.Element
+ */
+ public String generateEndTag(Element element) {
+ if (element == null)
+ return null;
+
+ ElementImpl impl = (ElementImpl) element;
+
+ // first check if tag adapter exists
+ TagAdapter adapter = (TagAdapter) impl.getExistingAdapter(TagAdapter.class);
+ if (adapter != null) {
+ String endTag = adapter.getEndTag(impl);
+ if (endTag != null)
+ return endTag;
+ }
+
+ if (impl.isEmptyTag())
+ return null;
+ if (!impl.isContainer())
+ return null;
+ if (impl.isJSPTag())
+ return JSPTag.TAG_CLOSE;
+
+ String tagName = generateTagName(element);
+ int length = (tagName != null ? tagName.length() : 0);
+ StringBuffer buffer = new StringBuffer(length + 4);
+ buffer.append(END_OPEN);
+ if (tagName != null)
+ buffer.append(tagName);
+ buffer.append('>');
+ return buffer.toString();
+ }
+
+ /**
+ * generateEntityRef method
+ *
+ * @return java.lang.String
+ * @param entityRef
+ * org.w3c.dom.EntityReference
+ */
+ public String generateEntityRef(EntityReference entityRef) {
+ if (entityRef == null)
+ return null;
+
+ String name = entityRef.getNodeName();
+ int length = (name != null ? name.length() : 0);
+ StringBuffer buffer = new StringBuffer(length + 4);
+ buffer.append('&');
+ if (name != null)
+ buffer.append(name);
+ buffer.append(';');
+ return buffer.toString();
+ }
+
+ /**
+ * generatePI method
+ *
+ * @return java.lang.String
+ * @param pi
+ * org.w3c.dom.ProcessingInstruction
+ */
+ public String generatePI(ProcessingInstruction pi) {
+ if (pi == null)
+ return null;
+
+ String target = pi.getTarget();
+ String data = pi.getData();
+ int length = (target != null ? target.length() : 0);
+ if (data != null)
+ length += data.length();
+ StringBuffer buffer = new StringBuffer(length + 8);
+ buffer.append(PI_OPEN);
+ if (target != null)
+ buffer.append(target);
+ buffer.append(' ');
+ if (data != null)
+ buffer.append(data);
+ buffer.append(PI_CLOSE);
+ return buffer.toString();
+ }
+
+ /**
+ * generateSource method
+ *
+ * @return java.lang.String
+ * @param node
+ * org.w3c.dom.Node
+ */
+ public String generateSource(Node node) {
+ switch (node.getNodeType()) {
+ case Node.ELEMENT_NODE :
+ return generateElement((Element) node);
+ case Node.TEXT_NODE :
+ return generateText((Text) node);
+ case Node.COMMENT_NODE :
+ return generateComment((Comment) node);
+ case Node.DOCUMENT_TYPE_NODE :
+ return generateDoctype((DocumentType) node);
+ case Node.PROCESSING_INSTRUCTION_NODE :
+ return generatePI((ProcessingInstruction) node);
+ case Node.CDATA_SECTION_NODE :
+ return generateCDATASection((CDATASection) node);
+ case Node.ENTITY_REFERENCE_NODE :
+ return generateEntityRef((EntityReference) node);
+ default :
+ // DOCUMENT
+ break;
+ }
+ return generateChild(node);
+ }
+
+ /**
+ * generateStartTag method
+ *
+ * @return java.lang.String
+ * @param element
+ * Element
+ */
+ public String generateStartTag(Element element) {
+ if (element == null)
+ return null;
+
+ ElementImpl impl = (ElementImpl) element;
+
+ if (impl.isJSPTag()) {
+ // check if JSP content type and JSP Document
+ XMLDocument document = (XMLDocument) element.getOwnerDocument();
+ if (document != null && document.isJSPType()) {
+ if (document.isJSPDocument() && !impl.hasChildNodes()) {
+ impl.setJSPTag(false);
+ }
+ } else {
+ impl.setJSPTag(false);
+ }
+ }
+ if (impl.isCommentTag() && impl.getExistingAdapter(TagAdapter.class) == null) {
+ CommentElementRegistry registry = CommentElementRegistry.getInstance();
+ registry.setupCommentElement(impl);
+ }
+
+ // first check if tag adapter exists
+ TagAdapter adapter = (TagAdapter) impl.getExistingAdapter(TagAdapter.class);
+ if (adapter != null) {
+ String startTag = adapter.getStartTag(impl);
+ if (startTag != null)
+ return startTag;
+ }
+
+ StringBuffer buffer = new StringBuffer();
+
+ if (impl.isCommentTag()) {
+ if (impl.isJSPTag())
+ buffer.append(JSPTag.COMMENT_OPEN);
+ else
+ buffer.append(COMMENT_OPEN);
+ String tagName = generateTagName(element);
+ if (tagName != null)
+ buffer.append(tagName);
+ } else if (impl.isJSPTag()) {
+ buffer.append(JSPTag.TAG_OPEN);
+ String tagName = generateTagName(element);
+ if (tagName != null)
+ buffer.append(tagName);
+ if (impl.isContainer())
+ return buffer.toString(); // JSP container
+ } else {
+ buffer.append('<');
+ String tagName = generateTagName(element);
+ if (tagName != null)
+ buffer.append(tagName);
+ }
+
+ NamedNodeMap attributes = element.getAttributes();
+ int length = attributes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) attributes.item(i);
+ if (attr == null)
+ continue;
+ buffer.append(' ');
+ String attrName = generateAttrName(attr);
+ if (attrName != null)
+ buffer.append(attrName);
+ String attrValue = generateAttrValue(attr);
+ if (attrValue != null) {
+ // attr name only for HTML boolean and JSP
+ buffer.append('=');
+ buffer.append(attrValue);
+ }
+ }
+
+ String closeTag = generateCloseTag(element);
+ if (closeTag != null)
+ buffer.append(closeTag);
+
+ return buffer.toString();
+ }
+
+ /**
+ */
+ public String generateTagName(Element element) {
+ if (element == null)
+ return null;
+ XMLElement xe = (XMLElement) element;
+ String tagName = element.getTagName();
+ if (tagName == null)
+ return null;
+ if (xe.isJSPTag()) {
+ if (tagName.equals(JSPTag.JSP_EXPRESSION))
+ return JSPTag.EXPRESSION_TOKEN;
+ if (tagName.equals(JSPTag.JSP_DECLARATION))
+ return JSPTag.DECLARATION_TOKEN;
+ if (tagName.equals(JSPTag.JSP_DIRECTIVE))
+ return JSPTag.DIRECTIVE_TOKEN;
+ if (tagName.startsWith(JSPTag.JSP_DIRECTIVE)) {
+ int offset = JSPTag.JSP_DIRECTIVE.length() + 1; // after '.'
+ return (JSPTag.DIRECTIVE_TOKEN + tagName.substring(offset));
+ }
+ return (xe.isCommentTag()) ? tagName : null;
+ } else if (tagName.startsWith(JSPTag.TAG_OPEN)) {
+ if (!tagName.endsWith(JSPTag.TAG_CLOSE)) {
+ // close JSP
+ return (tagName + JSPTag.TAG_CLOSE);
+ }
+ } else if (xe.isCommentTag()) {
+ String prefix = element.getPrefix();
+ if (prefix.equals(SSI_PREFIX)) {
+ return (SSI_TOKEN + element.getLocalName());
+ }
+ } else {
+ if (!xe.isJSPTag() && xe.isGlobalTag() && // global tag
+ CMNodeUtil.getElementDeclaration(xe) != null) {
+ String newName = tagName;
+ switch (getTagNameCase(xe)) {
+ case DocumentTypeAdapter.UPPER_CASE :
+ newName = tagName.toUpperCase();
+ break;
+ case DocumentTypeAdapter.LOWER_CASE :
+ newName = tagName.toLowerCase();
+ break;
+ }
+ if (newName != tagName) {
+ tagName = newName;
+ setTagName(element, tagName);
+ }
+ }
+ }
+ return tagName;
+ }
+
+ /**
+ * generateText method
+ *
+ * @return java.lang.String
+ * @param text
+ * org.w3c.dom.Text
+ */
+ public String generateText(Text text) {
+ if (text == null)
+ return null;
+ TextImpl impl = (TextImpl) text;
+ String source = impl.getTextSource();
+ if (source != null)
+ return source;
+ return generateTextData(text, impl.getData());
+ }
+
+ /**
+ */
+ public String generateTextData(Text text, String data) {
+ if (data == null)
+ return null;
+ if (text == null)
+ return null;
+ TextImpl impl = (TextImpl) text;
+ if (impl.isJSPContent() || impl.isCDATAContent()) {
+ return new SourceValidator(impl).convertSource(data);
+ }
+ String source = data;
+
+ // convert special characters to character entities
+ StringBuffer buffer = null;
+ int offset = 0;
+ int length = data.length();
+ for (int i = 0; i < length; i++) {
+ String name = getCharName(data.charAt(i));
+ if (name == null)
+ continue;
+ if (buffer == null)
+ buffer = new StringBuffer(length + 8);
+ if (i > offset)
+ buffer.append(data.substring(offset, i));
+ buffer.append('&');
+ buffer.append(name);
+ buffer.append(';');
+ offset = i + 1;
+ }
+ if (buffer != null) {
+ if (length > offset)
+ buffer.append(data.substring(offset));
+ source = buffer.toString();
+ }
+
+ if (source == null || source.length() == 0)
+ return null;
+ return source;
+ }
+
+ /**
+ */
+ private int getAttrNameCase(Attr attr) {
+ DocumentImpl document = (DocumentImpl) attr.getOwnerDocument();
+ if (document == null)
+ return DocumentTypeAdapter.STRICT_CASE;
+ DocumentTypeAdapter adapter = document.getDocumentTypeAdapter();
+ if (adapter == null)
+ return DocumentTypeAdapter.STRICT_CASE;
+ return adapter.getAttrNameCase();
+ }
+
+ /**
+ */
+ private String getCharName(char c) {
+ switch (c) {
+ case '<' :
+ return XMLCharEntity.LT_NAME;
+ case '>' :
+ return XMLCharEntity.GT_NAME;
+ case '&' :
+ return XMLCharEntity.AMP_NAME;
+ case '"' :
+ return XMLCharEntity.QUOT_NAME;
+ }
+ return null;
+ }
+
+ /**
+ */
+ private int getTagNameCase(Element element) {
+ DocumentImpl document = (DocumentImpl) element.getOwnerDocument();
+ if (document == null)
+ return DocumentTypeAdapter.STRICT_CASE;
+ DocumentTypeAdapter adapter = document.getDocumentTypeAdapter();
+ if (adapter == null)
+ return DocumentTypeAdapter.STRICT_CASE;
+ return adapter.getTagNameCase();
+ }
+
+ /**
+ */
+ private boolean isBooleanAttr(Attr attr) {
+ if (attr == null)
+ return false;
+ CMAttributeDeclaration decl = CMNodeUtil.getAttributeDeclaration(attr);
+ if (decl == null)
+ return false;
+ CMDataType type = decl.getAttrType();
+ if (type == null)
+ return false;
+ String values[] = type.getEnumeratedValues();
+ if (values == null)
+ return false;
+ return (values.length == 1 && values[0].equals(decl.getAttrName()));
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelContext.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelContext.java
new file mode 100644
index 0000000000..6a799f75f4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelContext.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+/**
+ * XMLModelContext class
+ */
+class XMLModelContext {
+ private Node nextNode = null;
+ private Node parentNode = null;
+
+ // private XMLModelImpl model = null;
+ private Node rootNode = null;
+
+ /**
+ * XMLModelContext constructor
+ *
+ * @param rootNode
+ * org.w3c.dom.Node
+ */
+ XMLModelContext(Node rootNode) {
+ super();
+
+ this.rootNode = rootNode;
+ }
+
+ /**
+ * findEndTag method
+ *
+ * @return org.w3c.dom.Element
+ * @param tagName
+ * java.lang.String
+ */
+ Element findEndTag(String tagName) {
+ if (tagName == null)
+ return null;
+ if (this.parentNode == null)
+ return null;
+
+ for (Node parent = this.parentNode.getParentNode(); parent != null; parent = parent.getParentNode()) {
+ if (parent.getNodeType() != Node.ELEMENT_NODE)
+ break;
+ ElementImpl element = (ElementImpl) parent;
+ if (element.hasEndTag()) {
+ if (element.matchTagName(tagName))
+ return element;
+ // if ancestor element has end tag stop search
+ break;
+ }
+ if (element.getNextSibling() != null)
+ break;
+ }
+
+ return null;
+ }
+
+ /**
+ */
+ Text findNextText() {
+ Node node = this.nextNode;
+ while (node != null) {
+ if (node != this.nextNode && node.getNodeType() == Node.TEXT_NODE) {
+ TextImpl text = (TextImpl) node;
+ // skip empty text
+ if (text.getStructuredDocumentRegion() != null)
+ return text;
+ }
+ Node child = node.getFirstChild();
+ if (child != null) {
+ node = child;
+ continue;
+ }
+ while (node != null) {
+ Node next = node.getNextSibling();
+ if (next != null) {
+ node = next;
+ break;
+ }
+ node = node.getParentNode();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * findPreviousText method
+ *
+ * @return org.w3c.dom.Text
+ */
+ Text findPreviousText() {
+ if (this.parentNode == null)
+ return null;
+ Node node = null;
+ if (this.nextNode != null)
+ node = this.nextNode.getPreviousSibling();
+ else
+ node = this.parentNode.getLastChild();
+ if (node == null || node.getNodeType() != Node.TEXT_NODE)
+ return null;
+ return (Text) node;
+ }
+
+ /**
+ * findStartTag method
+ *
+ * @return org.w3c.dom.Element
+ * @param tagName
+ * java.lang.String
+ */
+ Element findStartTag(String tagName, String rootName) {
+ if (tagName == null)
+ return null;
+
+ // check previous for empty content element
+ Node prev = null;
+ if (this.nextNode != null)
+ prev = this.nextNode.getPreviousSibling();
+ else if (this.parentNode != null)
+ prev = this.parentNode.getLastChild();
+ if (prev != null && prev.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) prev;
+ if (!element.hasEndTag() && !element.isEmptyTag() && element.matchTagName(tagName))
+ return element;
+ }
+
+ for (Node parent = this.parentNode; parent != null; parent = parent.getParentNode()) {
+ if (parent.getNodeType() != Node.ELEMENT_NODE)
+ break;
+ ElementImpl element = (ElementImpl) parent;
+ if (element.matchTagName(tagName))
+ return element;
+ if (rootName != null && element.matchTagName(rootName))
+ break;
+ }
+
+ return null;
+ }
+
+ /**
+ * getNextNode method
+ *
+ * @return org.w3c.dom.Node
+ */
+ Node getNextNode() {
+ return this.nextNode;
+ }
+
+ /**
+ * getParentNode method
+ *
+ * @return org.w3c.dom.Node
+ */
+ Node getParentNode() {
+ return this.parentNode;
+ }
+
+ /**
+ * getRootNode method
+ *
+ * @return org.w3c.dom.Node
+ */
+ Node getRootNode() {
+ return this.rootNode;
+ }
+
+ /**
+ * setLast method
+ */
+ void setLast() {
+ if (this.parentNode == null)
+ return;
+ if (this.nextNode != null) {
+ Node prev = this.nextNode.getPreviousSibling();
+ if (prev == null || prev.getNodeType() != Node.ELEMENT_NODE)
+ return;
+ ElementImpl element = (ElementImpl) prev;
+ if (element.hasEndTag() || !element.isContainer() || element.isEmptyTag())
+ return;
+ setParentNode(prev);
+ }
+
+ // find last open parent
+ Node parent = this.parentNode;
+ Node last = parent.getLastChild();
+ while (last != null) {
+ if (last.getNodeType() != Node.ELEMENT_NODE)
+ break;
+ ElementImpl element = (ElementImpl) last;
+ if (element.hasEndTag() || !element.isContainer() || element.isEmptyTag())
+ break;
+ parent = element;
+ last = parent.getLastChild();
+ }
+ if (parent != this.parentNode)
+ setParentNode(parent);
+ }
+
+ /**
+ * setNextNode method
+ *
+ * @param nextNode
+ * org.w3c.dom.Node
+ */
+ void setNextNode(Node nextNode) {
+ this.nextNode = nextNode;
+ if (nextNode == null)
+ return;
+ this.parentNode = nextNode.getParentNode();
+ }
+
+ /**
+ * setParentNode method
+ *
+ * @param parentNode
+ * org.w3c.dom.Node
+ */
+ void setParentNode(Node parentNode) {
+ this.parentNode = parentNode;
+ this.nextNode = null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelImpl.java
new file mode 100644
index 0000000000..640a164113
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelImpl.java
@@ -0,0 +1,875 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+import org.eclipse.wst.sse.core.AbstractStructuredModel;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.events.NewDocumentEvent;
+import org.eclipse.wst.sse.core.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.Logger;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLGenerator;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLModelNotifier;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * XMLModelImpl class
+ */
+public class XMLModelImpl extends AbstractStructuredModel implements IStructuredDocumentListener, XMLModel, DOMImplementation {
+ private static String TRACE_PARSER_MANAGEMENT_EXCEPTION = "parserManagement"; //$NON-NLS-1$
+ private Object active = null;
+ protected DocumentImpl document = null;
+ private XMLGenerator generator = null;
+ private XMLModelNotifier notifier = null;
+ private XMLModelParser parser = null;
+ private boolean refresh = false;
+ private XMLModelUpdater updater = null;
+
+ /**
+ * XMLModelImpl constructor
+ */
+ public XMLModelImpl() {
+ super();
+ this.document = (DocumentImpl) internalCreateDocument();
+ }
+
+ /**
+ * This API allows clients to declare that they are about to make a
+ * "large" change to the model. This change might be in terms of content
+ * or it might be in terms of the model id or base location.
+ *
+ * Note that in the case of embedded calls, notification to listners is
+ * sent only once.
+ *
+ * Note that the client who is making these changes has the responsibility
+ * to restore the models state once finished with the changes. See
+ * getMemento and restoreState.
+ *
+ * The method isModelStateChanging can be used by a client to determine if
+ * the model is already in a change sequence.
+ */
+ public void aboutToChangeModel() {
+ super.aboutToChangeModel();
+ // technically, no need to call beginChanging so often,
+ // since aboutToChangeModel can be nested.
+ // but will leave as is for this release.
+ // see modelChanged, and be sure stays coordinated there.
+ getModelNotifier().beginChanging();
+ }
+
+ public void aboutToReinitializeModel() {
+ XMLModelNotifier notifier = getModelNotifier();
+ notifier.cancelPending();
+ super.aboutToReinitializeModel();
+ }
+
+ /**
+ * attrReplaced method
+ *
+ * @param element
+ * org.w3c.dom.Element
+ * @param newAttr
+ * org.w3c.dom.Attr
+ * @param oldAttr
+ * org.w3c.dom.Attr
+ */
+ protected void attrReplaced(Element element, Attr newAttr, Attr oldAttr) {
+ if (element == null)
+ return;
+ if (getActiveParser() == null) {
+ XMLModelUpdater updater = getModelUpdater();
+ setActive(updater);
+ updater.initialize();
+ updater.replaceAttr(element, newAttr, oldAttr);
+ setActive(null);
+ }
+ getModelNotifier().attrReplaced(element, newAttr, oldAttr);
+ }
+
+ /**
+ * This API allows a client controlled way of notifying all ModelEvent
+ * listners that the model has been changed. This method is a matched pair
+ * to aboutToChangeModel, and must be called after aboutToChangeModel ...
+ * or some listeners could be left waiting indefinitely for the changed
+ * event. So, its suggested that changedModel always be in a finally
+ * clause. Likewise, a client should never call changedModel without
+ * calling aboutToChangeModel first.
+ *
+ * In the case of embedded calls, the notification is just sent once.
+ *
+ */
+ public void changedModel() {
+ // NOTE: the order of 'changedModel' and 'endChanging' is significant.
+ // By calling changedModel first, this basically decrements the
+ // "isChanging" counter
+ // in super class and when zero all listeners to model state events
+ // will be notified
+ // that the model has been changed. 'endChanging' will notify all
+ // deferred adapters.
+ // So, the significance of order is that adapters (and methods they
+ // call)
+ // can count on the state of model "isChanging" to be accurate.
+ // But, remember, that this means the "modelChanged" event can be
+ // received before all
+ // adapters have finished their processing.
+ // NOTE NOTE: The above note is obsolete in fact (though still states
+ // issue correctly).
+ // Due to popular demand, the order of these calls were reversed and
+ // behavior
+ // changed on 07/22/2004.
+ //
+ // see also
+ // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4302
+ // for motivation for this 'on verge of' call.
+ // this could be improved in future if notifier also used counting
+ // flag to avoid nested calls. If/when changed be sure to check if
+ // aboutToChangeModel needs any changes too.
+ if (isModelChangeStateOnVergeOfEnding()) {
+ // end lock before noticiation loop, since directly or indirectly
+ // we may be "called from foriegn code" during notification.
+ endLock();
+
+ // the notifier is what controls adaper notification, which
+ // should be sent out before the 'modelChanged' event.
+ getModelNotifier().endChanging();
+ }
+ // changedModel handles 'nesting', so only one event sent out
+ // when mulitple calls to 'aboutToChange/Changed'.
+ super.changedModel();
+ handleRefresh();
+ }
+
+ /**
+ * childReplaced method
+ *
+ * @param parentNode
+ * org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param oldChild
+ * org.w3c.dom.Node
+ */
+ protected void childReplaced(Node parentNode, Node newChild, Node oldChild) {
+ if (parentNode == null)
+ return;
+ if (getActiveParser() == null) {
+ XMLModelUpdater updater = getModelUpdater();
+ setActive(updater);
+ updater.initialize();
+ updater.replaceChild(parentNode, newChild, oldChild);
+ setActive(null);
+ }
+ getModelNotifier().childReplaced(parentNode, newChild, oldChild);
+ }
+
+ /**
+ * Creates an XML <code>Document</code> object of the specified type
+ * with its document element. HTML-only DOM implementations do not need to
+ * implement this method.
+ *
+ * @param namespaceURIThe
+ * namespace URI of the document element to create.
+ * @param qualifiedNameThe
+ * qualified name of the document element to be created.
+ * @param doctypeThe
+ * type of document to be created or <code>null</code>. When
+ * <code>doctype</code> is not <code>null</code>, its
+ * <code>Node.ownerDocument</code> attribute is set to the
+ * document being created.
+ * @return A new <code>Document</code> object.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified qualified
+ * name contains an illegal character. <br>
+ * NAMESPACE_ERR: Raised if the <code>qualifiedName</code>
+ * is malformed, if the <code>qualifiedName</code> has a
+ * prefix and the <code>namespaceURI</code> is
+ * <code>null</code>, or if the
+ * <code>qualifiedName</code> has a prefix that is "xml"
+ * and the <code>namespaceURI</code> is different from "
+ * http://www.w3.org/XML/1998/namespace" .<br>
+ * WRONG_DOCUMENT_ERR: Raised if <code>doctype</code> has
+ * already been used with a different document or was
+ * created from a different implementation.
+ * @since DOM Level 2
+ */
+ public Document createDocument(String namespaceURI, String qualifiedName, DocumentType doctype) throws DOMException {
+ return null;
+ }
+
+ /**
+ * Creates an empty <code>DocumentType</code> node. Entity declarations
+ * and notations are not made available. Entity reference expansions and
+ * default attribute additions do not occur. It is expected that a future
+ * version of the DOM will provide a way for populating a
+ * <code>DocumentType</code>.<br>
+ * HTML-only DOM implementations do not need to implement this method.
+ *
+ * @param qualifiedNameThe
+ * qualified name of the document type to be created.
+ * @param publicIdThe
+ * external subset public identifier.
+ * @param systemIdThe
+ * external subset system identifier.
+ * @return A new <code>DocumentType</code> node with
+ * <code>Node.ownerDocument</code> set to <code>null</code>.
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified qualified
+ * name contains an illegal character. <br>
+ * NAMESPACE_ERR: Raised if the <code>qualifiedName</code>
+ * is malformed.
+ * @since DOM Level 2
+ */
+ public DocumentType createDocumentType(String qualifiedName, String publicId, String systemId) throws DOMException {
+ DocumentTypeImpl documentType = new DocumentTypeImpl();
+ documentType.setName(qualifiedName);
+ documentType.setPublicId(publicId);
+ documentType.setSystemId(systemId);
+ return documentType;
+ }
+
+ /**
+ */
+ protected void documentTypeChanged() {
+ if (this.refresh)
+ return;
+ // unlike 'resfresh', 'reinitialize' finishes loop
+ // and flushes remaining notification que before
+ // actually reinitializing.
+ // FUTURE: perhaps all "handleRefresh" should be changed
+ // to "reinit needede"?
+ this.setReinitializeNeeded(true);
+ }
+
+ protected void editableChanged(Node node) {
+ if (node != null) {
+ getModelNotifier().editableChanged(node);
+ }
+ }
+
+ /**
+ */
+ protected void endTagChanged(Element element) {
+ if (element == null)
+ return;
+ if (getActiveParser() == null) {
+ XMLModelUpdater updater = getModelUpdater();
+ setActive(updater);
+ updater.initialize();
+ updater.changeEndTag(element);
+ setActive(null);
+ }
+ getModelNotifier().endTagChanged(element);
+ }
+
+ /**
+ */
+ private XMLModelParser getActiveParser() {
+ if (this.parser == null)
+ return null;
+ if (this.parser != this.active)
+ return null;
+ return this.parser;
+ }
+
+ /**
+ */
+ private XMLModelUpdater getActiveUpdater() {
+ if (this.updater == null)
+ return null;
+ if (this.updater != this.active)
+ return null;
+ return this.updater;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class adapter) {
+ if (Document.class.equals(adapter))
+ return getDocument();
+ return super.getAdapter(adapter);
+ }
+
+ /**
+ * getDocument method
+ *
+ * @return XMLDocument
+ */
+ public XMLDocument getDocument() {
+ return this.document;
+ }
+
+ public XMLGenerator getGenerator() {
+ if (this.generator == null) {
+ this.generator = XMLGeneratorImpl.getInstance();
+ }
+ return this.generator;
+ }
+
+ /**
+ * getNode method
+ *
+ * @param offset
+ * int
+ */
+ public IndexedRegion getIndexedRegion(int offset) {
+ if (this.document == null)
+ return null;
+ // search in document children
+ XMLNode parent = null;
+ int length = this.document.getEndOffset();
+ if (offset * 2 < length) {
+ // search from the first
+ XMLNode child = (XMLNode) this.document.getFirstChild();
+ while (child != null) {
+ if (child.getEndOffset() <= offset) {
+ child = (XMLNode) child.getNextSibling();
+ continue;
+ }
+ if (child.getStartOffset() > offset) {
+ break;
+ }
+ IStructuredDocumentRegion startStructuredDocumentRegion = child.getStartStructuredDocumentRegion();
+ if (startStructuredDocumentRegion != null) {
+ if (startStructuredDocumentRegion.getEnd() > offset)
+ return child;
+ }
+ IStructuredDocumentRegion endStructuredDocumentRegion = child.getEndStructuredDocumentRegion();
+ if (endStructuredDocumentRegion != null) {
+ if (endStructuredDocumentRegion.getStart() <= offset)
+ return child;
+ }
+ // dig more
+ parent = child;
+ child = (XMLNode) parent.getFirstChild();
+ }
+ } else {
+ // search from the last
+ XMLNode child = (XMLNode) this.document.getLastChild();
+ while (child != null) {
+ if (child.getStartOffset() > offset) {
+ child = (XMLNode) child.getPreviousSibling();
+ continue;
+ }
+ if (child.getEndOffset() <= offset) {
+ break;
+ }
+ IStructuredDocumentRegion startStructuredDocumentRegion = child.getStartStructuredDocumentRegion();
+ if (startStructuredDocumentRegion != null) {
+ if (startStructuredDocumentRegion.getEnd() > offset)
+ return child;
+ }
+ IStructuredDocumentRegion endStructuredDocumentRegion = child.getEndStructuredDocumentRegion();
+ if (endStructuredDocumentRegion != null) {
+ if (endStructuredDocumentRegion.getStart() <= offset)
+ return child;
+ }
+ // dig more
+ parent = child;
+ child = (XMLNode) parent.getLastChild();
+ }
+ }
+ return parent;
+ }
+
+ /**
+ */
+ public XMLModelNotifier getModelNotifier() {
+ if (this.notifier == null) {
+ this.notifier = new XMLModelNotifierImpl();
+ }
+ return this.notifier;
+ }
+
+ /**
+ */
+ private XMLModelParser getModelParser() {
+ if (this.parser == null) {
+ this.parser = new XMLModelParser(this);
+ }
+ return this.parser;
+ }
+
+ /**
+ */
+ private XMLModelUpdater getModelUpdater() {
+ if (this.updater == null) {
+ this.updater = new XMLModelUpdater(this);
+ }
+ return this.updater;
+ }
+
+ /**
+ */
+ private void handleRefresh() {
+ if (!this.refresh)
+ return;
+ XMLModelNotifier notifier = getModelNotifier();
+ boolean isChanging = notifier.isChanging();
+ if (!isChanging)
+ notifier.beginChanging(true);
+ XMLModelParser parser = getModelParser();
+ setActive(parser);
+ this.document.removeChildNodes();
+ try {
+ parser.replaceStructuredDocumentRegions(getStructuredDocument().getRegionList(), null);
+ } catch (Exception ex) {
+ Logger.logException(ex);
+ } finally {
+ setActive(null);
+ if (!isChanging)
+ notifier.endChanging();
+ this.refresh = false;
+ }
+ }
+
+ /**
+ * Test if the DOM implementation implements a specific feature.
+ *
+ * @param featureThe
+ * name of the feature to test (case-insensitive). The values
+ * used by DOM features are defined throughout the DOM Level 2
+ * specifications and listed in the section. The name must be
+ * an XML name. To avoid possible conflicts, as a convention,
+ * names referring to features defined outside the DOM
+ * specification should be made unique by reversing the name of
+ * the Internet domain name of the person (or the organization
+ * that the person belongs to) who defines the feature,
+ * component by component, and using this as a prefix. For
+ * instance, the W3C SVG Working Group defines the feature
+ * "org.w3c.dom.svg".
+ * @param versionThis
+ * is the version number of the feature to test. In Level 2,
+ * the string can be either "2.0" or "1.0". If the version is
+ * not specified, supporting any version of the feature causes
+ * the method to return <code>true</code>.
+ * @return <code>true</code> if the feature is implemented in the
+ * specified version, <code>false</code> otherwise.
+ */
+ public boolean hasFeature(String feature, String version) {
+ if (feature == null)
+ return false;
+ if (version != null) {
+ if (!version.equals("1.0") && !version.equals("2.0")) { //$NON-NLS-2$//$NON-NLS-1$
+ return false;
+ }
+ }
+ if (feature.equalsIgnoreCase("Core")) //$NON-NLS-1$
+ return true; //$NON-NLS-1$
+ if (feature.equalsIgnoreCase("XML")) //$NON-NLS-1$
+ return true; //$NON-NLS-1$
+ return false;
+ }
+
+ /**
+ * createDocument method
+ *
+ * @return org.w3c.dom.Document
+ */
+ protected Document internalCreateDocument() {
+ DocumentImpl document = new DocumentImpl();
+ document.setModel(this);
+ return document;
+ }
+
+ boolean isReparsing() {
+ return (active != null);
+ }
+
+ /**
+ * nameChanged method
+ *
+ * @param node
+ * org.w3c.dom.Node
+ */
+ protected void nameChanged(Node node) {
+ if (node == null)
+ return;
+ if (getActiveParser() == null) {
+ XMLModelUpdater updater = getModelUpdater();
+ setActive(updater);
+ updater.initialize();
+ updater.changeName(node);
+ setActive(null);
+ }
+ // notification is already sent
+ }
+
+ /**
+ * newModel method
+ *
+ * @param structuredDocumentEvent
+ * com.ibm.sed.structuredDocument.impl.events.NewModelEvent
+ */
+ public void newModel(NewDocumentEvent structuredDocumentEvent) {
+ if (structuredDocumentEvent == null)
+ return;
+ IStructuredDocument structuredDocument = structuredDocumentEvent.getStructuredDocument();
+ if (structuredDocument == null)
+ return;
+ // this should not happen, but for the case
+ if (structuredDocument != getStructuredDocument())
+ setStructuredDocument(structuredDocument);
+ IStructuredDocumentRegionList flatNodes = structuredDocument.getRegionList();
+ if (flatNodes == null)
+ return;
+ if (this.document == null)
+ return; // being constructed
+ XMLModelUpdater updater = getActiveUpdater();
+ if (updater != null) { // being updated
+ try {
+ updater.replaceStructuredDocumentRegions(flatNodes, null);
+ } catch (Exception ex) {
+ Logger.logException(ex);
+ this.refresh = true;
+ handleRefresh();
+ } finally {
+ setActive(null);
+ }
+ // // for new model, we might need to
+ // // re-init, e.g. if someone calls setText
+ // // on an existing model
+ // checkForReinit();
+ return;
+ }
+ XMLModelNotifier notifier = getModelNotifier();
+ boolean isChanging = notifier.isChanging();
+ // call even if changing to notify doing new model
+ getModelNotifier().beginChanging(true);
+ XMLModelParser parser = getModelParser();
+ setActive(parser);
+ this.document.removeChildNodes();
+ try {
+ parser.replaceStructuredDocumentRegions(flatNodes, null);
+ } catch (Exception ex) {
+ Logger.logException(ex);
+ // meaningless to refresh, because the result might be the same
+ } finally {
+ setActive(null);
+ if (!isChanging) {
+ getModelNotifier().endChanging();
+ }
+ // ignore refresh
+ this.refresh = false;
+ }
+ // checkForReinit();
+ }
+
+ /**
+ */
+ public void noChange(NoChangeEvent event) {
+ XMLModelUpdater updater = getActiveUpdater();
+ if (updater != null) { // being updated
+ // cleanup updater staffs
+ try {
+ updater.replaceStructuredDocumentRegions(null, null);
+ } catch (Exception ex) {
+ Logger.logException(ex);
+ this.refresh = true;
+ handleRefresh();
+ } finally {
+ setActive(null);
+ }
+ // I guess no chanage means the model could not need re-init
+ //checkForReinit();
+ return;
+ }
+ }
+
+ /**
+ * nodesReplaced method
+ *
+ * @param event
+ * com.ibm.sed.structuredDocument.impl.events.NodesReplacedElement
+ */
+ public void nodesReplaced(StructuredDocumentRegionsReplacedEvent event) {
+ if (event == null)
+ return;
+ IStructuredDocumentRegionList oldStructuredDocumentRegions = event.getOldStructuredDocumentRegions();
+ IStructuredDocumentRegionList newStructuredDocumentRegions = event.getNewStructuredDocumentRegions();
+ XMLModelUpdater updater = getActiveUpdater();
+ if (updater != null) { // being updated
+ try {
+ updater.replaceStructuredDocumentRegions(newStructuredDocumentRegions, oldStructuredDocumentRegions);
+ } catch (Exception ex) {
+ if (ex.getClass().equals(StructuredDocumentRegionManagementException.class)) {
+ Logger.traceException(TRACE_PARSER_MANAGEMENT_EXCEPTION, ex);
+ } else {
+ Logger.logException(ex);
+ }
+ this.refresh = true;
+ handleRefresh();
+ } finally {
+ setActive(null);
+ }
+ //checkForReinit();
+ return;
+ }
+ XMLModelNotifier notifier = getModelNotifier();
+ boolean isChanging = notifier.isChanging();
+ if (!isChanging)
+ notifier.beginChanging();
+ XMLModelParser parser = getModelParser();
+ setActive(parser);
+ try {
+ parser.replaceStructuredDocumentRegions(newStructuredDocumentRegions, oldStructuredDocumentRegions);
+ } catch (Exception ex) {
+ Logger.logException(ex);
+ this.refresh = true;
+ handleRefresh();
+ } finally {
+ setActive(null);
+ if (!isChanging) {
+ notifier.endChanging();
+ handleRefresh();
+ }
+ }
+
+ }
+
+ /**
+ * regionChanged method
+ *
+ * @param structuredDocumentEvent
+ * com.ibm.sed.structuredDocument.impl.events.RegionChangedEvent
+ */
+ public void regionChanged(RegionChangedEvent event) {
+ if (event == null)
+ return;
+ IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
+ if (flatNode == null)
+ return;
+ ITextRegion region = event.getRegion();
+ if (region == null)
+ return;
+ XMLModelUpdater updater = getActiveUpdater();
+ if (updater != null) { // being updated
+ try {
+ updater.changeRegion(flatNode, region);
+ } catch (Exception ex) {
+ Logger.logException(ex);
+ this.refresh = true;
+ handleRefresh();
+ } finally {
+ setActive(null);
+ }
+ // checkForReinit();
+ return;
+ }
+ XMLModelNotifier notifier = getModelNotifier();
+ boolean isChanging = notifier.isChanging();
+ if (!isChanging)
+ notifier.beginChanging();
+ XMLModelParser parser = getModelParser();
+ setActive(parser);
+ try {
+ parser.changeRegion(flatNode, region);
+ } catch (Exception ex) {
+ Logger.logException(ex);
+ this.refresh = true;
+ handleRefresh();
+ } finally {
+ setActive(null);
+ if (!isChanging) {
+ notifier.endChanging();
+ handleRefresh();
+ }
+ }
+ // checkForReinit();
+ }
+
+ /**
+ * regionsReplaced method
+ *
+ * @param event
+ * com.ibm.sed.structuredDocument.impl.events.RegionReplacedEvent
+ */
+ public void regionsReplaced(RegionsReplacedEvent event) {
+ if (event == null)
+ return;
+ IStructuredDocumentRegion flatNode = event.getStructuredDocumentRegion();
+ if (flatNode == null)
+ return;
+ ITextRegionList oldRegions = event.getOldRegions();
+ ITextRegionList newRegions = event.getNewRegions();
+ if (oldRegions == null && newRegions == null)
+ return;
+ XMLModelUpdater updater = getActiveUpdater();
+ if (updater != null) { // being updated
+ try {
+ updater.replaceRegions(flatNode, newRegions, oldRegions);
+ } catch (Exception ex) {
+ Logger.logException(ex);
+ this.refresh = true;
+ handleRefresh();
+ } finally {
+ setActive(null);
+ }
+ // checkForReinit();
+ return;
+ }
+ XMLModelNotifier notifier = getModelNotifier();
+ boolean isChanging = notifier.isChanging();
+ if (!isChanging)
+ notifier.beginChanging();
+ XMLModelParser parser = getModelParser();
+ setActive(parser);
+ try {
+ parser.replaceRegions(flatNode, newRegions, oldRegions);
+ } catch (Exception ex) {
+ Logger.logException(ex);
+ this.refresh = true;
+ handleRefresh();
+ } finally {
+ setActive(null);
+ if (!isChanging) {
+ notifier.endChanging();
+ handleRefresh();
+ }
+ }
+ // checkForReinit();
+ }
+
+ /**
+ */
+ public void releaseFromEdit() {
+ if (!isShared()) {
+ //this.document.releaseStyleSheets();
+ this.document.releaseDocumentType();
+ }
+ super.releaseFromEdit();
+ }
+
+ /**
+ */
+ public void releaseFromRead() {
+ if (!isShared()) {
+ //this.document.releaseStyleSheets();
+ this.document.releaseDocumentType();
+ }
+ super.releaseFromRead();
+ }
+
+ /**
+ */
+ private void setActive(Object active) {
+ this.active = active;
+ // side effect
+ // when ever becomes active, besure tagNameCache is cleared
+ // (and not used)
+ if (active == null) {
+ document.activateTagNameCache(true);
+ } else {
+ document.activateTagNameCache(false);
+ }
+
+ }
+
+ /**
+ */
+ public void setGenerator(XMLGenerator generator) {
+ this.generator = generator;
+ }
+
+ /**
+ */
+ public void setModelNotifier(XMLModelNotifier notifier) {
+ this.notifier = notifier;
+ }
+
+ /**
+ */
+ public void setModelParser(XMLModelParser parser) {
+ this.parser = parser;
+ }
+
+ /**
+ */
+ public void setModelUpdater(XMLModelUpdater updater) {
+ this.updater = updater;
+ }
+
+ /**
+ * setStructuredDocument method
+ *
+ * @param structuredDocument
+ * com.ibm.sed.structuredDocument.IStructuredDocument
+ */
+ public void setStructuredDocument(IStructuredDocument structuredDocument) {
+ IStructuredDocument oldStructuredDocument = super.getStructuredDocument();
+ if (structuredDocument == oldStructuredDocument)
+ return; // nothing to do
+ if (oldStructuredDocument != null)
+ oldStructuredDocument.removeDocumentChangingListener(this);
+ super.setStructuredDocument(structuredDocument);
+ if (structuredDocument.getLength() > 0) {
+ newModel(new NewDocumentEvent(structuredDocument, this));
+ }
+ if (structuredDocument != null)
+ structuredDocument.addDocumentChangingListener(this);
+ }
+
+ /**
+ */
+ protected void startTagChanged(Element element) {
+ if (element == null)
+ return;
+ if (getActiveParser() == null) {
+ XMLModelUpdater updater = getModelUpdater();
+ setActive(updater);
+ updater.initialize();
+ updater.changeStartTag(element);
+ setActive(null);
+ }
+ getModelNotifier().startTagChanged(element);
+ }
+
+ /**
+ * valueChanged method
+ *
+ * @param node
+ * org.w3c.dom.Node
+ */
+ protected void valueChanged(Node node) {
+ if (node == null)
+ return;
+ if (getActiveParser() == null) {
+ XMLModelUpdater updater = getModelUpdater();
+ setActive(updater);
+ updater.initialize();
+ updater.changeValue(node);
+ setActive(null);
+ }
+ getModelNotifier().valueChanged(node);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifierImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifierImpl.java
new file mode 100644
index 0000000000..4146e0c5af
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelNotifierImpl.java
@@ -0,0 +1,469 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.xml.core.Logger;
+import org.eclipse.wst.xml.core.document.XMLModelNotifier;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class XMLModelNotifierImpl implements XMLModelNotifier {
+
+ /* end: for debugging only */
+ private class NotifyEvent {
+ Object changedFeature;
+ boolean discarded;
+ Object newValue;
+ // note: don't initialize instance variables, since
+ // that causes double assignments, and lots of these are created.
+ INodeNotifier notifier;
+ Object oldValue;
+ int pos;
+ String reason;
+ int type;
+
+ NotifyEvent(INodeNotifier notifier, int type, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ this.notifier = notifier;
+ this.type = type;
+ this.changedFeature = changedFeature;
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ this.pos = pos;
+ this.reason = ""; //$NON-NLS-1$
+ }
+ }
+
+ private final static String ADDED_THEN_REMOVED = "Discard: Added then removed rule"; //$NON-NLS-1$
+ private final static boolean fOptimizeDeferred = true;
+ private final static boolean fOptimizeDeferredAccordingToParentAdded = true;
+ private final static boolean fOptimizeDeferredAccordingToParentRemoved = true;
+ private final static String PARENT_IS_ADDED = "Disarded: Parent has just been added"; //$NON-NLS-1$
+ /* start: for debugging only */
+ private final static String PARENT_IS_REMOVED_TOO = "Discard: Parent was removed too"; //$NON-NLS-1$
+ private final static String PARENT_IS_REPARENTED = "Not Discard: Parent was removed so this implies reparenting"; //$NON-NLS-1$
+ private Node changedRoot = null;
+
+ private boolean changing = false;
+ private boolean doingNewModel = false;
+ private Vector events = null;
+ private boolean flushing = false;
+
+ /**
+ */
+ public XMLModelNotifierImpl() {
+ super();
+ }
+
+ /**
+ * attrReplaced method
+ *
+ * @param element
+ * org.w3c.dom.Element
+ * @param newAttr
+ * org.w3c.dom.Attr
+ * @param oldAttr
+ * org.w3c.dom.Attr
+ */
+ public void attrReplaced(Element element, Attr newAttr, Attr oldAttr) {
+ if (element == null)
+ return;
+ Attr attr = null;
+ String oldValue = null;
+ String newValue = null;
+ if (oldAttr != null) {
+ attr = oldAttr;
+ oldValue = oldAttr.getValue();
+ }
+ if (newAttr != null) {
+ attr = newAttr;
+ newValue = newAttr.getValue();
+ }
+ XMLNode notifier = (XMLNode) element;
+ int offset = notifier.getStartOffset();
+ notify(notifier, INodeNotifier.CHANGE, attr, oldValue, newValue, offset);
+ propertyChanged(notifier);
+ }
+
+ /**
+ */
+ public void beginChanging() {
+ this.changing = true;
+ }
+
+ /**
+ */
+ public void beginChanging(boolean newModel) {
+ beginChanging();
+ this.doingNewModel = newModel;
+ }
+
+ /**
+ * @see com.ibm.sed.model.xml.XMLModelNotifier#cancelPending()
+ */
+ public void cancelPending() {
+ // we don't want to change the size of this array, since
+ // the array may be being processed, in the defferred notification
+ // loop, but we can signal that all
+ // should be discarded, so any remaining ones will be ignored.
+ if (this.events != null) {
+ Iterator iterator = this.events.iterator();
+ while (iterator.hasNext()) {
+ NotifyEvent event = (NotifyEvent) iterator.next();
+ event.discarded = true;
+ }
+ }
+ // this cancel is presumably being called as a function of
+ // "reinitiailization" so we can ignore changes to the
+ // old root, and changes to the new one will be triggered during
+ // reinitialization.
+ changedRoot = null;
+ }
+
+ /**
+ * childReplaced method
+ *
+ * @param parentNode
+ * org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param oldChild
+ * org.w3c.dom.Node
+ */
+ public void childReplaced(Node parentNode, Node newChild, Node oldChild) {
+ if (parentNode == null)
+ return;
+ XMLNode notifier = (XMLNode) parentNode;
+ int type = INodeNotifier.CHANGE;
+ if (newChild == null)
+ type = INodeNotifier.REMOVE;
+ else if (oldChild == null)
+ type = INodeNotifier.ADD;
+ int offset = notifier.getStartOffset();
+ notify(notifier, type, oldChild, oldChild, newChild, offset);
+ structureChanged(notifier);
+ }
+
+ public void editableChanged(Node node) {
+ if (node == null)
+ return;
+ XMLNode notifier = (XMLNode) node;
+ int offset = notifier.getStartOffset();
+ notify(notifier, INodeNotifier.CHANGE, null, null, null, offset);
+ propertyChanged(notifier);
+ }
+
+ /**
+ */
+ public void endChanging() {
+ this.doingNewModel = false;
+ if (!this.changing)
+ return; // avoid nesting calls
+ notifyDeferred();
+ if (this.changedRoot != null) {
+ notifyStructureChanged(this.changedRoot);
+ if (Debug.debugNotifyDeferred) {
+ String p = this.changedRoot.getNodeName();
+ System.out.println("Deferred STRUCUTRE_CHANGED: " + p); //$NON-NLS-1$
+ }
+ this.changedRoot = null;
+ }
+ this.changing = false;
+ }
+
+ /**
+ */
+ public void endTagChanged(Element element) {
+ if (element == null)
+ return;
+ XMLNode notifier = (XMLNode) element;
+ int offset = notifier.getStartOffset();
+ notify(notifier, INodeNotifier.CHANGE, null, null, null, offset);
+ propertyChanged(element);
+ }
+
+ /**
+ */
+ public boolean hasChanged() {
+ return (this.events != null);
+ }
+
+ /**
+ */
+ public boolean isChanging() {
+ return this.changing;
+ }
+
+ /**
+ */
+ private void notify(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ if (notifier == null)
+ return;
+ if (this.changing && !this.flushing) {
+ // defer notification
+ if (this.events == null)
+ this.events = new Vector();
+ // we do not defer anything if we are doing a new Model,
+ // except for the document event, since all others are
+ // trivial and not needed at that initial point.
+ // But even for that one document event, in the new model case,
+ // it is still important to defer it.
+ if ((!doingNewModel) || (((Node) notifier).getNodeType() == Node.DOCUMENT_NODE)) {
+ this.events.addElement(new NotifyEvent(notifier, eventType, changedFeature, oldValue, newValue, pos));
+ }
+ return;
+ }
+ try {
+ // Its important to "keep going" if exception occurs, since this
+ // notification
+ // comes in between "about to change" and "changed" events. We do
+ // log, however,
+ // since would indicate a program error.
+ notifier.notify(eventType, changedFeature, oldValue, newValue, pos);
+ } catch (Exception e) {
+ Logger.logException("A structured model client threw following exception during adapter notification (" + INodeNotifier.EVENT_TYPE_STRINGS[eventType] + " )", e); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ /**
+ */
+ private void notifyDeferred() {
+ if (this.events == null)
+ return;
+ if (this.flushing)
+ return;
+ this.flushing = true; // force notification
+ int count = this.events.size();
+ for (int i = 0; i < count; i++) {
+ NotifyEvent event = (NotifyEvent) this.events.elementAt(i);
+ if (event == null)
+ continue; // error
+ if (event.discarded)
+ continue;
+ if (!doingNewModel && fOptimizeDeferred) {
+ // check redundant events (no need to check if doing NewModel,
+ // since
+ // shouldn't be redunancies)
+ if (event.type == INodeNotifier.ADD) {
+ for (int n = i + 1; n < count; n++) {
+ NotifyEvent next = (NotifyEvent) this.events.elementAt(n);
+ if (next == null)
+ continue; // error
+ if (next.type == INodeNotifier.REMOVE && next.oldValue == event.newValue) {
+ // Added then removed later, discard both
+ event.discarded = true;
+ next.discarded = true;
+ if (Debug.debugNotifyDeferred) {
+ event.reason = event.reason + ADDED_THEN_REMOVED + "(see " + n + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ next.reason = next.reason + ADDED_THEN_REMOVED + "(see " + i + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ break;
+ }
+ }
+ if (event.discarded)
+ continue;
+ if (fOptimizeDeferredAccordingToParentAdded) {
+ for (int p = 0; p < i; p++) {
+ NotifyEvent prev = (NotifyEvent) this.events.elementAt(p);
+ if (prev == null)
+ continue; // error
+ if (prev.type == INodeNotifier.REMOVE && prev.oldValue == event.notifier) {
+ // parent is reparented, do not discard
+ if (Debug.debugNotifyDeferred) {
+ event.reason = event.reason + PARENT_IS_REPARENTED + "(see " + p + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ break;
+ } else if (prev.type == INodeNotifier.ADD && prev.newValue == event.notifier) {
+ // parent has been added, discard this
+ event.discarded = true;
+ if (Debug.debugNotifyDeferred) {
+ event.reason = event.reason + PARENT_IS_ADDED + "(see " + p + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ break;
+ }
+ }
+ if (event.discarded)
+ continue;
+ }
+ } else if (event.type == INodeNotifier.REMOVE) {
+ if (fOptimizeDeferredAccordingToParentRemoved) {
+ for (int n = i + 1; n < count; n++) {
+ NotifyEvent next = (NotifyEvent) this.events.elementAt(n);
+ if (next == null)
+ continue; // error
+ if (next.type == INodeNotifier.REMOVE) {
+ if (next.oldValue == event.notifier) {
+ // parent will be removed, discard this
+ event.discarded = true;
+ if (Debug.debugNotifyDeferred) {
+ event.reason = event.reason + PARENT_IS_REMOVED_TOO + "(see " + n + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ break;
+ }
+ }
+ }
+ if (event.discarded)
+ continue;
+ }
+ }
+ }
+ notify(event.notifier, event.type, event.changedFeature, event.oldValue, event.newValue, event.pos);
+ }
+ if (Debug.debugNotifyDeferred) {
+ for (int l = 0; l < count; l++) {
+ NotifyEvent event = (NotifyEvent) this.events.elementAt(l);
+ Object o = null;
+ String t = null;
+ if (event.type == INodeNotifier.ADD) {
+ o = event.newValue;
+ t = " + "; //$NON-NLS-1$
+ } else if (event.type == INodeNotifier.REMOVE) {
+ o = event.oldValue;
+ t = " - "; //$NON-NLS-1$
+ }
+ if (o instanceof Element) {
+ String p = ((Node) event.notifier).getNodeName();
+ String c = ((Node) o).getNodeName();
+ String d = (event.discarded ? "! " : " "); //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println(d + p + t + c);
+ }
+ }
+ }
+ this.flushing = false;
+ this.events = null;
+ }
+
+ /**
+ */
+ private void notifyStructureChanged(Node root) {
+ if (root == null)
+ return;
+ INodeNotifier notifier = (INodeNotifier) root;
+ try {
+ // Its important to "keep going" if exception occurs, since this
+ // notification
+ // comes in between "about to change" and "changed" events. We do
+ // log, however,
+ // since would indicate a program error.
+ notifier.notify(INodeNotifier.STRUCTURE_CHANGED, null, null, null, -1);
+ } catch (Exception e) {
+ Logger.logException("A structured model client threw following exception during adapter notification (" + INodeNotifier.EVENT_TYPE_STRINGS[INodeNotifier.STRUCTURE_CHANGED] + " )", e); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ }
+
+ /**
+ */
+ public void propertyChanged(Node node) {
+ }
+
+ /**
+ * @param node
+ */
+ private void setCommonRootIfNeeded(Node node) {
+ // defer notification
+ if (this.changedRoot == null) {
+ this.changedRoot = node;
+ } else {
+ // tiny optimization: if previous commonAncestor (changedRoot) is
+ // already 'document',
+ // or if already equal to this 'node',
+ // then no need to re-calculate
+ if (changedRoot.getNodeType() != Node.DOCUMENT_NODE && changedRoot != node) {
+ Node common = ((NodeImpl) this.changedRoot).getCommonAncestor(node);
+ if (common != null)
+ this.changedRoot = common;
+ else
+ this.changedRoot = node;
+ }
+ }
+ }
+
+ /**
+ */
+ public void startTagChanged(Element element) {
+ if (element == null)
+ return;
+ XMLNode notifier = (XMLNode) element;
+ int offset = notifier.getStartOffset();
+ notify(notifier, INodeNotifier.CHANGE, null, null, null, offset);
+ propertyChanged(element);
+ }
+
+ /**
+ */
+ public void structureChanged(Node node) {
+ if (node == null)
+ return;
+ if (isChanging()) {
+ setCommonRootIfNeeded(node);
+ if (Debug.debugNotifyDeferred) {
+ String p = this.changedRoot.getNodeName();
+ System.out.println("requested STRUCUTRE_CHANGED: " + p); //$NON-NLS-1$
+ }
+ return;
+ }
+ if (Debug.debugNotifyDeferred) {
+ String p = node.getNodeName();
+ System.out.println("STRUCUTRE_CHANGED: " + p); //$NON-NLS-1$
+ }
+ notifyStructureChanged(node);
+ }
+
+ /**
+ * valueChanged method
+ *
+ * @param node
+ * org.w3c.dom.Node
+ */
+ public void valueChanged(Node node) {
+ if (node == null)
+ return;
+ XMLNode notifier = null;
+ if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ Attr attr = (Attr) node;
+ notifier = (XMLNode) attr.getOwnerElement();
+ // TODO_dmw: experimental: changed 06/29/2004 to send "strucuture
+ // changed" even for attribute value changes
+ // there are pros and cons to considering attribute value
+ // "structure changed". Will (re)consider
+ // setCommonRootIfNeeded(notifier);
+ if (notifier == null)
+ return;
+ String value = attr.getValue();
+ int offset = notifier.getStartOffset();
+ notify(notifier, INodeNotifier.CHANGE, attr, null, value, offset);
+ } else {
+ // note: we do not send structured changed event for content
+ // changed
+ notifier = (XMLNode) node;
+ String value = node.getNodeValue();
+ int offset = notifier.getStartOffset();
+ notify(notifier, INodeNotifier.CHANGE, null, null, value, offset);
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ XMLNode parent = (XMLNode) node.getParentNode();
+ if (parent != null) {
+ notify(parent, INodeNotifier.CONTENT_CHANGED, node, null, value, offset);
+ }
+ }
+ }
+ propertyChanged(notifier);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java
new file mode 100644
index 0000000000..7d64743d9a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java
@@ -0,0 +1,2365 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.commentelement.impl.CommentElementConfiguration;
+import org.eclipse.wst.xml.core.commentelement.impl.CommentElementRegistry;
+import org.eclipse.wst.xml.core.document.JSPTag;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+/**
+ * XMLModelParser
+ */
+public class XMLModelParser implements org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts {
+ private ModelParserAdapter adapter = null;
+ private XMLModelContext context = null;
+ private DocumentImpl document = null;
+
+ private XMLModelImpl model = null;
+
+ /**
+ */
+ protected XMLModelParser(XMLModelImpl model) {
+ super();
+
+ if (model != null) {
+ this.model = model;
+ this.document = (DocumentImpl) model.getDocument();
+ if (this.document != null) {
+ this.adapter = (ModelParserAdapter) this.document.getAdapterFor(ModelParserAdapter.class);
+ }
+ }
+ }
+
+ /**
+ */
+ protected boolean canBeImplicitTag(Element element) {
+ if (this.adapter != null) {
+ return this.adapter.canBeImplicitTag(element);
+ }
+ return false;
+ }
+
+ /**
+ */
+ protected boolean canBeImplicitTag(Element element, Node child) {
+ if (this.adapter != null) {
+ return this.adapter.canBeImplicitTag(element, child);
+ }
+ return false;
+ }
+
+ /**
+ */
+ protected boolean canContain(Element element, Node child) {
+ if (element == null || child == null)
+ return false;
+ ElementImpl impl = (ElementImpl) element;
+ if (impl.isEndTag())
+ return false; // invalid (floating) end tag
+ if (!impl.isContainer())
+ return false;
+ if (child.getNodeType() != Node.TEXT_NODE) {
+ if (impl.isJSPContainer() || impl.isCDATAContainer()) {
+ // accepts only Text child
+ return false;
+ }
+ }
+ if (this.adapter != null) {
+ return this.adapter.canContain(element, child);
+ }
+ return true;
+ }
+
+ /**
+ */
+ private void changeAttrEqual(IStructuredDocumentRegion flatNode, ITextRegion region) {
+ int offset = flatNode.getStart();
+ if (offset < 0)
+ return;
+ NodeImpl root = (NodeImpl) this.context.getRootNode();
+ if (root == null)
+ return;
+ Node node = root.getNodeAt(offset);
+ if (node == null)
+ return;
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+ // just notify the change instead of setting data
+ ProcessingInstructionImpl pi = (ProcessingInstructionImpl) node;
+ pi.notifyValueChanged();
+ }
+ return;
+ }
+ // actually, do nothing
+ }
+
+ /**
+ * changeAttrName method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ * @param region
+ * com.ibm.sed.structuredDocument.ITextRegion
+ */
+ private void changeAttrName(IStructuredDocumentRegion flatNode, ITextRegion region) {
+ int offset = flatNode.getStart();
+ if (offset < 0)
+ return;
+ NodeImpl root = (NodeImpl) this.context.getRootNode();
+ if (root == null)
+ return;
+ Node node = root.getNodeAt(offset);
+ if (node == null)
+ return;
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+ // just notify the change instead of setting data
+ ProcessingInstructionImpl pi = (ProcessingInstructionImpl) node;
+ pi.notifyValueChanged();
+ }
+ return;
+ }
+
+ ElementImpl element = (ElementImpl) node;
+ NamedNodeMap attributes = element.getAttributes();
+ if (attributes == null)
+ return;
+ int length = attributes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) attributes.item(i);
+ if (attr == null)
+ continue;
+ if (attr.getNameRegion() != region)
+ continue;
+
+ String name = flatNode.getText(region);
+ attr.setName(name);
+ break;
+ }
+ }
+
+ /**
+ * changeAttrValue method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ * @param region
+ * com.ibm.sed.structuredDocument.ITextRegion
+ */
+ private void changeAttrValue(IStructuredDocumentRegion flatNode, ITextRegion region) {
+ int offset = flatNode.getStart();
+ if (offset < 0)
+ return;
+ NodeImpl root = (NodeImpl) this.context.getRootNode();
+ if (root == null)
+ return;
+ Node node = root.getNodeAt(offset);
+ if (node == null)
+ return;
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+ // just notify the change instead of setting data
+ ProcessingInstructionImpl pi = (ProcessingInstructionImpl) node;
+ pi.notifyValueChanged();
+ }
+ return;
+ }
+
+ ElementImpl element = (ElementImpl) node;
+ NamedNodeMap attributes = element.getAttributes();
+ if (attributes == null)
+ return;
+ int length = attributes.getLength();
+ for (int i = 0; i < length; i++) {
+ AttrImpl attr = (AttrImpl) attributes.item(i);
+ if (attr == null)
+ continue;
+ if (attr.getValueRegion() != region)
+ continue;
+ // just notify the change instead of setting value
+ attr.notifyValueChanged();
+ break;
+ }
+ }
+
+ /**
+ * changeData method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ * @param region
+ * com.ibm.sed.structuredDocument.ITextRegion
+ */
+ private void changeData(IStructuredDocumentRegion flatNode, ITextRegion region) {
+ int offset = flatNode.getStart();
+ if (offset < 0)
+ return;
+ NodeImpl root = (NodeImpl) this.context.getRootNode();
+ if (root == null)
+ return;
+ Node node = root.getNodeAt(offset);
+ if (node == null)
+ return;
+ switch (node.getNodeType()) {
+ case Node.TEXT_NODE : {
+ TextImpl text = (TextImpl) node;
+ if (text.isSharingStructuredDocumentRegion(flatNode)) {
+ // has consecutive text sharing IStructuredDocumentRegion
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ }
+ this.context.setNextNode(node);
+ cleanupText();
+ break;
+ }
+ case Node.CDATA_SECTION_NODE :
+ case Node.PROCESSING_INSTRUCTION_NODE :
+ break;
+ case Node.COMMENT_NODE :
+ case Node.ELEMENT_NODE :
+ // comment tag
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ default :
+ return;
+ }
+
+ // just notify the change instead of setting data
+ NodeImpl impl = (NodeImpl) node;
+ impl.notifyValueChanged();
+ }
+
+ /**
+ */
+ private void changeEndTag(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
+ int offset = flatNode.getStart();
+ if (offset < 0)
+ return; // error
+ NodeImpl root = (NodeImpl) this.context.getRootNode();
+ if (root == null)
+ return; // error
+ Node node = root.getNodeAt(offset);
+ if (node == null)
+ return; // error
+
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ }
+
+ // check if change is only for close tag
+ if (newRegions != null) {
+ Iterator e = newRegions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_CLOSE)
+ continue;
+
+ // other region has changed
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ }
+ }
+ if (oldRegions != null) {
+ Iterator e = oldRegions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_CLOSE)
+ continue;
+
+ // other region has changed
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ }
+ }
+
+ // change for close tag has no impact
+ // do nothing
+ }
+
+ /**
+ * changeRegion method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ * @param region
+ * com.ibm.sed.structuredDocument.ITextRegion
+ */
+ void changeRegion(IStructuredDocumentRegion flatNode, ITextRegion region) {
+ if (flatNode == null || region == null)
+ return;
+ if (this.document == null)
+ return;
+ this.context = new XMLModelContext(this.document);
+
+ // optimize typical cases
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_CONTENT || regionType == XMLRegionContext.XML_COMMENT_TEXT || regionType == XMLRegionContext.XML_CDATA_TEXT || regionType == XMLRegionContext.BLOCK_TEXT || regionType == JSP_CONTENT) {
+ changeData(flatNode, region);
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+ changeAttrName(flatNode, region);
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+ changeAttrValue(flatNode, region);
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+ changeAttrEqual(flatNode, region);
+ } else if (regionType == XMLRegionContext.XML_TAG_NAME || regionType == JSP_ROOT_TAG_NAME || regionType == JSP_DIRECTIVE_NAME) {
+ changeTagName(flatNode, region);
+ } else {
+ changeStructuredDocumentRegion(flatNode);
+ }
+ }
+
+ /**
+ */
+ private void changeStartTag(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
+ int offset = flatNode.getStart();
+ if (offset < 0)
+ return; // error
+ NodeImpl root = (NodeImpl) this.context.getRootNode();
+ if (root == null)
+ return; // error
+ Node node = root.getNodeAt(offset);
+ if (node == null)
+ return; // error
+
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ }
+ ElementImpl element = (ElementImpl) node;
+
+ // check if changes are only for attributes and close tag
+ boolean tagNameUnchanged = false;
+ if (newRegions != null) {
+ Iterator e = newRegions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME || regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS || regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+ continue;
+ if (regionType == XMLRegionContext.XML_TAG_CLOSE) {
+ // change from empty tag may have impact on structure
+ if (!element.isEmptyTag())
+ continue;
+ } else if (regionType == XMLRegionContext.XML_TAG_NAME || regionType == JSP_ROOT_TAG_NAME || regionType == JSP_DIRECTIVE_NAME) {
+ String oldTagName = element.getTagName();
+ String newTagName = flatNode.getText(region);
+ if (oldTagName != null && newTagName != null && oldTagName.equals(newTagName)) {
+ // the tag name is unchanged
+ tagNameUnchanged = true;
+ continue;
+ }
+ }
+
+ // other region has changed
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ }
+ }
+ if (oldRegions != null) {
+ Iterator e = oldRegions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME || regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS || regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+ continue;
+ if (regionType == XMLRegionContext.XML_TAG_CLOSE) {
+ // change from empty tag may have impact on structure
+ if (!element.isEmptyTag())
+ continue;
+ } else if (regionType == XMLRegionContext.XML_TAG_NAME || regionType == JSP_ROOT_TAG_NAME) {
+ // if new tag name is unchanged, it's OK
+ if (tagNameUnchanged)
+ continue;
+ }
+
+ // other region has changed
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ }
+ }
+
+ // update attributes
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return; // error
+ NamedNodeMap attributes = element.getAttributes();
+ if (attributes == null)
+ return; // error
+
+ // first remove attributes
+ int regionIndex = 0;
+ int attrIndex = 0;
+ AttrImpl attr = null;
+ while (attrIndex < attributes.getLength()) {
+ attr = (AttrImpl) attributes.item(attrIndex);
+ if (attr == null) { // error
+ attrIndex++;
+ continue;
+ }
+ ITextRegion nameRegion = attr.getNameRegion();
+ if (nameRegion == null) { // error
+ element.removeAttributeNode(attr);
+ continue;
+ }
+ boolean found = false;
+ for (int i = regionIndex; i < regions.size(); i++) {
+ ITextRegion region = regions.get(i);
+ if (region == nameRegion) {
+ regionIndex = i + 1; // next region
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ attrIndex++;
+ } else {
+ element.removeAttributeNode(attr);
+ }
+ }
+
+ // insert or update attributes
+ attrIndex = 0; // reset to first
+ AttrImpl newAttr = null;
+ ITextRegion oldValueRegion = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+ if (newAttr != null) {
+ // insert deferred new attribute
+ element.insertAttributeNode(newAttr, attrIndex++);
+ newAttr = null;
+ } else if (attr != null && oldValueRegion != null) {
+ // notify existing attribute value removal
+ attr.notifyValueChanged();
+ }
+
+ oldValueRegion = null;
+ attr = (AttrImpl) attributes.item(attrIndex);
+ if (attr != null && attr.getNameRegion() == region) {
+ // existing attribute
+ attrIndex++;
+ // clear other regions
+ oldValueRegion = attr.getValueRegion();
+ attr.setEqualRegion(null);
+ attr.setValueRegion(null);
+ } else {
+ String name = flatNode.getText(region);
+ attr = (AttrImpl) this.document.createAttribute(name);
+ if (attr != null)
+ attr.setNameRegion(region);
+ // defer insertion of new attribute
+ newAttr = attr;
+ }
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+ if (attr != null) {
+ attr.setEqualRegion(region);
+ }
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+ if (attr != null) {
+ attr.setValueRegion(region);
+ if (attr != newAttr && oldValueRegion != region) {
+ // notify existing attribute value changed
+ attr.notifyValueChanged();
+ }
+ oldValueRegion = null;
+ attr = null;
+ }
+ }
+ }
+
+ if (newAttr != null) {
+ // insert deferred new attribute
+ element.appendAttributeNode(newAttr);
+ } else if (attr != null && oldValueRegion != null) {
+ // notify existing attribute value removal
+ attr.notifyValueChanged();
+ }
+ }
+
+ /**
+ * changeStructuredDocumentRegion method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void changeStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return;
+ if (this.document == null)
+ return;
+
+ setupContext(flatNode);
+
+ removeStructuredDocumentRegion(flatNode);
+ // make sure the parent is set to deepest level
+ // when end tag has been removed
+ this.context.setLast();
+ insertStructuredDocumentRegion(flatNode);
+
+ cleanupText();
+ cleanupEndTag();
+ }
+
+ /**
+ */
+ private void changeTagName(IStructuredDocumentRegion flatNode, ITextRegion region) {
+ int offset = flatNode.getStart();
+ if (offset < 0)
+ return; // error
+ NodeImpl root = (NodeImpl) this.context.getRootNode();
+ if (root == null)
+ return; // error
+ Node node = root.getNodeAt(offset);
+ if (node == null)
+ return; // error
+
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ }
+
+ ElementImpl element = (ElementImpl) node;
+ String newTagName = flatNode.getText(region);
+ if (newTagName == null || !element.matchTagName(newTagName)) {
+ // the tag name is changed
+ changeStructuredDocumentRegion(flatNode);
+ return;
+ }
+
+ // the tag name is unchanged
+ // this happens when typing spaces after the tag name
+ // do nothing, but...
+ // if it's not a change in the end tag of an element with the start
+ // tag,
+ // and case has been changed, set to element and notify
+ if (!element.hasStartTag() || StructuredDocumentRegionUtil.getFirstRegionType(flatNode) != XMLRegionContext.XML_END_TAG_OPEN) {
+ String tagName = element.getTagName();
+ if (tagName == null || !tagName.equals(newTagName)) {
+ element.setTagName(newTagName);
+ element.notifyValueChanged();
+ }
+ }
+ }
+
+ /**
+ * cleanupContext method
+ */
+ private void cleanupEndTag() {
+ Node parent = this.context.getParentNode();
+ Node next = this.context.getNextNode();
+ while (parent != null) {
+ while (next != null) {
+ if (next.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) next;
+ if (element.isEndTag()) {
+ // floating end tag
+ String tagName = element.getTagName();
+ String rootName = getFindRootName(tagName);
+ ElementImpl start = (ElementImpl) this.context.findStartTag(tagName, rootName);
+ if (start != null) {
+ insertEndTag(start);
+ // move the end tag from 'element' to 'start'
+ start.addEndTag(element);
+ removeNode(element);
+ parent = this.context.getParentNode();
+ next = this.context.getNextNode();
+ continue;
+ }
+ }
+ }
+
+ Node first = next.getFirstChild();
+ if (first != null) {
+ parent = next;
+ next = first;
+ this.context.setNextNode(next);
+ } else {
+ next = next.getNextSibling();
+ this.context.setNextNode(next);
+ }
+ }
+
+ if (parent.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) parent;
+ if (!element.hasEndTag() && element.hasStartTag() && element.getNextSibling() == null) {
+ String tagName = element.getTagName();
+ ElementImpl end = (ElementImpl) this.context.findEndTag(tagName);
+ if (end != null) {
+ // move the end tag from 'end' to 'element'
+ element.addEndTag(end);
+ removeEndTag(end);
+ this.context.setParentNode(parent); // reset context
+ continue;
+ }
+ }
+ }
+
+ next = parent.getNextSibling();
+ parent = parent.getParentNode();
+ if (next != null) {
+ this.context.setNextNode(next);
+ } else {
+ this.context.setParentNode(parent);
+ }
+ }
+ }
+
+ /**
+ */
+ private void cleanupText() {
+ Node parent = this.context.getParentNode();
+ if (parent == null)
+ return; // error
+ Node next = this.context.getNextNode();
+ Node prev = (next == null ? parent.getLastChild() : next.getPreviousSibling());
+
+ TextImpl nextText = null;
+ TextImpl prevText = null;
+ if (next != null && next.getNodeType() == Node.TEXT_NODE) {
+ nextText = (TextImpl) next;
+ }
+ if (prev != null && prev.getNodeType() == Node.TEXT_NODE) {
+ prevText = (TextImpl) prev;
+ }
+ if (nextText == null && prevText == null)
+ return;
+ if (nextText != null && prevText != null) {
+ // consecutive Text nodes created by setupContext(),
+ // concat them
+ IStructuredDocumentRegion flatNode = nextText.getStructuredDocumentRegion();
+ if (flatNode != null)
+ prevText.appendStructuredDocumentRegion(flatNode);
+ Node newNext = next.getNextSibling();
+ parent.removeChild(next);
+ next = null;
+ this.context.setNextNode(newNext);
+ }
+
+ TextImpl childText = (prevText != null ? prevText : nextText);
+ if (childText.getNextSibling() == null && childText.getPreviousSibling() == null) {
+ if (parent.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl parentElement = (ElementImpl) parent;
+ if (!parentElement.hasStartTag() && !parentElement.hasEndTag()) {
+ if (childText.isWhitespace() || childText.isInvalid()) {
+ // implicit parent is not required
+ Node newParent = parent.getParentNode();
+ if (newParent != null) {
+ Node newNext = parent.getNextSibling();
+ newParent.removeChild(parent);
+ parent.removeChild(childText);
+ newParent.insertBefore(childText, newNext);
+ if (childText == next) {
+ this.context.setNextNode(childText);
+ } else if (newNext != null) {
+ this.context.setNextNode(newNext);
+ } else {
+ this.context.setParentNode(newParent);
+ }
+ // try again
+ cleanupText();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * This routine create an Element from comment data for comment style
+ * elements, such as SSI and METADATA
+ */
+ protected Element createCommentElement(String data, boolean isJSPTag) {
+ String trimmedData = data.trim();
+ CommentElementConfiguration[] configs = CommentElementRegistry.getInstance().getConfigurations();
+ for (int iConfig = 0; iConfig < configs.length; iConfig++) {
+ CommentElementConfiguration config = configs[iConfig];
+ if ((isJSPTag && !config.acceptJSPComment()) || (!isJSPTag && !config.acceptXMLComment())) {
+ continue;
+ }
+ String[] prefixes = config.getPrefix();
+ for (int iPrefix = 0; iPrefix < prefixes.length; iPrefix++) {
+ if (trimmedData.startsWith(prefixes[iPrefix])) {
+ return config.createElement(this.document, data, isJSPTag);
+ }
+ }
+ }
+ if (this.adapter != null) {
+ return this.adapter.createCommentElement(this.document, data, isJSPTag);
+ }
+ return null;
+ }
+
+ /**
+ * This routine create an implicit Element for given parent and child,
+ * such as HTML, BODY, HEAD, and TBODY for HTML document.
+ */
+ protected Element createImplicitElement(Node parent, Node child) {
+ if (this.adapter != null) {
+ return this.adapter.createImplicitElement(this.document, parent, child);
+ }
+ return null;
+ }
+
+ /**
+ */
+ private void demoteNodes(Node root, Node newParent, Node oldParent, Node next) {
+ if (newParent.getNodeType() != Node.ELEMENT_NODE)
+ return;
+ ElementImpl newElement = (ElementImpl) newParent;
+
+ // find next
+ while (next == null) {
+ if (oldParent.getNodeType() != Node.ELEMENT_NODE)
+ return;
+ ElementImpl oldElement = (ElementImpl) oldParent;
+ if (oldElement.hasEndTag())
+ return;
+ oldParent = oldElement.getParentNode();
+ if (oldParent == null)
+ return; // error
+ next = oldElement.getNextSibling();
+ }
+
+ while (next != null) {
+ boolean done = false;
+ if (next.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl nextElement = (ElementImpl) next;
+ if (!nextElement.hasStartTag()) {
+ Node nextChild = nextElement.getFirstChild();
+ if (nextChild != null) {
+ // demote children
+ next = nextChild;
+ oldParent = nextElement;
+ continue;
+ }
+
+ if (nextElement.hasEndTag()) {
+ if (nextElement.matchEndTag(newElement)) {
+ // stop at the matched invalid end tag
+ next = nextElement.getNextSibling();
+ oldParent.removeChild(nextElement);
+ newElement.addEndTag(nextElement);
+
+ if (newElement == root)
+ return;
+ Node p = newElement.getParentNode();
+ // check if reached to top
+ if (p == null || p == oldParent || p.getNodeType() != Node.ELEMENT_NODE)
+ return;
+ newElement = (ElementImpl) p;
+ done = true;
+ }
+ } else {
+ // remove implicit element
+ next = nextElement.getNextSibling();
+ oldParent.removeChild(nextElement);
+ done = true;
+ }
+ }
+ }
+
+ if (!done) {
+ if (!canContain(newElement, next)) {
+ if (newElement == root)
+ return;
+ Node p = newElement.getParentNode();
+ // check if reached to top
+ if (p == null || p == oldParent || p.getNodeType() != Node.ELEMENT_NODE)
+ return;
+ newElement = (ElementImpl) p;
+ continue;
+ }
+
+ Node child = next;
+ next = next.getNextSibling();
+ oldParent.removeChild(child);
+ insertNode(newElement, child, null);
+ Node childParent = child.getParentNode();
+ if (childParent != newElement) {
+ newElement = (ElementImpl) childParent;
+ }
+ }
+
+ // find next parent and sibling
+ while (next == null) {
+ if (oldParent.getNodeType() != Node.ELEMENT_NODE)
+ return;
+ ElementImpl oldElement = (ElementImpl) oldParent;
+
+ // dug parent must not have children at this point
+ if (!oldElement.hasChildNodes() && !oldElement.hasStartTag()) {
+ oldParent = oldElement.getParentNode();
+ if (oldParent == null)
+ return; // error
+ next = oldElement;
+ break;
+ }
+
+ if (oldElement.hasEndTag())
+ return;
+ oldParent = oldElement.getParentNode();
+ if (oldParent == null)
+ return; // error
+ next = oldElement.getNextSibling();
+ }
+ }
+ }
+
+ /**
+ */
+ protected final XMLDocument getDocument() {
+ return this.document;
+ }
+
+ /**
+ */
+ protected String getFindRootName(String tagName) {
+ if (this.adapter != null) {
+ return this.adapter.getFindRootName(tagName);
+ }
+ return null;
+ }
+
+ /**
+ */
+ protected final XMLModel getModel() {
+ return this.model;
+ }
+
+ /**
+ * insertCDATASection method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertCDATASection(IStructuredDocumentRegion flatNode) {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+
+ CDATASectionImpl cdata = null;
+ try {
+ cdata = (CDATASectionImpl) this.document.createCDATASection(null);
+ } catch (DOMException ex) {
+ }
+ if (cdata == null) { // CDATA section might not be supported
+ insertInvalidDecl(flatNode); // regard as invalid decl
+ return;
+ }
+
+ cdata.setStructuredDocumentRegion(flatNode);
+ insertNode(cdata);
+ }
+
+ /**
+ * insertComment method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertComment(IStructuredDocumentRegion flatNode) {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+
+ String data = null;
+ boolean isJSPTag = false;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == JSP_COMMENT_OPEN) {
+ isJSPTag = true;
+ } else if (regionType == XMLRegionContext.XML_COMMENT_TEXT || regionType == JSP_COMMENT_TEXT) {
+ if (data == null) {
+ data = flatNode.getText(region);
+ }
+ }
+ }
+
+ if (data != null) {
+ ElementImpl element = (ElementImpl) createCommentElement(data, isJSPTag);
+ if (element != null) {
+ if (!isEndTag(element)) {
+ element.setStartStructuredDocumentRegion(flatNode);
+ insertStartTag(element);
+ return;
+ }
+
+ // end tag
+ element.setEndStructuredDocumentRegion(flatNode);
+
+ String tagName = element.getTagName();
+ String rootName = getFindRootName(tagName);
+ ElementImpl start = (ElementImpl) this.context.findStartTag(tagName, rootName);
+ if (start != null) { // start tag found
+ insertEndTag(start);
+ start.addEndTag(element);
+ return;
+ }
+
+ // invalid end tag
+ insertNode(element);
+ return;
+ }
+ }
+
+ CommentImpl comment = (CommentImpl) this.document.createComment(null);
+ if (comment == null)
+ return;
+ if (isJSPTag)
+ comment.setJSPTag(true);
+ comment.setStructuredDocumentRegion(flatNode);
+ insertNode(comment);
+ }
+
+ /**
+ * insertDecl method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertDecl(IStructuredDocumentRegion flatNode) {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+
+ boolean isDocType = false;
+ String name = null;
+ String publicId = null;
+ String systemId = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_DOCTYPE_DECLARATION) {
+ isDocType = true;
+ } else if (regionType == XMLRegionContext.XML_DOCTYPE_NAME) {
+ if (name == null)
+ name = flatNode.getText(region);
+ } else if (regionType == XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBREF) {
+ if (publicId == null)
+ publicId = StructuredDocumentRegionUtil.getAttrValue(flatNode, region);
+ } else if (regionType == XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSREF) {
+ if (systemId == null)
+ systemId = StructuredDocumentRegionUtil.getAttrValue(flatNode, region);
+ }
+ }
+
+ // invalid declaration
+ if (!isDocType) {
+ insertInvalidDecl(flatNode);
+ return;
+ }
+
+ DocumentTypeImpl docType = (DocumentTypeImpl) this.document.createDoctype(name);
+ if (docType == null)
+ return;
+ if (publicId != null)
+ docType.setPublicId(publicId);
+ if (systemId != null)
+ docType.setSystemId(systemId);
+ docType.setStructuredDocumentRegion(flatNode);
+ insertNode(docType);
+ }
+
+ /**
+ * insertEndTag method
+ *
+ * @param element
+ * org.w3c.dom.Element
+ */
+ private void insertEndTag(Element element) {
+ if (element == null)
+ return;
+
+ Node newParent = element.getParentNode();
+ if (newParent == null)
+ return; // error
+
+ if (!((ElementImpl) element).isContainer()) {
+ // just update context
+ Node elementNext = element.getNextSibling();
+ if (elementNext != null)
+ this.context.setNextNode(elementNext);
+ else
+ this.context.setParentNode(newParent);
+ return;
+ }
+
+ // promote children
+ Node newNext = element.getNextSibling();
+ Node oldParent = this.context.getParentNode();
+ if (oldParent == null)
+ return; // error
+ Node oldNext = this.context.getNextNode();
+ promoteNodes(element, newParent, newNext, oldParent, oldNext);
+
+ // update context
+ // re-check the next sibling
+ newNext = element.getNextSibling();
+ if (newNext != null)
+ this.context.setNextNode(newNext);
+ else
+ this.context.setParentNode(newParent);
+ }
+
+ /**
+ * insertEndTag method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertEndTag(IStructuredDocumentRegion flatNode) {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+
+ String tagName = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ if (region.getType() == XMLRegionContext.XML_TAG_NAME || region.getType() == JSP_ROOT_TAG_NAME || region.getType() == JSP_DIRECTIVE_NAME) {
+ if (tagName == null)
+ tagName = flatNode.getText(region);
+ }
+ }
+
+ if (tagName == null) { // invalid end tag
+ insertText(flatNode); // regard as invalid text
+ return;
+ }
+
+ String rootName = getFindRootName(tagName);
+ ElementImpl start = (ElementImpl) this.context.findStartTag(tagName, rootName);
+ if (start != null) { // start tag found
+ insertEndTag(start);
+ start.setEndStructuredDocumentRegion(flatNode);
+ return;
+ }
+
+ // invalid end tag
+ ElementImpl end = null;
+ try {
+ end = (ElementImpl) this.document.createElement(tagName);
+ } catch (DOMException ex) {
+ }
+ if (end == null) { // invalid end tag
+ insertText(flatNode); // regard as invalid text
+ return;
+ }
+ end.setEndStructuredDocumentRegion(flatNode);
+ insertNode(end);
+ }
+
+ /**
+ * insertEntityRef method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertEntityRef(IStructuredDocumentRegion flatNode) {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+
+ String name = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_ENTITY_REFERENCE || regionType == XMLRegionContext.XML_CHAR_REFERENCE) {
+ if (name == null)
+ name = StructuredDocumentRegionUtil.getEntityRefName(flatNode, region);
+ }
+ }
+
+ if (name == null) { // invalid entity
+ insertText(flatNode);
+ return;
+ }
+
+ String value = this.document.getCharValue(name);
+ if (value != null) { // character entity
+ TextImpl text = (TextImpl) this.context.findPreviousText();
+ if (text != null) { // existing text found
+ // do not append data
+ text.appendStructuredDocumentRegion(flatNode);
+ // notify the change
+ text.notifyValueChanged();
+ return;
+ }
+
+ // new text
+ text = (TextImpl) this.document.createTextNode(null);
+ if (text == null)
+ return;
+ text.setStructuredDocumentRegion(flatNode);
+ insertNode(text);
+ return;
+ }
+
+ // general entity reference
+ EntityReferenceImpl ref = null;
+ try {
+ ref = (EntityReferenceImpl) this.document.createEntityReference(name);
+ } catch (DOMException ex) {
+ }
+ if (ref == null) { // entity reference might not be supported
+ insertText(flatNode); // regard as invalid text
+ return;
+ }
+
+ ref.setStructuredDocumentRegion(flatNode);
+ insertNode(ref);
+ }
+
+ /**
+ * insertInvalidDecl method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertInvalidDecl(IStructuredDocumentRegion flatNode) {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+
+ ElementImpl element = null;
+ try {
+ element = (ElementImpl) this.document.createElement("!");//$NON-NLS-1$
+ } catch (DOMException ex) {
+ }
+ if (element == null) { // invalid tag
+ insertText(flatNode); // regard as invalid text
+ return;
+ }
+ element.setEmptyTag(true);
+ element.setStartStructuredDocumentRegion(flatNode);
+ insertNode(element);
+ }
+
+ /**
+ * insertJSPTag method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertJSPTag(IStructuredDocumentRegion flatNode) {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+
+ String tagName = null;
+ AttrImpl attr = null;
+ Vector attrNodes = null;
+ boolean isCloseTag = false;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == JSP_SCRIPTLET_OPEN) {
+ tagName = JSPTag.JSP_SCRIPTLET;
+ } else if (regionType == JSP_EXPRESSION_OPEN) {
+ tagName = JSPTag.JSP_EXPRESSION;
+ } else if (regionType == JSP_DECLARATION_OPEN) {
+ tagName = JSPTag.JSP_DECLARATION;
+ } else if (regionType == JSP_DIRECTIVE_OPEN) {
+ tagName = JSPTag.JSP_DIRECTIVE;
+ } else if (regionType == JSP_DIRECTIVE_NAME) {
+ tagName += '.';
+ tagName += flatNode.getText(region);
+ } else if (regionType == JSP_CLOSE) {
+ isCloseTag = true;
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+ String name = flatNode.getText(region);
+ attr = (AttrImpl) this.document.createAttribute(name);
+ if (attr != null) {
+ attr.setNameRegion(region);
+ if (attrNodes == null)
+ attrNodes = new Vector();
+ attrNodes.addElement(attr);
+ }
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+ if (attr != null) {
+ attr.setEqualRegion(region);
+ }
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+ if (attr != null) {
+ attr.setValueRegion(region);
+ attr = null;
+ }
+ }
+ }
+
+ if (tagName == null) {
+ if (isCloseTag) {
+ // close JSP tag
+ Node parent = this.context.getParentNode();
+ if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl start = (ElementImpl) parent;
+ if (start.isJSPContainer()) {
+ insertEndTag(start);
+ start.setEndStructuredDocumentRegion(flatNode);
+ return;
+ }
+ }
+ }
+ // invalid JSP tag
+ insertText(flatNode); // regard as invalid text
+ return;
+ }
+
+ ElementImpl element = null;
+ try {
+ element = (ElementImpl) this.document.createElement(tagName);
+ } catch (DOMException ex) {
+ }
+ if (element == null) { // invalid tag
+ insertText(flatNode); // regard as invalid text
+ return;
+ }
+ if (attrNodes != null) {
+ Enumeration ae = attrNodes.elements();
+ while (ae.hasMoreElements()) {
+ Attr a = (Attr) ae.nextElement();
+ if (a == null)
+ continue;
+ element.appendAttributeNode(a);
+ }
+ }
+ element.setJSPTag(true);
+ element.setStartStructuredDocumentRegion(flatNode);
+ insertStartTag(element);
+ }
+
+ /**
+ * insertNode method
+ *
+ * @param child
+ * org.w3c.dom.Node
+ */
+ private void insertNode(Node node) {
+ if (node == null)
+ return;
+ if (this.context == null)
+ return;
+
+ Node parent = this.context.getParentNode();
+ if (parent == null)
+ return;
+ Node next = this.context.getNextNode();
+ while (parent.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) parent;
+ if (canContain(element, node)) {
+ if (!element.hasStartTag() && next == element.getFirstChild()) {
+ // first child of implicit tag
+ // deletege to the parent
+ parent = element.getParentNode();
+ if (parent == null)
+ return;
+ next = element;
+ this.context.setNextNode(next);
+ continue;
+ }
+ break;
+ }
+ parent = element.getParentNode();
+ if (parent == null)
+ return;
+
+ // promote siblings
+ Node newNext = element.getNextSibling();
+ Node child = next;
+ while (child != null) {
+ Node nextChild = child.getNextSibling();
+ element.removeChild(child);
+ parent.insertBefore(child, newNext);
+ child = nextChild;
+ }
+
+ // leave the old end tag where it is
+ if (element.hasEndTag()) {
+ Element end = element.removeEndTag();
+ if (end != null) {
+ parent.insertBefore(end, newNext);
+ if (next == null)
+ next = end;
+ }
+ }
+ if (!element.hasStartTag()) {
+ // implicit element
+ if (!element.hasChildNodes()) {
+ parent.removeChild(element);
+ }
+ }
+
+ // update context
+ if (next == null)
+ next = newNext;
+ if (next != null)
+ this.context.setNextNode(next);
+ else
+ this.context.setParentNode(parent);
+ }
+
+ insertNode(parent, node, next);
+ next = node.getNextSibling();
+ if (next != null)
+ this.context.setNextNode(next);
+ else
+ this.context.setParentNode(node.getParentNode());
+ }
+
+ /**
+ */
+ private void insertNode(Node parent, Node node, Node next) {
+ while (next != null && next.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl nextElement = (ElementImpl) next;
+ if (nextElement.hasStartTag())
+ break;
+ if (!canBeImplicitTag(nextElement, node))
+ break;
+ parent = nextElement;
+ next = nextElement.getFirstChild();
+ }
+ Element implicitElement = createImplicitElement(parent, node);
+ if (implicitElement != null)
+ node = implicitElement;
+ parent.insertBefore(node, next);
+ }
+
+ /**
+ * insertPI method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertPI(IStructuredDocumentRegion flatNode) {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+
+ String target = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_PI_OPEN || regionType == XMLRegionContext.XML_PI_CLOSE)
+ continue;
+ if (target == null)
+ target = flatNode.getText(region);
+ }
+
+ ProcessingInstructionImpl pi = (ProcessingInstructionImpl) this.document.createProcessingInstruction(target, null);
+ if (pi == null)
+ return;
+ pi.setStructuredDocumentRegion(flatNode);
+ insertNode(pi);
+ }
+
+ /**
+ * insertStartTag method
+ *
+ * @param element
+ * org.w3c.dom.Element
+ */
+ private void insertStartTag(Element element) {
+ if (element == null)
+ return;
+ if (this.context == null)
+ return;
+
+ insertNode(element);
+
+ ElementImpl newElement = (ElementImpl) element;
+ if (newElement.isEmptyTag() || !newElement.isContainer())
+ return;
+
+ // demote siblings
+ Node parent = this.context.getParentNode();
+ if (parent == null)
+ return; // error
+ Node next = this.context.getNextNode();
+ demoteNodes(element, element, parent, next);
+
+ // update context
+ Node firstChild = element.getFirstChild();
+ if (firstChild != null)
+ this.context.setNextNode(firstChild);
+ else
+ this.context.setParentNode(element);
+ }
+
+ /**
+ * insertStartTag method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertStartTag(IStructuredDocumentRegion flatNode) {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+
+ String tagName = null;
+ boolean isEmptyTag = false;
+ AttrImpl attr = null;
+ Vector attrNodes = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_NAME || regionType == JSP_ROOT_TAG_NAME || regionType == JSP_DIRECTIVE_NAME) {
+ if (tagName == null)
+ tagName = flatNode.getText(region);
+ } else if (regionType == XMLRegionContext.XML_EMPTY_TAG_CLOSE) {
+ isEmptyTag = true;
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+ String name = flatNode.getText(region);
+ attr = (AttrImpl) this.document.createAttribute(name);
+ if (attr != null) {
+ attr.setNameRegion(region);
+ if (attrNodes == null)
+ attrNodes = new Vector();
+ attrNodes.addElement(attr);
+ }
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+ if (attr != null) {
+ attr.setEqualRegion(region);
+ }
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+ if (attr != null) {
+ attr.setValueRegion(region);
+ attr = null;
+ }
+ }
+ }
+
+ if (tagName == null) { // invalid start tag
+ insertText(flatNode); // regard as invalid text
+ return;
+ }
+
+ ElementImpl element = null;
+ try {
+ element = (ElementImpl) this.document.createElement(tagName);
+ } catch (DOMException ex) {
+ }
+ if (element == null) { // invalid tag
+ insertText(flatNode); // regard as invalid text
+ return;
+ }
+ if (attrNodes != null) {
+ Enumeration ae = attrNodes.elements();
+ while (ae.hasMoreElements()) {
+ Attr a = (Attr) ae.nextElement();
+ if (a == null)
+ continue;
+ element.appendAttributeNode(a);
+ }
+ }
+ if (isEmptyTag)
+ element.setEmptyTag(true);
+ element.setStartStructuredDocumentRegion(flatNode);
+ insertStartTag(element);
+ }
+
+ /**
+ * insertStructuredDocumentRegion method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertStructuredDocumentRegion(IStructuredDocumentRegion flatNode) {
+ String regionType = StructuredDocumentRegionUtil.getFirstRegionType(flatNode);
+ if (regionType == XMLRegionContext.XML_TAG_OPEN) {
+ insertStartTag(flatNode);
+ } else if (regionType == XMLRegionContext.XML_END_TAG_OPEN) {
+ insertEndTag(flatNode);
+ } else if (regionType == XMLRegionContext.XML_COMMENT_OPEN || regionType == JSP_COMMENT_OPEN) {
+ insertComment(flatNode);
+ } else if (regionType == XMLRegionContext.XML_ENTITY_REFERENCE || regionType == XMLRegionContext.XML_CHAR_REFERENCE) {
+ insertEntityRef(flatNode);
+ } else if (regionType == XMLRegionContext.XML_DECLARATION_OPEN) {
+ insertDecl(flatNode);
+ } else if (regionType == XMLRegionContext.XML_PI_OPEN) {
+ insertPI(flatNode);
+ } else if (regionType == XMLRegionContext.XML_CDATA_OPEN) {
+ insertCDATASection(flatNode);
+ } else if (regionType == JSP_SCRIPTLET_OPEN || regionType == JSP_EXPRESSION_OPEN || regionType == JSP_DECLARATION_OPEN || regionType == JSP_DIRECTIVE_OPEN || regionType == JSP_CLOSE) {
+ insertJSPTag(flatNode);
+ } else {
+ insertText(flatNode);
+ }
+ }
+
+ /**
+ * insertText method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void insertText(IStructuredDocumentRegion flatNode) {
+ TextImpl text = (TextImpl) this.context.findPreviousText();
+ if (text != null) { // existing text found
+ text.appendStructuredDocumentRegion(flatNode);
+ // notify the change
+ text.notifyValueChanged();
+ return;
+ }
+
+ // new text
+ text = (TextImpl) this.document.createTextNode(null);
+ if (text == null)
+ return;
+ text.setStructuredDocumentRegion(flatNode);
+ insertNode(text);
+ }
+
+ /**
+ */
+ protected boolean isEndTag(XMLElement element) {
+ if (this.adapter != null) {
+ return this.adapter.isEndTag(element);
+ }
+ return element.isEndTag();
+ }
+
+ /**
+ */
+ private void promoteNodes(Node root, Node newParent, Node newNext, Node oldParent, Node next) {
+ ElementImpl newElement = null;
+ if (newParent.getNodeType() == Node.ELEMENT_NODE) {
+ newElement = (ElementImpl) newParent;
+ }
+
+ Node rootParent = root.getParentNode();
+ while (oldParent != rootParent) {
+ while (next != null) {
+ boolean done = false;
+ boolean endTag = false;
+ if (next.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl nextElement = (ElementImpl) next;
+ if (!nextElement.hasStartTag()) {
+ Node nextChild = nextElement.getFirstChild();
+ if (nextChild != null) {
+ // promote children
+ next = nextChild;
+ oldParent = nextElement;
+ continue;
+ }
+
+ if (nextElement.hasEndTag()) {
+ if (nextElement.matchEndTag(newElement)) {
+ endTag = true;
+ }
+ } else {
+ // remove implicit element
+ next = nextElement.getNextSibling();
+ oldParent.removeChild(nextElement);
+ done = true;
+ }
+ }
+ }
+
+ if (!done) {
+ if (!endTag && newElement != null && !canContain(newElement, next)) {
+ newParent = newElement.getParentNode();
+ if (newParent == null)
+ return; // error
+ Node elementNext = newElement.getNextSibling();
+ // promote siblings
+ promoteNodes(newElement, newParent, elementNext, newElement, newNext);
+ newNext = newElement.getNextSibling();
+ if (newParent.getNodeType() == Node.ELEMENT_NODE) {
+ newElement = (ElementImpl) newParent;
+ } else {
+ newElement = null;
+ }
+ continue;
+ }
+
+ Node child = next;
+ next = next.getNextSibling();
+ oldParent.removeChild(child);
+ insertNode(newParent, child, newNext);
+ Node childParent = child.getParentNode();
+ if (childParent != newParent) {
+ newParent = childParent;
+ newElement = (ElementImpl) newParent;
+ newNext = child.getNextSibling();
+ }
+ }
+ }
+
+ if (oldParent.getNodeType() != Node.ELEMENT_NODE)
+ return;
+ ElementImpl oldElement = (ElementImpl) oldParent;
+ oldParent = oldElement.getParentNode();
+ if (oldParent == null)
+ return; // error
+ next = oldElement.getNextSibling();
+
+ if (oldElement.hasEndTag()) {
+ Element end = null;
+ if (!oldElement.hasChildNodes() && !oldElement.hasStartTag()) {
+ oldParent.removeChild(oldElement);
+ end = oldElement;
+ } else {
+ end = oldElement.removeEndTag();
+ }
+ if (end != null) {
+ insertNode(newParent, end, newNext);
+ Node endParent = end.getParentNode();
+ if (endParent != newParent) {
+ newParent = endParent;
+ newElement = (ElementImpl) newParent;
+ newNext = end.getNextSibling();
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * removeEndTag method
+ *
+ * @param element
+ * org.w3c.dom.Element
+ */
+ private void removeEndTag(Element element) {
+ if (element == null)
+ return;
+ if (this.context == null)
+ return;
+
+ Node parent = element.getParentNode();
+ if (parent == null)
+ return; // error
+
+ if (!((ElementImpl) element).isContainer()) {
+ // just update context
+ Node elementNext = element.getNextSibling();
+ if (elementNext != null)
+ this.context.setNextNode(elementNext);
+ else
+ this.context.setParentNode(parent);
+ return;
+ }
+
+ // demote siblings
+ Node next = element.getNextSibling();
+ ElementImpl newElement = (ElementImpl) element;
+ // find new parent
+ for (Node last = newElement.getLastChild(); last != null; last = last.getLastChild()) {
+ if (last.getNodeType() != Node.ELEMENT_NODE)
+ break;
+ ElementImpl lastElement = (ElementImpl) last;
+ if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
+ break;
+ newElement = lastElement;
+ }
+ Node lastChild = newElement.getLastChild();
+ demoteNodes(element, newElement, parent, next);
+
+ // update context
+ Node newNext = null;
+ if (lastChild != null)
+ newNext = lastChild.getNextSibling();
+ else
+ newNext = newElement.getFirstChild();
+ if (newNext != null)
+ this.context.setNextNode(newNext);
+ else
+ this.context.setParentNode(newElement);
+ }
+
+ /**
+ * Remove the specified node if it is no longer required implicit tag with
+ * remaining child nodes promoted.
+ */
+ private Element removeImplicitElement(Node parent) {
+ if (parent == null)
+ return null;
+ if (parent.getNodeType() != Node.ELEMENT_NODE)
+ return null;
+ ElementImpl element = (ElementImpl) parent;
+ if (!element.isImplicitTag())
+ return null;
+ if (canBeImplicitTag(element))
+ return null;
+
+ Node elementParent = element.getParentNode();
+ if (elementParent == null)
+ return null; // error
+ Node firstChild = element.getFirstChild();
+ Node child = firstChild;
+ Node elementNext = element.getNextSibling();
+ while (child != null) {
+ Node nextChild = child.getNextSibling();
+ element.removeChild(child);
+ elementParent.insertBefore(child, elementNext);
+ child = nextChild;
+ }
+
+ // reset context
+ if (this.context.getParentNode() == element) {
+ Node oldNext = this.context.getNextNode();
+ if (oldNext != null) {
+ this.context.setNextNode(oldNext);
+ } else {
+ if (elementNext != null) {
+ this.context.setNextNode(elementNext);
+ } else {
+ this.context.setParentNode(elementParent);
+ }
+ }
+ } else if (this.context.getNextNode() == element) {
+ if (firstChild != null) {
+ this.context.setNextNode(firstChild);
+ } else {
+ if (elementNext != null) {
+ this.context.setNextNode(elementNext);
+ } else {
+ this.context.setParentNode(elementParent);
+ }
+ }
+ }
+
+ removeNode(element);
+ return element;
+ }
+
+ /**
+ * removeNode method
+ *
+ * @param node
+ * org.w3c.dom.Node
+ */
+ private void removeNode(Node node) {
+ if (node == null)
+ return;
+ if (this.context == null)
+ return;
+
+ Node parent = node.getParentNode();
+ if (parent == null)
+ return;
+ Node next = node.getNextSibling();
+ Node prev = node.getPreviousSibling();
+
+ // update context
+ Node oldParent = this.context.getParentNode();
+ if (node == oldParent) {
+ if (next != null)
+ this.context.setNextNode(next);
+ else
+ this.context.setParentNode(parent);
+ } else {
+ Node oldNext = this.context.getNextNode();
+ if (node == oldNext) {
+ this.context.setNextNode(next);
+ }
+ }
+
+ parent.removeChild(node);
+
+ if (removeImplicitElement(parent) != null)
+ return;
+
+ // demote sibling
+ if (prev != null && prev.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl newElement = (ElementImpl) prev;
+ if (!newElement.hasEndTag() && !newElement.isEmptyTag() && newElement.isContainer()) {
+ // find new parent
+ for (Node last = newElement.getLastChild(); last != null; last = last.getLastChild()) {
+ if (last.getNodeType() != Node.ELEMENT_NODE)
+ break;
+ ElementImpl lastElement = (ElementImpl) last;
+ if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
+ break;
+ newElement = lastElement;
+ }
+ Node lastChild = newElement.getLastChild();
+ demoteNodes(prev, newElement, parent, next);
+
+ // update context
+ Node newNext = null;
+ if (lastChild != null)
+ newNext = lastChild.getNextSibling();
+ else
+ newNext = newElement.getFirstChild();
+ if (newNext != null)
+ this.context.setNextNode(newNext);
+ else
+ this.context.setParentNode(newElement);
+ }
+ }
+ }
+
+ /**
+ * removeStartTag method
+ *
+ * @param element
+ * org.w3c.dom.Element
+ */
+ private void removeStartTag(Element element) {
+ if (element == null)
+ return;
+ if (this.context == null)
+ return;
+
+ // for implicit tag
+ ElementImpl oldElement = (ElementImpl) element;
+ if (canBeImplicitTag(oldElement)) {
+ Node newParent = null;
+ Node prev = oldElement.getPreviousSibling();
+ if (prev != null && prev.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl prevElement = (ElementImpl) prev;
+ if (!prevElement.hasEndTag()) {
+ if (prevElement.hasStartTag() || prevElement.matchTagName(oldElement.getTagName())) {
+ newParent = prevElement;
+ }
+ }
+ }
+ if (newParent == null) {
+ // this element should stay as implicit tag
+ // just remove all attributes
+ oldElement.removeStartTag();
+
+ // update context
+ Node child = oldElement.getFirstChild();
+ if (child != null) {
+ this.context.setNextNode(child);
+ } else if (oldElement.hasEndTag()) {
+ this.context.setParentNode(oldElement);
+ }
+ return;
+ }
+ }
+ // for comment tag
+ if (oldElement.isCommentTag())
+ oldElement.removeStartTag();
+
+ // promote children
+ Node elementParent = element.getParentNode();
+ Node parent = elementParent;
+ if (parent == null)
+ return;
+ Node first = element.getFirstChild();
+ Node firstElement = null; // for the case first is removed as end tag
+ if (first != null) {
+ // find new parent for children
+ ElementImpl newElement = null;
+ for (Node last = element.getPreviousSibling(); last != null; last = last.getLastChild()) {
+ if (last.getNodeType() != Node.ELEMENT_NODE)
+ break;
+ ElementImpl lastElement = (ElementImpl) last;
+ if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
+ break;
+ newElement = lastElement;
+ }
+ Node next = first;
+ if (newElement != null) {
+ while (next != null) {
+ if (!newElement.hasEndTag() && newElement.hasStartTag() && next.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl nextElement = (ElementImpl) next;
+ if (!nextElement.hasStartTag() && nextElement.hasEndTag() && nextElement.matchEndTag(newElement)) {
+ // stop at the matched invalid end tag
+ Node elementChild = nextElement.getFirstChild();
+ while (elementChild != null) {
+ Node nextChild = elementChild.getNextSibling();
+ nextElement.removeChild(elementChild);
+ newElement.appendChild(elementChild);
+ elementChild = nextChild;
+ }
+
+ next = nextElement.getNextSibling();
+ element.removeChild(nextElement);
+ newElement.addEndTag(nextElement);
+ if (nextElement == first)
+ firstElement = newElement;
+
+ Node newParent = newElement.getParentNode();
+ if (newParent == parent)
+ break;
+ if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
+ break; // error
+ newElement = (ElementImpl) newParent;
+ continue;
+ }
+ }
+ if (!canContain(newElement, next)) {
+ Node newParent = newElement.getParentNode();
+ if (newParent == parent)
+ break;
+ if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
+ break; // error
+ newElement = (ElementImpl) newParent;
+ continue;
+ }
+ Node child = next;
+ next = next.getNextSibling();
+ element.removeChild(child);
+ newElement.appendChild(child);
+ }
+ newElement = null;
+ }
+ if (parent.getNodeType() == Node.ELEMENT_NODE) {
+ newElement = (ElementImpl) parent;
+ }
+ while (next != null) {
+ if (newElement == null || canContain(newElement, next)) {
+ Node child = next;
+ next = next.getNextSibling();
+ element.removeChild(child);
+ parent.insertBefore(child, element);
+ continue;
+ }
+
+ parent = newElement.getParentNode();
+ if (parent == null)
+ return;
+
+ // promote siblings
+ Node newNext = newElement.getNextSibling();
+ Node child = element;
+ while (child != null) {
+ Node nextChild = child.getNextSibling();
+ newElement.removeChild(child);
+ parent.insertBefore(child, newNext);
+ child = nextChild;
+ }
+
+ // leave the old end tag where it is
+ if (newElement.hasEndTag()) {
+ Element end = newElement.removeEndTag();
+ if (end != null) {
+ parent.insertBefore(end, newNext);
+ }
+ }
+ if (!newElement.hasStartTag()) {
+ // implicit element
+ if (!newElement.hasChildNodes()) {
+ parent.removeChild(newElement);
+ }
+ }
+
+ if (parent.getNodeType() == Node.ELEMENT_NODE) {
+ newElement = (ElementImpl) parent;
+ } else {
+ newElement = null;
+ }
+ }
+ }
+
+ Node newNext = element;
+ Node startElement = null; // for the case element is removed as end
+ // tag
+ if (oldElement.hasEndTag()) {
+ // find new parent for invalid end tag and siblings
+ ElementImpl newElement = null;
+ for (Node last = element.getPreviousSibling(); last != null; last = last.getLastChild()) {
+ if (last.getNodeType() != Node.ELEMENT_NODE)
+ break;
+ ElementImpl lastElement = (ElementImpl) last;
+ if (lastElement.hasEndTag() || lastElement.isEmptyTag() || !lastElement.isContainer())
+ break;
+ newElement = lastElement;
+ }
+ if (newElement != null) {
+ // demote invalid end tag and sibling
+ Node next = element;
+ while (next != null) {
+ if (!newElement.hasEndTag() && newElement.hasStartTag() && next.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl nextElement = (ElementImpl) next;
+ if (!nextElement.hasStartTag() && nextElement.hasEndTag() && nextElement.matchEndTag(newElement)) {
+ // stop at the matched invalid end tag
+ Node elementChild = nextElement.getFirstChild();
+ while (elementChild != null) {
+ Node nextChild = elementChild.getNextSibling();
+ nextElement.removeChild(elementChild);
+ newElement.appendChild(elementChild);
+ elementChild = nextChild;
+ }
+
+ next = nextElement.getNextSibling();
+ parent.removeChild(nextElement);
+ newElement.addEndTag(nextElement);
+ if (nextElement == newNext)
+ startElement = newElement;
+
+ Node newParent = newElement.getParentNode();
+ if (newParent == parent)
+ break;
+ if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
+ break; // error
+ newElement = (ElementImpl) newParent;
+ continue;
+ }
+ }
+ if (!canContain(newElement, next)) {
+ Node newParent = newElement.getParentNode();
+ if (newParent == parent)
+ break;
+ if (newParent == null || newParent.getNodeType() != Node.ELEMENT_NODE)
+ break; // error
+ newElement = (ElementImpl) newParent;
+ continue;
+ }
+ Node child = next;
+ next = next.getNextSibling();
+ parent.removeChild(child);
+ if (child == oldElement) {
+ if (!oldElement.isCommentTag()) {
+ // clone (re-create) end tag
+ Element end = oldElement.removeEndTag();
+ if (end != null) {
+ child = end;
+ newNext = end;
+ }
+ }
+ }
+ newElement.appendChild(child);
+ }
+ } else {
+ if (!oldElement.isCommentTag()) {
+ // clone (re-create) end tag
+ Element end = oldElement.removeEndTag();
+ if (end != null) {
+ parent.insertBefore(end, oldElement);
+ parent.removeChild(oldElement);
+ newNext = end;
+ }
+ }
+ }
+ } else {
+ newNext = oldElement.getNextSibling();
+ parent.removeChild(oldElement);
+ }
+
+ // update context
+ Node oldParent = this.context.getParentNode();
+ Node oldNext = this.context.getNextNode();
+ if (element == oldParent) {
+ if (oldNext != null) {
+ this.context.setNextNode(oldNext); // reset for new parent
+ } else if (newNext != null) {
+ this.context.setNextNode(newNext);
+ } else {
+ this.context.setParentNode(parent);
+ }
+ } else if (element == oldNext) {
+ if (firstElement != null) {
+ this.context.setParentNode(firstElement);
+ } else if (first != null) {
+ this.context.setNextNode(first);
+ } else if (startElement != null) {
+ this.context.setParentNode(startElement);
+ } else {
+ this.context.setNextNode(newNext);
+ }
+ }
+
+ removeImplicitElement(elementParent);
+ }
+
+ /**
+ * removeStructuredDocumentRegion method
+ *
+ * @param oldStructuredDocumentRegion
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void removeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+ NodeImpl next = (NodeImpl) this.context.getNextNode();
+ if (next != null) {
+ short nodeType = next.getNodeType();
+ if (nodeType != Node.ELEMENT_NODE) {
+ IStructuredDocumentRegion flatNode = next.getStructuredDocumentRegion();
+ if (flatNode == oldStructuredDocumentRegion) {
+ removeNode(next);
+ return;
+ }
+ if (nodeType != Node.TEXT_NODE) {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ if (flatNode == null) {
+ // this is the case for empty Text
+ // remove and continue
+ removeNode(next);
+ removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+ TextImpl text = (TextImpl) next;
+ boolean isShared = text.isSharingStructuredDocumentRegion(oldStructuredDocumentRegion);
+ if (isShared) {
+ // make sure there is next Text node sharing this
+ TextImpl nextText = (TextImpl) this.context.findNextText();
+ if (nextText == null || !nextText.hasStructuredDocumentRegion(oldStructuredDocumentRegion)) {
+ isShared = false;
+ }
+ }
+ oldStructuredDocumentRegion = text.removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ if (oldStructuredDocumentRegion == null) {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ if (text.getStructuredDocumentRegion() == null) {
+ // this is the case partial IStructuredDocumentRegion is
+ // removed
+ removeNode(text);
+ } else {
+ // notify the change
+ text.notifyValueChanged();
+ }
+ // if shared, continue to remove IStructuredDocumentRegion
+ // from them
+ if (isShared)
+ removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+
+ ElementImpl element = (ElementImpl) next;
+ if (element.hasStartTag()) {
+ IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
+ if (flatNode != oldStructuredDocumentRegion) {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ if (element.hasEndTag() || element.hasChildNodes()) {
+ element.setStartStructuredDocumentRegion(null);
+ removeStartTag(element);
+ } else {
+ removeNode(element);
+ }
+ } else {
+ Node child = element.getFirstChild();
+ if (child != null) {
+ this.context.setNextNode(child);
+ removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+
+ if (!element.hasEndTag()) {
+ // implicit element
+ removeNode(element);
+ removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+
+ IStructuredDocumentRegion flatNode = element.getEndStructuredDocumentRegion();
+ if (flatNode != oldStructuredDocumentRegion) {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ removeNode(element);
+ }
+ return;
+ }
+
+ Node parent = this.context.getParentNode();
+ if (parent == null || parent.getNodeType() != Node.ELEMENT_NODE) {
+ throw new StructuredDocumentRegionManagementException();
+ }
+
+ ElementImpl end = (ElementImpl) parent;
+ if (end.hasEndTag()) {
+ IStructuredDocumentRegion flatNode = end.getEndStructuredDocumentRegion();
+ if (flatNode != oldStructuredDocumentRegion) {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ if (!end.hasStartTag() && !end.hasChildNodes()) {
+ this.context.setNextNode(end);
+ removeNode(end);
+ } else {
+ end.setEndStructuredDocumentRegion(null);
+ removeEndTag(end);
+ }
+ return;
+ }
+
+ next = (NodeImpl) end.getNextSibling();
+ if (next != null) {
+ this.context.setNextNode(next);
+ removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+
+ parent = (NodeImpl) end.getParentNode();
+ if (parent != null) {
+ this.context.setParentNode(parent);
+ removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+ }
+
+ /**
+ * replaceRegions method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ * @param newRegions
+ * java.util.Vector
+ * @param oldRegions
+ * java.util.Vector
+ */
+ void replaceRegions(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
+ if (flatNode == null)
+ return;
+ if (this.document == null)
+ return;
+ this.context = new XMLModelContext(this.document);
+
+ // optimize typical cases
+ String regionType = StructuredDocumentRegionUtil.getFirstRegionType(flatNode);
+ if (regionType == XMLRegionContext.XML_TAG_OPEN) {
+ changeStartTag(flatNode, newRegions, oldRegions);
+ } else if (regionType == XMLRegionContext.XML_END_TAG_OPEN) {
+ changeEndTag(flatNode, newRegions, oldRegions);
+ } else {
+ changeStructuredDocumentRegion(flatNode);
+ }
+ }
+
+ /**
+ * replaceStructuredDocumentRegions method
+ *
+ * @param newStructuredDocumentRegions
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegionList
+ * @param oldStructuredDocumentRegions
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegionList
+ */
+ void replaceStructuredDocumentRegions(IStructuredDocumentRegionList newStructuredDocumentRegions, IStructuredDocumentRegionList oldStructuredDocumentRegions) {
+ if (this.document == null)
+ return;
+ this.context = new XMLModelContext(this.document);
+
+ int newCount = (newStructuredDocumentRegions != null ? newStructuredDocumentRegions.getLength() : 0);
+ int oldCount = (oldStructuredDocumentRegions != null ? oldStructuredDocumentRegions.getLength() : 0);
+
+ if (oldCount > 0) {
+ setupContext(oldStructuredDocumentRegions.item(0));
+ // Node startParent = this.context.getParentNode();
+
+ Enumeration e = oldStructuredDocumentRegions.elements();
+ while (e.hasMoreElements()) {
+ IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e.nextElement();
+ if (flatNode == null)
+ continue;
+ removeStructuredDocumentRegion(flatNode);
+ }
+ } else {
+ if (newCount == 0)
+ return;
+ setupContext(newStructuredDocumentRegions.item(0));
+ }
+ // make sure the parent is set to deepest level
+ // when end tag has been removed
+ this.context.setLast();
+
+ if (newCount > 0) {
+ Enumeration e = newStructuredDocumentRegions.elements();
+ while (e.hasMoreElements()) {
+ IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e.nextElement();
+ if (flatNode == null)
+ continue;
+ insertStructuredDocumentRegion(flatNode);
+ }
+ }
+
+ cleanupText();
+ cleanupEndTag();
+ }
+
+ /**
+ * setupContext method
+ *
+ * @param flatNode
+ * com.ibm.sed.structuredDocument.IStructuredDocumentRegion
+ */
+ private void setupContext(IStructuredDocumentRegion startStructuredDocumentRegion) {
+ int offset = startStructuredDocumentRegion.getStart();
+ if (offset < 0)
+ return;
+ NodeImpl root = (NodeImpl) this.context.getRootNode();
+ if (root == null)
+ return;
+
+ if (offset == 0) {
+ // at the beggining of document
+ Node child = root.getFirstChild();
+ if (child != null)
+ this.context.setNextNode(child);
+ else
+ this.context.setParentNode(root);
+ return;
+ }
+
+ NodeImpl node = (NodeImpl) root.getNodeAt(offset);
+ if (node == null) {
+ // might be at the end of document
+ this.context.setParentNode(root);
+ this.context.setLast();
+ return;
+ }
+
+ if (offset == node.getStartOffset()) {
+ this.context.setNextNode(node);
+ return;
+ }
+
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ TextImpl text = (TextImpl) node;
+ Text nextText = text.splitText(startStructuredDocumentRegion);
+ // notify the change
+ text.notifyValueChanged();
+ if (nextText == null)
+ return; // error
+ this.context.setNextNode(nextText);
+ return;
+ }
+
+ for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (offset >= ((NodeImpl) child).getEndOffset())
+ continue;
+ this.context.setNextNode(child);
+ return;
+ }
+ this.context.setParentNode(node);
+ this.context.setLast();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelUpdater.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelUpdater.java
new file mode 100644
index 0000000000..c9cab984c8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelUpdater.java
@@ -0,0 +1,1647 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.document;
+
+
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.document.JSPTag;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLGenerator;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+/**
+ * XMLModelUpdater class
+ */
+public class XMLModelUpdater implements XMLJSPRegionContexts {
+ private int diff = 0;
+ private int gapLength = 0;
+ private int gapOffset = 0;
+ private IStructuredDocumentRegion gapStructuredDocumentRegion = null;
+ private XMLGenerator generator = null;
+ private XMLModelImpl model = null;
+ private NodeImpl nextNode = null;
+ private NodeImpl parentNode = null;
+
+ protected XMLModelUpdater(XMLModelImpl model) {
+ super();
+
+ if (model != null) {
+ this.model = model;
+ this.generator = model.getGenerator();
+ }
+ }
+
+ /**
+ * changeAttrValue method
+ *
+ * @param attrNode
+ * org.w3c.dom.Attr
+ */
+ private void changeAttrName(Attr attrNode) {
+ if (attrNode == null)
+ return;
+
+ AttrImpl attr = (AttrImpl) attrNode;
+ ElementImpl element = (ElementImpl) attr.getOwnerElement();
+ if (element == null)
+ return;
+
+ if (element.isCommentTag()) {
+ changeStartTag(element);
+ return;
+ }
+
+ int offset = element.getStartOffset();
+ int start = offset;
+ int end = offset;
+
+ String name = attr.getName();
+ if (name == null)
+ name = new String();
+ ITextRegion nameRegion = attr.getNameRegion();
+ if (nameRegion == null)
+ return; // error
+ start += nameRegion.getStart();
+ // use getTextEnd() because getEnd() may include the tailing spaces
+ end += nameRegion.getTextEnd();
+
+ replaceSource(name, start, end);
+ }
+
+ /**
+ * changeAttrValue method
+ *
+ * @param attrNode
+ * org.w3c.dom.Attr
+ */
+ private void changeAttrValue(Attr attrNode) {
+ if (attrNode == null)
+ return;
+
+ AttrImpl attr = (AttrImpl) attrNode;
+ ElementImpl element = (ElementImpl) attr.getOwnerElement();
+ if (element == null)
+ return;
+
+ if (element.isCommentTag()) {
+ changeStartTag(element);
+ return;
+ }
+
+ int offset = element.getStartOffset();
+ int start = offset;
+ int end = offset;
+
+ String value = null;
+ ITextRegion valueRegion = attr.getValueRegion();
+ if (valueRegion != null) {
+ char quote = 0; // no quote preference
+ // DW: 4/16/2003 due to change in structuredDocument ... we need a
+ // flatnode to
+ // get at region values. For now I'll assume this is always the
+ // first
+ // flatnode .. may need to make smarter later (e.g. to search for
+ // the flatnode that this.valueRegion belongs to.
+ IStructuredDocumentRegion documentRegion = element.getFirstStructuredDocumentRegion();
+ String oldValue = documentRegion.getText(valueRegion);
+ if (oldValue != null && oldValue.length() > 0) {
+ char firstChar = oldValue.charAt(0);
+ if (firstChar == '"' || firstChar == '\'') {
+ quote = firstChar;
+ }
+ }
+
+ ITextRegion startRegion = valueRegion;
+
+ value = this.generator.generateAttrValue(attr, quote);
+ if (value == null) {
+ value = new String();
+ // remove equal too
+ ITextRegion equalRegion = attr.getEqualRegion();
+ if (equalRegion != null)
+ startRegion = equalRegion;
+ }
+ attr.setValueRegion(valueRegion); // reset value
+
+ start += startRegion.getStart();
+ // use getTextEnd() because getEnd() may include the tailing
+ // spaces
+ end += valueRegion.getTextEnd();
+ } else {
+ ITextRegion equalRegion = attr.getEqualRegion();
+
+ value = this.generator.generateAttrValue(attr);
+ if (value == null) {
+ if (equalRegion == null)
+ return; // nothng to do
+ value = new String();
+ // remove equal
+ start += equalRegion.getStart();
+ end += equalRegion.getTextEnd();
+ } else {
+ if (equalRegion != null) {
+ // use getTextEnd() because getEnd() may include the
+ // tailing spaces
+ start += equalRegion.getTextEnd();
+ } else {
+ ITextRegion nameRegion = attr.getNameRegion();
+ if (nameRegion == null)
+ return; // must never happen
+ // use getTextEnd() because getEnd() may include the
+ // tailing spaces
+ start += nameRegion.getTextEnd();
+ value = '=' + value;
+ }
+ end = start;
+ }
+ }
+
+ replaceSource(value, start, end);
+ }
+
+ /**
+ */
+ void changeEndTag(Element element) {
+ String source = this.generator.generateEndTag(element);
+ if (source == null)
+ return;
+ int length = source.length();
+ if (length == 0)
+ return;
+
+ ElementImpl impl = (ElementImpl) element;
+ int offset = impl.getEndStartOffset();
+ int start = offset;
+ int end = offset;
+ if (impl.hasEndTag()) {
+ end = impl.getEndOffset();
+ this.gapStructuredDocumentRegion = impl.getEndStructuredDocumentRegion();
+ impl.setEndStructuredDocumentRegion(new StructuredDocumentRegionProxy(offset, length));
+ }
+
+ replaceSource(source, start, end);
+ }
+
+ /**
+ * changeName method
+ *
+ * @param node
+ * org.w3c.dom.Node
+ */
+ void changeName(Node node) {
+ if (node == null)
+ return;
+ if (getStructuredDocument() == null)
+ return;
+
+ // support changing name of attribute for setPrefix()
+ short nodeType = node.getNodeType();
+ if (nodeType == Node.ATTRIBUTE_NODE) {
+ changeAttrName((Attr) node);
+ return;
+ }
+
+ // not supported
+ return;
+ }
+
+ void changeRegion(IStructuredDocumentRegion flatNode, ITextRegion region) {
+ // future_TODO: optimize
+
+ NodeImpl root = (NodeImpl) this.model.getDocument();
+ this.parentNode = root;
+ this.nextNode = (NodeImpl) root.getFirstChild();
+
+ removeGapStructuredDocumentRegion(flatNode);
+ insertGapStructuredDocumentRegionBefore(flatNode.getStart());
+ changeStructuredDocumentRegion(flatNode);
+ insertGapStructuredDocumentRegionAfter(flatNode.getEnd());
+ }
+
+ /**
+ * This is a fallback method to regenerate the start tag.
+ */
+ void changeStartTag(Element element) {
+ if (element == null)
+ return;
+ ElementImpl impl = (ElementImpl) element;
+
+ if (!impl.hasStartTag() && !impl.hasEndTag()) {
+ // need to generate the start and the end tags
+ Node parent = element.getParentNode();
+ if (parent != null) {
+ replaceChild(parent, element, element);
+ return;
+ }
+ // else error
+ }
+
+ String source = this.generator.generateStartTag(element);
+ if (source == null)
+ return;
+ int length = source.length();
+ if (length == 0)
+ return;
+
+ int offset = impl.getStartOffset();
+ int start = offset;
+ int end = offset;
+ if (impl.hasStartTag()) {
+ end = impl.getStartEndOffset();
+ this.gapStructuredDocumentRegion = impl.getStartStructuredDocumentRegion();
+ }
+ impl.setStartStructuredDocumentRegion(new StructuredDocumentRegionProxy(offset, length));
+
+ replaceSource(source, start, end);
+ }
+
+ private void changeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+ if (oldStructuredDocumentRegion == null)
+ return; // error
+ if (this.parentNode == null)
+ return; // error
+
+ int oldOffset = oldStructuredDocumentRegion.getStart();
+ int oldEnd = oldStructuredDocumentRegion.getEnd();
+ boolean isEndTag = false;
+
+ // find owner node
+ NodeImpl ownerNode = null;
+ while (this.parentNode != null) {
+ if (this.nextNode != null) {
+ IStructuredDocumentRegion nextStructuredDocumentRegion = this.nextNode.getStructuredDocumentRegion();
+ if (nextStructuredDocumentRegion != null) {
+ if (nextStructuredDocumentRegion == oldStructuredDocumentRegion) {
+ ownerNode = this.nextNode;
+ break;
+ }
+ int nextOffset = nextStructuredDocumentRegion.getStart();
+ if (nextOffset == oldOffset) { // found
+ ownerNode = this.nextNode;
+ break;
+ }
+ if (this.nextNode.getNodeType() == Node.TEXT_NODE) {
+ TextImpl text = (TextImpl) this.nextNode;
+ if (text.hasStructuredDocumentRegion(oldStructuredDocumentRegion)) {
+ ownerNode = this.nextNode;
+ break;
+ }
+ int nextEnd = nextStructuredDocumentRegion.getEnd();
+ if (nextOffset < oldEnd && nextEnd > oldOffset) {
+ ownerNode = this.nextNode;
+ break;
+ }
+ }
+ }
+
+ Node child = this.nextNode.getFirstChild();
+ if (child != null) {
+ this.parentNode = this.nextNode;
+ this.nextNode = (NodeImpl) child;
+ continue;
+ }
+
+ if (this.nextNode.getNodeType() == Node.ELEMENT_NODE) {
+ this.parentNode = this.nextNode;
+ this.nextNode = null;
+ continue;
+ }
+
+ this.nextNode = (NodeImpl) this.nextNode.getNextSibling();
+ if (this.nextNode != null)
+ continue;
+ }
+
+ if (this.parentNode.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) this.parentNode;
+ IStructuredDocumentRegion endStructuredDocumentRegion = element.getEndStructuredDocumentRegion();
+ if (endStructuredDocumentRegion != null) {
+ if (endStructuredDocumentRegion == oldStructuredDocumentRegion) {
+ ownerNode = this.parentNode;
+ isEndTag = true;
+ break;
+ }
+ int endOffset = endStructuredDocumentRegion.getStart();
+ if (endOffset == oldOffset) { // found
+ ownerNode = this.parentNode;
+ isEndTag = true;
+ break;
+ }
+ }
+ }
+
+ this.nextNode = (NodeImpl) this.parentNode.getNextSibling();
+ this.parentNode = (NodeImpl) this.parentNode.getParentNode();
+ }
+ if (ownerNode == null)
+ throw new StructuredDocumentRegionManagementException();
+
+ short nodeType = ownerNode.getNodeType();
+ if (nodeType == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) ownerNode;
+ if (isEndTag) {
+ element.setEndStructuredDocumentRegion(oldStructuredDocumentRegion);
+ } else {
+ element.setStartStructuredDocumentRegion(oldStructuredDocumentRegion);
+ updateAttrRegions(element, oldStructuredDocumentRegion);
+ }
+ } else if (nodeType == Node.TEXT_NODE) {
+ TextImpl text = (TextImpl) ownerNode;
+
+ IStructuredDocumentRegion flatNode = text.getStructuredDocumentRegion();
+ if (flatNode == oldStructuredDocumentRegion) {
+ int newOffset = oldOffset;
+ int newEnd = oldEnd;
+ if (oldOffset == this.gapOffset) {
+ newOffset += this.diff;
+ } else {
+ newEnd = this.gapOffset;
+ }
+ int newLength = newEnd - newOffset;
+ IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(newOffset, newLength, oldStructuredDocumentRegion);
+ text.setStructuredDocumentRegion(newStructuredDocumentRegion);
+
+ if (oldEnd > newEnd) {
+ this.nextNode = (NodeImpl) text.getNextSibling();
+ changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ }
+ return;
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+ int offset = proxy.getOffset();
+ int end = offset + proxy.getLength();
+ if (proxy.getStructuredDocumentRegion() == null) {
+ if (offset == oldOffset && end == oldEnd) {
+ text.setStructuredDocumentRegion(oldStructuredDocumentRegion);
+ } else {
+ if (end > oldEnd) {
+ StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer();
+ container.appendStructuredDocumentRegion(oldStructuredDocumentRegion);
+ proxy.setOffset(oldEnd);
+ proxy.setLength(end - oldEnd);
+ container.appendStructuredDocumentRegion(proxy);
+ text.setStructuredDocumentRegion(container);
+ } else {
+ proxy.setStructuredDocumentRegion(oldStructuredDocumentRegion);
+
+ if (end < oldEnd) { // to be shared
+ this.nextNode = (NodeImpl) text.getNextSibling();
+ changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ }
+ }
+ }
+ return;
+ }
+
+ if (offset >= this.gapOffset) {
+ proxy.setOffset(offset + this.diff);
+ end += this.diff;
+ }
+ if (end < oldEnd) { // to be shared
+ this.nextNode = (NodeImpl) text.getNextSibling();
+ changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+ } else if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == null)
+ continue; // error
+ if (content == oldStructuredDocumentRegion) {
+ int newOffset = oldOffset;
+ int newEnd = oldEnd;
+ if (oldOffset == this.gapOffset) {
+ newOffset += this.diff;
+ } else {
+ newEnd = this.gapOffset;
+ }
+ int newLength = newEnd - newOffset;
+ IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(newOffset, newLength, oldStructuredDocumentRegion);
+ container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+
+ if (oldEnd > newEnd) { // to be shared
+ this.nextNode = (NodeImpl) text.getNextSibling();
+ changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ }
+ return;
+ }
+
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ int offset = proxy.getOffset();
+ int end = offset + proxy.getLength();
+ if (end <= oldOffset)
+ continue;
+ if (proxy.getStructuredDocumentRegion() == null) {
+ if (offset == oldOffset && end == oldEnd) {
+ container.replaceStructuredDocumentRegion(oldStructuredDocumentRegion, i);
+ } else {
+ if (end > oldEnd) {
+ container.insertStructuredDocumentRegion(oldStructuredDocumentRegion, i);
+ proxy.setOffset(oldEnd);
+ proxy.setLength(end - oldEnd);
+ } else {
+ proxy.setStructuredDocumentRegion(oldStructuredDocumentRegion);
+
+ if (end < oldEnd) { // to be shared
+ this.nextNode = (NodeImpl) text.getNextSibling();
+ changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ }
+ }
+ }
+ return;
+ }
+
+ if (offset >= this.gapOffset) {
+ proxy.setOffset(offset + this.diff);
+ end += this.diff;
+ }
+ if (end < oldEnd) { // to be shared
+ this.nextNode = (NodeImpl) text.getNextSibling();
+ changeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+ }
+ }
+ } else {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ } else {
+ ownerNode.setStructuredDocumentRegion(oldStructuredDocumentRegion);
+ }
+ }
+
+ /**
+ */
+ private void changeTextData(Text text) {
+ if (text == null)
+ return;
+
+ String source = this.generator.generateSource(text);
+ if (source == null)
+ source = new String();
+ int length = source.length();
+
+ TextImpl impl = (TextImpl) text;
+ int start = impl.getStartOffset();
+ int end = impl.getEndOffset();
+ int offset = start;
+
+ // make sure previous tag is closed
+ Node prev = text.getPreviousSibling();
+ if (prev != null) {
+ String preTag = getCloseTag((XMLNode) prev);
+ if (preTag != null && preTag.length() > 0) {
+ offset += preTag.length();
+ source = preTag + source;
+ }
+ } else {
+ Node parent = text.getParentNode();
+ if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) parent;
+ String preTag = getStartCloseTag(element);
+ if (preTag != null && preTag.length() > 0) {
+ offset += preTag.length();
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(preTag);
+ buffer.append(source);
+ if (text.getNextSibling() == null && !element.hasEndTag() && (element.isJSPContainer() || element.isCDATAContainer())) {
+ // need to generate the end tag
+ String postTag = this.generator.generateEndTag(element);
+ if (postTag != null) {
+ int postLength = postTag.length();
+ if (postLength > 0) {
+ buffer.append(postTag);
+ int postOffset = offset + length;
+ IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy(postOffset, postLength);
+ element.setEndStructuredDocumentRegion(flatNode);
+ }
+ }
+ }
+ source = buffer.toString();
+ }
+ }
+ }
+
+ this.gapStructuredDocumentRegion = impl.getStructuredDocumentRegion();
+ IStructuredDocumentRegion newStructuredDocumentRegion = null;
+ if (length > 0)
+ newStructuredDocumentRegion = new StructuredDocumentRegionProxy(offset, length);
+ impl.setStructuredDocumentRegion(newStructuredDocumentRegion);
+
+ replaceSource(source, start, end);
+ }
+
+ /**
+ * changeValue method
+ *
+ * @param node
+ * org.w3c.dom.Node
+ */
+ void changeValue(Node node) {
+ if (node == null)
+ return;
+ if (getStructuredDocument() == null)
+ return;
+
+ short nodeType = node.getNodeType();
+ if (nodeType == Node.TEXT_NODE) {
+ changeTextData((Text) node);
+ return;
+ }
+ if (nodeType == Node.ATTRIBUTE_NODE) {
+ changeAttrValue((Attr) node);
+ return;
+ }
+ if (nodeType == Node.ELEMENT_NODE) {
+ changeStartTag((Element) node);
+ return;
+ }
+
+ String source = this.generator.generateSource(node);
+ if (source == null)
+ source = new String();
+ int length = source.length();
+
+ NodeImpl impl = (NodeImpl) node;
+ int start = impl.getStartOffset();
+ int end = impl.getEndOffset();
+
+ this.gapStructuredDocumentRegion = impl.getStructuredDocumentRegion();
+ IStructuredDocumentRegion flatNode = null;
+ if (length > 0)
+ flatNode = new StructuredDocumentRegionProxy(start, length);
+ impl.setStructuredDocumentRegion(flatNode);
+
+ replaceSource(source, start, end);
+ }
+
+ /**
+ */
+ private String getAttrValueClose(XMLElement element) {
+ if (element == null)
+ return null;
+
+ IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
+ if (flatNode == null)
+ return null;
+ ITextRegion region = StructuredDocumentRegionUtil.getLastRegion(flatNode);
+ if (region == null || region.getType() != XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+ return null;
+ String value = flatNode.getText(region);
+ if (value == null)
+ return null;
+ int length = value.length();
+ if (length == 0)
+ return null;
+
+ // check open JSP tag
+ boolean closeJSPTag = false;
+ int offset = value.indexOf(JSPTag.TAG_OPEN);
+ while (offset >= 0) {
+ offset = value.indexOf(JSPTag.TAG_CLOSE, offset + 2);
+ if (offset < 0) {
+ closeJSPTag = true;
+ break;
+ }
+ offset = value.indexOf(JSPTag.TAG_OPEN, offset + 2);
+ }
+
+ // check quote
+ boolean closeQuote = false;
+ char firstChar = value.charAt(0);
+ if (firstChar == '"' || firstChar == '\'') {
+ if (closeJSPTag || length == 1 || value.charAt(length - 1) != firstChar) {
+ closeQuote = true;
+ }
+ }
+
+ if (!closeJSPTag && !closeQuote)
+ return null;
+
+ StringBuffer buffer = new StringBuffer();
+ if (closeJSPTag)
+ buffer.append(JSPTag.TAG_CLOSE);
+ if (closeQuote)
+ buffer.append(firstChar);
+ return buffer.toString();
+ }
+
+ /**
+ * Gather close tags recursively.
+ */
+ private String getCloseTag(XMLNode node) {
+ if (node == null || node.isClosed())
+ return null;
+
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ return this.generator.generateCloseTag(node);
+ }
+
+ ElementImpl element = (ElementImpl) node;
+ if (element.hasEndTag()) {
+ // end tag is not closed
+ return this.generator.generateCloseTag(element);
+ }
+
+ // no end tag
+ int offset = element.getEndOffset();
+ StringBuffer buffer = new StringBuffer();
+
+ XMLNode lastChild = (XMLNode) element.getLastChild();
+ if (lastChild == null) {
+ if (!element.isStartTagClosed()) {
+ if (element.preferEmptyTag())
+ element.setEmptyTag(true);
+ String closeTag = getStartCloseTag(element);
+ if (closeTag != null) {
+ int length = closeTag.length();
+ if (length > 0) {
+ buffer.append(closeTag);
+ offset += length;
+ }
+ }
+ }
+ } else {
+ String closeTag = getCloseTag(lastChild);
+ if (closeTag != null) {
+ int length = closeTag.length();
+ if (length > 0) {
+ buffer.append(closeTag);
+ offset += length;
+ }
+ }
+ }
+
+ String endTag = this.generator.generateEndTag(element);
+ if (endTag != null) {
+ int length = endTag.length();
+ if (length > 0) {
+ buffer.append(endTag);
+ IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy(offset, length);
+ element.setEndStructuredDocumentRegion(flatNode);
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ */
+ private String getStartCloseTag(XMLElement element) {
+ if (element == null || element.isStartTagClosed())
+ return null;
+
+ StringBuffer buffer = new StringBuffer();
+ String attrValueClose = getAttrValueClose(element);
+ if (attrValueClose != null)
+ buffer.append(attrValueClose);
+ String closeTag = this.generator.generateCloseTag(element);
+ if (closeTag != null)
+ buffer.append(closeTag);
+ return buffer.toString();
+ }
+
+ private IStructuredDocument getStructuredDocument() {
+ if (model == null)
+ return null;
+ return model.getStructuredDocument();
+ }
+
+ /**
+ */
+ void initialize() {
+ this.gapStructuredDocumentRegion = null;
+ this.gapOffset = 0;
+ this.gapLength = 0;
+ this.diff = 0;
+ this.parentNode = null;
+ this.nextNode = null;
+ }
+
+ private void insertGapStructuredDocumentRegionAfter(int endOffset) {
+ if (this.gapStructuredDocumentRegion == null)
+ return;
+
+ if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) this.gapStructuredDocumentRegion;
+ IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+ if (flatNode != null)
+ insertStructuredDocumentRegion(flatNode);
+ } else if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) this.gapStructuredDocumentRegion;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == null)
+ continue;
+ if (content.getStart() < endOffset)
+ continue;
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+ if (flatNode != null)
+ insertStructuredDocumentRegion(flatNode);
+ } else {
+ insertStructuredDocumentRegion(content);
+ }
+ }
+ } else {
+ insertStructuredDocumentRegion(this.gapStructuredDocumentRegion);
+ }
+ }
+
+ private void insertGapStructuredDocumentRegionBefore(int startOffset) {
+ if (this.gapStructuredDocumentRegion == null)
+ return;
+
+ if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) this.gapStructuredDocumentRegion;
+ IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+ if (flatNode != null)
+ insertStructuredDocumentRegion(flatNode);
+ } else if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) this.gapStructuredDocumentRegion;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == null)
+ continue;
+ if (content.getStart() >= startOffset)
+ return;
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+ if (flatNode != null)
+ insertStructuredDocumentRegion(flatNode);
+ } else {
+ insertStructuredDocumentRegion(content);
+ }
+ }
+ } else {
+ insertStructuredDocumentRegion(this.gapStructuredDocumentRegion);
+ }
+ }
+
+ /**
+ */
+ private void insertStructuredDocumentRegion(IStructuredDocumentRegion newStructuredDocumentRegion) {
+ if (newStructuredDocumentRegion == null)
+ return; // error
+ if (this.parentNode == null)
+ return; // error
+
+ int newOffset = newStructuredDocumentRegion.getStart();
+ int newEnd = newStructuredDocumentRegion.getEnd();
+ boolean isEndTag = false;
+
+ // find owner node
+ NodeImpl ownerNode = null;
+ while (this.parentNode != null) {
+ if (this.nextNode != null) {
+ IStructuredDocumentRegion nextStructuredDocumentRegion = this.nextNode.getStructuredDocumentRegion();
+ if (nextStructuredDocumentRegion != null) {
+ int nextOffset = nextStructuredDocumentRegion.getStart();
+ if (nextOffset == newOffset) { // found
+ ownerNode = this.nextNode;
+ break;
+ }
+ if (this.nextNode.getNodeType() == Node.TEXT_NODE) {
+ int nextEnd = nextStructuredDocumentRegion.getEnd();
+ if (nextOffset < newEnd && nextEnd > newOffset) {
+ ownerNode = this.nextNode;
+ break;
+ }
+ }
+ }
+
+ Node child = this.nextNode.getFirstChild();
+ if (child != null) {
+ this.parentNode = this.nextNode;
+ this.nextNode = (NodeImpl) child;
+ continue;
+ }
+
+ if (this.nextNode.getNodeType() == Node.ELEMENT_NODE) {
+ this.parentNode = this.nextNode;
+ this.nextNode = null;
+ continue;
+ }
+
+ this.nextNode = (NodeImpl) this.nextNode.getNextSibling();
+ if (this.nextNode != null)
+ continue;
+ }
+
+ if (this.parentNode.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) this.parentNode;
+ IStructuredDocumentRegion endStructuredDocumentRegion = element.getEndStructuredDocumentRegion();
+ if (endStructuredDocumentRegion != null) {
+ int endOffset = endStructuredDocumentRegion.getStart();
+ if (endOffset == newOffset) { // found
+ ownerNode = this.parentNode;
+ isEndTag = true;
+ break;
+ }
+ }
+ }
+
+ this.nextNode = (NodeImpl) this.parentNode.getNextSibling();
+ this.parentNode = (NodeImpl) this.parentNode.getParentNode();
+ }
+ if (ownerNode == null)
+ throw new StructuredDocumentRegionManagementException();
+
+ short nodeType = ownerNode.getNodeType();
+ if (nodeType == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) ownerNode;
+ if (isEndTag) {
+ element.setEndStructuredDocumentRegion(newStructuredDocumentRegion);
+ } else {
+ element.setStartStructuredDocumentRegion(newStructuredDocumentRegion);
+ updateAttrRegions(element, newStructuredDocumentRegion);
+ }
+ } else if (nodeType == Node.TEXT_NODE) {
+ TextImpl text = (TextImpl) ownerNode;
+ IStructuredDocumentRegion oldStructuredDocumentRegion = text.getStructuredDocumentRegion();
+ if (oldStructuredDocumentRegion == null) {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ int oldOffset = oldStructuredDocumentRegion.getStart();
+ int oldEnd = oldStructuredDocumentRegion.getEnd();
+ if (oldOffset == newOffset && oldEnd == newEnd) {
+ text.setStructuredDocumentRegion(newStructuredDocumentRegion);
+ return;
+ }
+
+ if (oldStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) oldStructuredDocumentRegion;
+ if (oldEnd > newEnd) {
+ StructuredDocumentRegionContainer container = new StructuredDocumentRegionContainer();
+ if (oldOffset == newOffset) {
+ container.appendStructuredDocumentRegion(newStructuredDocumentRegion);
+ } else {
+ StructuredDocumentRegionProxy newProxy = new StructuredDocumentRegionProxy();
+ newProxy.setOffset(oldOffset);
+ newProxy.setLength(newEnd - oldOffset);
+ newProxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+ container.appendStructuredDocumentRegion(newProxy);
+ }
+ proxy.setOffset(newEnd);
+ proxy.setLength(oldEnd - newEnd);
+ container.appendStructuredDocumentRegion(proxy);
+ text.setStructuredDocumentRegion(container);
+ } else {
+ proxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+
+ if (oldEnd < newEnd) { // to be shared
+ this.nextNode = (NodeImpl) text.getNextSibling();
+ insertStructuredDocumentRegion(newStructuredDocumentRegion);
+ }
+ }
+ return;
+ }
+
+ if (oldStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) oldStructuredDocumentRegion;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == null)
+ continue; // error
+ int offset = content.getStart();
+ int end = content.getEnd();
+ if (end <= newOffset)
+ continue;
+ if (offset == newOffset && end == newEnd) {
+ container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+ return;
+ }
+
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ if (end > newEnd) {
+ if (offset == newOffset) {
+ container.insertStructuredDocumentRegion(newStructuredDocumentRegion, i);
+ } else {
+ StructuredDocumentRegionProxy newProxy = new StructuredDocumentRegionProxy();
+ newProxy.setOffset(offset);
+ newProxy.setLength(newEnd - offset);
+ newProxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+ container.insertStructuredDocumentRegion(newProxy, i);
+ }
+ proxy.setOffset(newEnd);
+ proxy.setLength(end - newEnd);
+ return;
+ } else {
+ proxy.setStructuredDocumentRegion(newStructuredDocumentRegion);
+ if (end == newEnd)
+ return;
+ }
+ }
+ }
+
+ if (oldEnd < newEnd) { // to be shared
+ this.nextNode = (NodeImpl) text.getNextSibling();
+ insertStructuredDocumentRegion(newStructuredDocumentRegion);
+ }
+ return;
+ } else {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ } else {
+ ownerNode.setStructuredDocumentRegion(newStructuredDocumentRegion);
+ }
+ }
+
+ private void removeGapStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+ if (this.gapStructuredDocumentRegion == null)
+ return;
+
+ if (this.gapStructuredDocumentRegion == oldStructuredDocumentRegion) {
+ this.gapStructuredDocumentRegion = null;
+ return;
+ }
+
+ if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) this.gapStructuredDocumentRegion;
+ IStructuredDocumentRegion flatNode = proxy.getStructuredDocumentRegion();
+ if (flatNode == oldStructuredDocumentRegion)
+ this.gapStructuredDocumentRegion = null;
+ } else if (this.gapStructuredDocumentRegion instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) this.gapStructuredDocumentRegion;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == null)
+ continue;
+ if (content == oldStructuredDocumentRegion) {
+ if (count > 1)
+ container.removeStructuredDocumentRegion(i);
+ else
+ this.gapStructuredDocumentRegion = null;
+ return;
+ }
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+ if (count > 1)
+ container.removeStructuredDocumentRegion(i);
+ else
+ this.gapStructuredDocumentRegion = null;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private void removeStructuredDocumentRegion(IStructuredDocumentRegion oldStructuredDocumentRegion) {
+ if (oldStructuredDocumentRegion == null)
+ return; // error
+ if (this.parentNode == null)
+ return; // error
+
+ int gapEnd = this.gapOffset + this.gapLength;
+ int oldOffset = oldStructuredDocumentRegion.getStart();
+ int oldEnd = oldStructuredDocumentRegion.getEnd();
+ if (oldOffset >= this.gapOffset && oldEnd <= gapEnd)
+ return; // do nothing
+ int oldLength = oldEnd - oldOffset;
+ if (oldOffset >= gapEnd)
+ oldOffset += this.diff;
+
+ // find owner node
+ NodeImpl ownerNode = null;
+ ElementImpl ownerEndTag = null;
+ TextImpl ownerText = null;
+ while (this.parentNode != null) {
+ if (this.nextNode != null) {
+ if (this.nextNode.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+ ownerNode = this.nextNode;
+ break;
+ }
+ if (this.nextNode.getNodeType() == Node.TEXT_NODE) {
+ TextImpl text = (TextImpl) this.nextNode;
+ if (text.hasStructuredDocumentRegion(oldStructuredDocumentRegion)) {
+ ownerNode = this.nextNode;
+ ownerText = text;
+ break;
+ }
+ }
+
+ Node child = this.nextNode.getFirstChild();
+ if (child != null) {
+ this.parentNode = this.nextNode;
+ this.nextNode = (NodeImpl) child;
+ continue;
+ }
+
+ if (this.nextNode.getNodeType() == Node.ELEMENT_NODE) {
+ this.parentNode = this.nextNode;
+ this.nextNode = null;
+ continue;
+ }
+
+ this.nextNode = (NodeImpl) this.nextNode.getNextSibling();
+ if (this.nextNode != null)
+ continue;
+ }
+
+ if (this.parentNode.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) this.parentNode;
+ if (element.getEndStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+ ownerNode = this.parentNode;
+ ownerEndTag = element;
+ break;
+ }
+ }
+
+ this.nextNode = (NodeImpl) this.parentNode.getNextSibling();
+ this.parentNode = (NodeImpl) this.parentNode.getParentNode();
+ }
+ if (ownerNode == null)
+ throw new StructuredDocumentRegionManagementException();
+
+ if (ownerText != null) {
+ IStructuredDocumentRegion flatNode = ownerText.getStructuredDocumentRegion();
+ if (flatNode == oldStructuredDocumentRegion) {
+ IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(oldOffset, oldLength);
+ ownerText.setStructuredDocumentRegion(newStructuredDocumentRegion);
+ return;
+ }
+
+ if (flatNode instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) flatNode;
+ if (proxy.getStructuredDocumentRegion() != oldStructuredDocumentRegion) {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ int offset = proxy.getOffset();
+ int end = offset + proxy.getLength();
+ if (offset >= this.gapOffset) {
+ proxy.setOffset(offset + this.diff);
+ }
+ proxy.setStructuredDocumentRegion(null);
+ if (end < oldEnd && (end < this.gapOffset || oldEnd > gapEnd)) { // has
+ // shared
+ removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+ } else if (flatNode instanceof StructuredDocumentRegionContainer) {
+ StructuredDocumentRegionContainer container = (StructuredDocumentRegionContainer) flatNode;
+ int count = container.getStructuredDocumentRegionCount();
+ for (int i = 0; i < count; i++) {
+ IStructuredDocumentRegion content = container.getStructuredDocumentRegion(i);
+ if (content == null)
+ continue; // error
+ if (content == oldStructuredDocumentRegion) {
+ IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(oldOffset, oldLength);
+ container.replaceStructuredDocumentRegion(newStructuredDocumentRegion, i);
+ return;
+ }
+
+ if (content instanceof StructuredDocumentRegionProxy) {
+ StructuredDocumentRegionProxy proxy = (StructuredDocumentRegionProxy) content;
+ if (proxy.getStructuredDocumentRegion() == oldStructuredDocumentRegion) {
+ int offset = proxy.getOffset();
+ int end = offset + proxy.getLength();
+ if (offset >= this.gapOffset) {
+ proxy.setOffset(offset + this.diff);
+ }
+ proxy.setStructuredDocumentRegion(null);
+ if (end < oldEnd && (end < this.gapOffset || oldEnd > gapEnd)) { // has
+ // shared
+ removeStructuredDocumentRegion(oldStructuredDocumentRegion);
+ return;
+ }
+ }
+ }
+ }
+ } else {
+ throw new StructuredDocumentRegionManagementException();
+ }
+ } else {
+ IStructuredDocumentRegion newStructuredDocumentRegion = new StructuredDocumentRegionProxy(oldOffset, oldLength);
+ if (ownerEndTag != null) {
+ ownerEndTag.setEndStructuredDocumentRegion(newStructuredDocumentRegion);
+ } else {
+ ownerNode.setStructuredDocumentRegion(newStructuredDocumentRegion);
+ }
+ }
+ }
+
+ /**
+ * replaceAttr method
+ *
+ * @param ownerElement
+ * org.w3c.dom.Element
+ * @param newAttr
+ * org.w3c.dom.Attr
+ * @param oldAttr
+ * org.w3c.dom.Attr
+ */
+ void replaceAttr(Element ownerElement, Attr newAttr, Attr oldAttr) {
+ if (ownerElement == null)
+ return;
+ if (getStructuredDocument() == null)
+ return;
+
+ ElementImpl element = (ElementImpl) ownerElement;
+ if (!element.hasStartTag()) {
+ changeStartTag(element);
+ return;
+ }
+ if (element.isCommentTag()) {
+ changeStartTag(element);
+ return;
+ }
+
+ int offset = element.getStartOffset();
+ int start = offset;
+ int end = offset;
+
+ boolean insertSpace = false;
+ String attrValueClose = null;
+ if (oldAttr != null) {
+ AttrImpl impl = (AttrImpl) oldAttr;
+ ITextRegion nameRegion = impl.getNameRegion();
+ if (nameRegion == null)
+ return; // must never happen
+ ITextRegion lastRegion = impl.getValueRegion();
+ if (lastRegion != null) {
+ end += lastRegion.getEnd();
+ } else {
+ lastRegion = impl.getEqualRegion();
+ if (lastRegion != null) {
+ end += lastRegion.getEnd();
+ } else {
+ end += nameRegion.getEnd();
+ lastRegion = nameRegion;
+ }
+ }
+ // check there are extra space before the last attribute
+ IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
+ if (flatNode == null)
+ return; // must never happen
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return; // must never happen
+ ITextRegion prevRegion = null;
+ ITextRegion nextRegion = null;
+ for (int i = 0; i < regions.size(); i++) {
+ ITextRegion region = regions.get(i);
+ if (region == nameRegion) {
+ if (i > 0) {
+ prevRegion = regions.get(i - 1);
+ }
+ }
+ if (region == lastRegion) {
+ if (i + 1 < regions.size()) {
+ nextRegion = regions.get(i + 1);
+ }
+ break;
+ }
+ }
+ boolean isLastAttr = false;
+ if (nextRegion != null) {
+ String regionType = nextRegion.getType();
+ if (regionType == XMLRegionContext.XML_TAG_CLOSE || regionType == XMLRegionContext.XML_EMPTY_TAG_CLOSE || regionType == JSP_CLOSE || regionType == JSP_DIRECTIVE_CLOSE) {
+ isLastAttr = true;
+ }
+ }
+ if (isLastAttr && prevRegion != null) {
+ start += prevRegion.getTextEnd();
+ } else {
+ start += nameRegion.getStart();
+ }
+
+ // impl.resetRegions(ownerElement);
+ impl.resetRegions(element);
+ } else { // append attribute
+ IStructuredDocumentRegion flatNode = element.getStartStructuredDocumentRegion();
+ if (flatNode == null)
+ return; // must never happen
+
+ attrValueClose = getAttrValueClose(element);
+ if (attrValueClose != null && attrValueClose.length() > 0) {
+ insertSpace = true;
+ start = flatNode.getEndOffset();
+ end = start;
+ } else {
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return; // must never happen
+ int attrStart = 0;
+ for (int i = regions.size() - 1; i >= 0; i--) {
+ ITextRegion region = regions.get(i);
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_CLOSE || regionType == XMLRegionContext.XML_EMPTY_TAG_CLOSE || regionType == JSP_CLOSE || regionType == JSP_DIRECTIVE_CLOSE)
+ continue;
+ int regionEnd = region.getEnd();
+ if (regionEnd == region.getTextEnd())
+ insertSpace = true;
+ attrStart = regionEnd;
+ break;
+ }
+ if (attrStart == 0)
+ return; // not found, must never happen
+ start += attrStart;
+ end = start;
+ }
+ }
+
+ String source = null;
+ if (newAttr != null) {
+ int size = 2;
+ if (attrValueClose != null)
+ size += attrValueClose.length();
+ String name = this.generator.generateAttrName(newAttr);
+ if (name != null)
+ size += name.length();
+ String value = this.generator.generateAttrValue(newAttr);
+ if (value != null)
+ size += value.length();
+ StringBuffer buffer = new StringBuffer(size);
+ if (attrValueClose != null)
+ buffer.append(attrValueClose);
+ if (insertSpace)
+ buffer.append(' ');
+ buffer.append(name);
+ if (value != null) {
+ buffer.append('=');
+ buffer.append(value);
+ }
+ source = buffer.toString();
+ }
+
+ replaceSource(source, start, end);
+ }
+
+ /**
+ * replaceChild method
+ *
+ * @param parentNode
+ * org.w3c.dom.Node
+ * @param newChild
+ * org.w3c.dom.Node
+ * @param oldChild
+ * org.w3c.dom.Node
+ */
+ void replaceChild(Node parentNode, Node newChild, Node oldChild) {
+ if (parentNode == null)
+ return;
+ if (newChild == null && oldChild == null)
+ return;
+ if (getStructuredDocument() == null)
+ return;
+
+ int start = 0;
+ int end = 0;
+ String preTag = null;
+ String postTag = null;
+ ElementImpl postElement = null;
+ if (oldChild != null) {
+ NodeImpl node = (NodeImpl) oldChild;
+ start = node.getStartOffset();
+ end = node.getEndOffset();
+ if (oldChild.getNodeType() == Node.TEXT_NODE) {
+ this.gapStructuredDocumentRegion = node.getStructuredDocumentRegion();
+ }
+ node.resetStructuredDocumentRegions(); // reset values from
+ // IStructuredDocumentRegion
+ } else {
+ NodeImpl prev = (NodeImpl) newChild.getPreviousSibling();
+ if (prev != null) {
+ start = prev.getEndOffset();
+ end = start;
+ preTag = getCloseTag(prev);
+ } else {
+ // first child
+ NodeImpl next = (NodeImpl) newChild.getNextSibling();
+ if (next != null) {
+ start = next.getStartOffset();
+ end = start;
+ if (parentNode.getNodeType() == Node.ELEMENT_NODE) {
+ preTag = getStartCloseTag((XMLElement) parentNode);
+ }
+ } else {
+ // newly having a child
+ if (parentNode.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) parentNode;
+ if (element.isEmptyTag()) { // empty tag format
+ // need to generate the start and the end tags
+ end = element.getEndOffset();
+ start = end - 2; // for "/>"
+ element.setEmptyTag(false);
+ preTag = this.generator.generateCloseTag(element);
+ postTag = this.generator.generateEndTag(element);
+ postElement = element;
+ } else if (!element.hasStartTag()) {
+ start = element.getStartOffset();
+ end = start;
+ // invalid end tag or implicit tag
+ // need to generate the start tag
+ preTag = this.generator.generateStartTag(element);
+ if (preTag != null) {
+ int length = preTag.length();
+ if (length > 0) {
+ IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy(start, length);
+ element.setStartStructuredDocumentRegion(flatNode);
+ }
+ }
+ if (!element.hasEndTag()) {
+ // implicit tag
+ // need to generate the end tags
+ postTag = this.generator.generateEndTag(element);
+ postElement = element;
+ }
+ } else {
+ start = element.getStartEndOffset();
+ end = start;
+ preTag = getStartCloseTag(element);
+ if (preTag != null && preTag.length() > 0) {
+ if (!element.hasEndTag() && (element.isJSPContainer() || element.isCDATAContainer())) {
+ // need to generate the end tag
+ postTag = this.generator.generateEndTag(element);
+ postElement = element;
+ }
+ }
+ }
+ }
+ // else might DOCUMENT_NODE, start and end are 0
+ }
+ }
+ }
+
+ String source = null;
+ if (newChild != null) {
+ StringBuffer buffer = new StringBuffer();
+ int offset = start;
+ if (preTag != null) {
+ int length = preTag.length();
+ if (length > 0) {
+ offset += length;
+ buffer.append(preTag);
+ }
+ }
+
+ NodeImpl node = (NodeImpl) newChild;
+ while (node != null) {
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) node;
+ if (element.preferEmptyTag())
+ element.setEmptyTag(true);
+ IStructuredDocumentRegion flatNode = null;
+ String startTag = this.generator.generateStartTag(element);
+ if (startTag != null) {
+ int length = startTag.length();
+ if (length > 0) {
+ buffer.append(startTag);
+ flatNode = new StructuredDocumentRegionProxy(offset, length);
+ offset += length;
+ }
+ }
+ element.setStartStructuredDocumentRegion(flatNode);
+ } else {
+ String content = this.generator.generateSource(node);
+ if (content == null)
+ content = new String();
+ int length = content.length();
+ IStructuredDocumentRegion flatNode = null;
+ if (length > 0) {
+ buffer.append(content);
+ flatNode = new StructuredDocumentRegionProxy(offset, length);
+ offset += length;
+ }
+ node.setStructuredDocumentRegion(flatNode);
+ }
+
+ NodeImpl child = (NodeImpl) node.getFirstChild();
+ if (child != null) {
+ node = child;
+ continue;
+ }
+
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ ElementImpl element = (ElementImpl) node;
+ IStructuredDocumentRegion flatNode = null;
+ String endTag = this.generator.generateEndTag(element);
+ if (endTag != null) {
+ int length = endTag.length();
+ if (length > 0) {
+ buffer.append(endTag);
+ flatNode = new StructuredDocumentRegionProxy(offset, length);
+ offset += length;
+ }
+ }
+ element.setEndStructuredDocumentRegion(flatNode);
+ }
+
+ while (node != null) {
+ if (node == newChild) {
+ node = null;
+ break;
+ }
+ NodeImpl next = (NodeImpl) node.getNextSibling();
+ if (next != null) {
+ node = next;
+ break;
+ }
+
+ node = (NodeImpl) node.getParentNode();
+ if (node.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+ ElementImpl element = (ElementImpl) node;
+ IStructuredDocumentRegion flatNode = null;
+ String endTag = this.generator.generateEndTag(element);
+ if (endTag != null) {
+ int length = endTag.length();
+ if (length > 0) {
+ buffer.append(endTag);
+ flatNode = new StructuredDocumentRegionProxy(offset, length);
+ offset += length;
+ }
+ }
+ element.setEndStructuredDocumentRegion(flatNode);
+ }
+ }
+
+ if (postTag != null) {
+ int length = postTag.length();
+ if (length > 0) {
+ buffer.append(postTag);
+ if (postElement != null) {
+ IStructuredDocumentRegion flatNode = new StructuredDocumentRegionProxy(offset, length);
+ postElement.setEndStructuredDocumentRegion(flatNode);
+ }
+ }
+ }
+ source = buffer.toString();
+ }
+
+ if (start == end && (source == null || source.length() == 0)) {
+ // no thing changed
+ return;
+ }
+
+ replaceSource(source, start, end);
+ }
+
+ void replaceRegions(IStructuredDocumentRegion flatNode, ITextRegionList newRegions, ITextRegionList oldRegions) {
+ // future_TODO: optimize
+
+ NodeImpl root = (NodeImpl) this.model.getDocument();
+ this.parentNode = root;
+ this.nextNode = (NodeImpl) root.getFirstChild();
+
+ removeGapStructuredDocumentRegion(flatNode);
+ insertGapStructuredDocumentRegionBefore(flatNode.getStart());
+ changeStructuredDocumentRegion(flatNode);
+ insertGapStructuredDocumentRegionAfter(flatNode.getEnd());
+ }
+
+ /**
+ * Wraps IStructuredDocumentRegion.replaceText() and sets contextual
+ * information.
+ */
+ private void replaceSource(String source, int start, int end) {
+ int inserted = 0;
+ if (source == null)
+ source = new String();
+ else
+ inserted = source.length();
+ int removed = end - start;
+ if (inserted == 0 && removed == 0)
+ return;
+
+ this.gapOffset = start;
+ this.gapLength = removed;
+ this.diff = inserted - removed;
+ // Note: due to bug
+ // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=3619
+ // for now assume "ignore readonly" region is ok -- assume DOM itself
+ // checks if
+ // ok to insert or not. In reality, we may have to make or "contains"
+ // method more
+ // better. Or, we may have to "perculate up" the parameter for clients
+ // to tell us programatically
+ // that its ok to insert/format in a read-only region.
+ getStructuredDocument().replaceText(this.model, this.gapOffset, this.gapLength, source, true);
+ }
+
+ void replaceStructuredDocumentRegions(IStructuredDocumentRegionList newStructuredDocumentRegions, IStructuredDocumentRegionList oldStructuredDocumentRegions) {
+ NodeImpl root = (NodeImpl) this.model.getDocument();
+
+ if (oldStructuredDocumentRegions != null) {
+ this.parentNode = root;
+ this.nextNode = (NodeImpl) root.getFirstChild();
+
+ Enumeration e = oldStructuredDocumentRegions.elements();
+ while (e.hasMoreElements()) {
+ IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e.nextElement();
+ if (flatNode == null)
+ continue;
+ removeStructuredDocumentRegion(flatNode);
+ removeGapStructuredDocumentRegion(flatNode);
+ }
+ }
+
+ if (newStructuredDocumentRegions != null) {
+ this.parentNode = root;
+ this.nextNode = (NodeImpl) root.getFirstChild();
+
+ IStructuredDocumentRegion lastStructuredDocumentRegion = null;
+ Enumeration e = newStructuredDocumentRegions.elements();
+ while (e.hasMoreElements()) {
+ IStructuredDocumentRegion flatNode = (IStructuredDocumentRegion) e.nextElement();
+ if (flatNode == null)
+ continue;
+ if (lastStructuredDocumentRegion == null)
+ insertGapStructuredDocumentRegionBefore(flatNode.getStart());
+ insertStructuredDocumentRegion(flatNode);
+ lastStructuredDocumentRegion = flatNode;
+ }
+ if (lastStructuredDocumentRegion != null) {
+ insertGapStructuredDocumentRegionAfter(lastStructuredDocumentRegion.getEnd());
+ } else {
+ insertGapStructuredDocumentRegionBefore(this.gapOffset);
+ // make sure to restore all backuped StructuredDocumentRegions
+ insertGapStructuredDocumentRegionAfter(this.gapOffset);
+ }
+ } else {
+ this.parentNode = root;
+ this.nextNode = (NodeImpl) root.getFirstChild();
+
+ insertGapStructuredDocumentRegionBefore(this.gapOffset);
+ // make sure to restore all backuped StructuredDocumentRegions
+ insertGapStructuredDocumentRegionAfter(this.gapOffset);
+ }
+ }
+
+ /**
+ */
+ private void updateAttrRegions(Element element, IStructuredDocumentRegion flatNode) {
+
+ // update attributes
+ ITextRegionList regions = flatNode.getRegions();
+ if (regions == null)
+ return;
+ NamedNodeMap attributes = element.getAttributes();
+ if (attributes == null)
+ return;
+ int index = -1;
+ AttrImpl attr = null;
+ Iterator e = regions.iterator();
+ while (e.hasNext()) {
+ ITextRegion region = (ITextRegion) e.next();
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+ attr = (AttrImpl) attributes.item(++index);
+ if (attr != null) {
+ attr.setNameRegion(region);
+ // reset other regions
+ attr.setEqualRegion(null);
+ attr.setValueRegion(null);
+ }
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+ if (attr != null)
+ attr.setEqualRegion(region);
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+ if (attr != null) {
+ attr.setValueRegion(region);
+ attr = null;
+ }
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/filebuffers/DocumentFactoryForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/filebuffers/DocumentFactoryForXML.java
new file mode 100644
index 0000000000..549752a77f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/filebuffers/DocumentFactoryForXML.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.filebuffers;
+
+import org.eclipse.core.filebuffers.IDocumentFactory;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.document.StructuredDocumentFactory;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+
+
+
+public class DocumentFactoryForXML implements IDocumentFactory {
+
+ public DocumentFactoryForXML() {
+ super();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.filebuffers.IDocumentFactory#createDocument()
+ */
+ public IDocument createDocument() {
+ IStructuredDocument structuredDocument = StructuredDocumentFactory.getNewStructuredDocumentInstance(new XMLSourceParser());
+ return structuredDocument;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/filebuffers/SetupParticipantForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/filebuffers/SetupParticipantForXML.java
new file mode 100644
index 0000000000..1390a1f0fb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/filebuffers/SetupParticipantForXML.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.filebuffers;
+
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.xml.core.text.rules.StructuredTextPartitionerForXML;
+
+
+
+public class SetupParticipantForXML implements IDocumentSetupParticipant {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.filebuffers.IDocumentSetupParticipant#setup(org.eclipse.jface.text.IDocument)
+ */
+ public void setup(IDocument document) {
+ if (document != null) {
+ IDocumentPartitioner partitioner = new StructuredTextPartitionerForXML();
+ document.setDocumentPartitioner(partitioner);
+ partitioner.connect(document);
+
+ // setup empty model here? coordinated via model manager?
+
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/BlockStructuredDocumentRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/BlockStructuredDocumentRegion.java
new file mode 100644
index 0000000000..5442a10f0e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/BlockStructuredDocumentRegion.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.parser.IBlockedStructuredDocumentRegion;
+
+
+public class BlockStructuredDocumentRegion extends BasicStructuredDocumentRegion implements IBlockedStructuredDocumentRegion {
+
+ private String partitionType;
+
+ /**
+ * A BlockStructuredDocumentRegion is like a IStructuredDocumentRegion,
+ * but is the result of a "block scan".
+ */
+ public BlockStructuredDocumentRegion() {
+ super();
+ }
+
+ public String getPartitionType() {
+ if (partitionType == null) {
+ // eventually can look up surroundingTag name
+ // but this field is primarily entended for future
+ // extensibility. This may change.
+ //partitionType = "org.eclipse.wst.sse.core." + tagname;
+ }
+ return partitionType;
+ }
+
+ public void setPartitionType(String partitionType) {
+ this.partitionType = partitionType;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/ContextRegionContainer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/ContextRegionContainer.java
new file mode 100644
index 0000000000..e238281ff4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/ContextRegionContainer.java
@@ -0,0 +1,386 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.text.TextRegionListImpl;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionCollection;
+import org.eclipse.wst.sse.core.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+
+
+public class ContextRegionContainer implements ITextRegionContainer {
+ protected int length;
+ protected ITextRegionCollection parent;
+ protected ITextRegionList regions;
+ protected int start;
+ protected int textLength;
+ protected String type;
+
+ public ContextRegionContainer() {
+ super();
+ regions = new TextRegionListImpl();
+
+ }
+
+ /**
+ * these "deep" parenting is not normal, but just in case.
+ */
+ private IStructuredDocument _getParentDocument() {
+ // go up enough parents to get to document
+ ITextRegionCollection parent = getParent();
+ while (!(parent instanceof IStructuredDocumentRegion)) {
+ // would be an error not to be container, but
+ // won't check for it now
+ parent = ((ITextRegionContainer) parent).getParent();
+ }
+ return ((IStructuredDocumentRegion) parent).getParentDocument();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjust(int)
+ */
+ public void adjust(int i) {
+
+ start += i;
+ // I erroneously added length and textLength
+ // may want to rename this method to adjustStart
+ //length += i;
+ //textLength += i;
+
+ }
+
+ public void adjustLengthWith(int i) {
+ length += i;
+ }
+
+ public void adjustStart(int i) {
+ start += i;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ textLength += i;
+
+ }
+
+ public boolean containsOffset(int i) {
+
+ return getStartOffset() <= i && i < getEndOffset();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#containsOffset(com.ibm.sed.structured.text.ITextRegion,
+ * int)
+ */
+ public boolean containsOffset(ITextRegion containedRegion, int offset) {
+ return getStartOffset(containedRegion) <= offset && offset < getEndOffset(containedRegion);
+ }
+
+ /**
+ * This method is just to equate positions. clients may (will probably)
+ * still need to make calls to equate regions, parent, etc.
+ */
+ public void equatePositions(ITextRegion region) {
+ start = region.getStart();
+ length = region.getLength();
+ textLength = region.getTextLength();
+ }
+
+ public int getEnd() {
+ return start + length;
+ }
+
+ public int getEndOffset() {
+ // our startOffset take into account our parent, and our start
+ return getStartOffset() + getLength();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getEndOffset(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public int getEndOffset(ITextRegion containedRegion) {
+ return getStartOffset(containedRegion) + containedRegion.getLength();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getFirstRegion()
+ */
+ public ITextRegion getFirstRegion() {
+ return getRegions().get(0);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getFullText()
+ */
+ public String getFullText() {
+ // CMVC > 252430, 245586
+ // unit test > com.ibm.sed.tests.other.UnitTests.testDeepEmbeddedJSP3
+ // this code modified on 6/25/03 (pa)
+
+ // String result = null;
+ // try {
+ // result = _getParentDocument().get(start, length);
+ // } catch (BadLocationException e) {
+ // Logger.logException("program error: unreachable exception", e);
+ // //$NON-NLS-1$
+ // }
+ // return result;
+ return getParent().getFullText(this);
+ }
+
+ public String getFullText(org.eclipse.wst.sse.core.text.ITextRegion aRegion) {
+ // Must be proxied here since aRegion should always be a child of
+ // *this* container and indexed from
+ // this container's offset
+ // try {
+ return parent.getFullText().substring(start + aRegion.getStart(), start + aRegion.getEnd());
+ //} catch (Exception e) {
+ //if (com.ibm.sed.util.Debug.debugStructuredDocument)
+ //e.printStackTrace();
+ //}
+ //return "";//$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getLastRegion()
+ */
+ public ITextRegion getLastRegion() {
+ return getRegions().get(getRegions().size() - 1);
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getNumberOfRegions()
+ */
+ public int getNumberOfRegions() {
+ return getRegions().size();
+ }
+
+ public ITextRegionCollection getParent() {
+ return parent;
+ }
+
+ /**
+ * The parameter offset refers to the overall offset in the document.
+ */
+ public ITextRegion getRegionAtCharacterOffset(int offset) {
+ ITextRegion result = null;
+ if (regions != null) {
+ // transform the requested offset to the "scale" that
+ // regions are stored in, which are all relative to the
+ // start point.
+ //int transformedOffset = offset - getStartOffset();
+ //
+ int length = getRegions().size();
+ for (int i = 0; i < length; i++) {
+ ITextRegion region = getRegions().get(i);
+ if (org.eclipse.wst.sse.core.util.Debug.debugStructuredDocument) {
+ System.out.println("region(s) in IStructuredDocumentRegion::getRegionAtCharacterOffset: " + region); //$NON-NLS-1$
+ System.out.println(" requested offset: " + offset); //$NON-NLS-1$
+ //System.out.println(" transformedOffset: " +
+ // transformedOffset); //$NON-NLS-1$
+ System.out.println(" region start: " + region.getStart()); //$NON-NLS-1$
+ System.out.println(" region end: " + region.getEnd()); //$NON-NLS-1$
+ System.out.println(" region type: " + region.getType()); //$NON-NLS-1$
+ System.out.println(" region class: " + region.getClass()); //$NON-NLS-1$
+
+ }
+ if ((getStartOffset(region) <= offset) && (offset < getEndOffset(region))) {
+ result = region;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ public ITextRegionList getRegions() {
+ return regions;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public int getStartOffset() {
+ return getParent().getStartOffset() + getStart();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getStartOffset(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public int getStartOffset(ITextRegion containedRegion) {
+ return getStartOffset() + containedRegion.getStart();
+ }
+
+ /**
+ * same as getFullText for this region type ... do we need to take white
+ * space off?
+ */
+
+ public String getText() {
+ String result = null;
+ try {
+ IStructuredDocument parentDocument = _getParentDocument();
+ result = parentDocument.get(start, length);
+ } catch (BadLocationException e) {
+ Logger.logException("program error: unreachable exception", e); //$NON-NLS-1$
+ }
+ return result;
+ }
+
+ public String getText(org.eclipse.wst.sse.core.text.ITextRegion aRegion) {
+ // Must be proxied here since aRegion should always be a child of
+ // *this* container and indexed from
+ // this container's offset
+ // com.ibm.sed.util.Assert.isTrue(regions.contains(aRegion));
+ //try {
+ return parent.getText().substring(start + aRegion.getStart(), start + aRegion.getTextEnd());
+ //} catch (Exception e) {
+ //if (com.ibm.sed.util.Debug.debugStructuredDocument)
+ //com.ibm.sed.util.Logger.log(e);
+ //}
+ // return ""; //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#getTextEnd()
+ */
+ public int getTextEnd() {
+ // int result = 0;
+ // ITextRegion lastRegion = (ITextRegion) regions.get(regions.size() -
+ // 1);
+ // result = getStartOffset(lastRegion) + lastRegion.getTextLength();
+ // return result;
+ return start + textLength;
+ }
+
+ public int getTextEndOffset() {
+ ITextRegion region = regions.get(regions.size() - 1);
+ // our startOffset take into account our parent, and our start
+ // (pa) 10/4 changed to be based on text end
+ // it used to return incorrect value for embedded region containers
+ //
+
+ // TODO CRITICAL -- need to re-work this work around, so doesn't
+ // depend on XMLRegionContext
+ // // this is a workaround for 226823///////////
+ // for (int i = regions.size() - 1; i >= 0 && region.getType() ==
+ // XMLRegionContext.WHITE_SPACE; i--)
+ // region = (ITextRegion) regions.get(i);
+ // /////////////////////////////////////////////
+
+ return getStartOffset() + region.getTextEnd();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegionCollection#getTextEndOffset(com.ibm.sed.structured.text.ITextRegion)
+ */
+ public int getTextEndOffset(ITextRegion containedRegion) {
+ int result = 0;
+ if (regions != null) {
+ int length = getRegions().size();
+ for (int i = 0; i < length; i++) {
+ ITextRegion region = getRegions().get(i);
+ if (region == containedRegion) {
+ result = getStartOffset(region) + region.getTextEnd();
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ public int getTextLength() {
+ return textLength;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setLength(int i) {
+ length = i;
+ }
+
+ public void setParent(ITextRegionCollection parentRegion) {
+ parent = parentRegion;
+ }
+
+ public void setRegions(ITextRegionList containedRegions) {
+ regions = containedRegions;
+ }
+
+ public void setStart(int i) {
+ start = i;
+ }
+
+ public void setTextLength(int i) {
+ textLength = i;
+ }
+
+ public void setType(String string) {
+ type = string;
+ }
+
+ public String toString() {
+ String className = getClass().getName();
+ String shortClassName = className.substring(className.lastIndexOf(".") + 1); //$NON-NLS-1$
+ String result = "Container!!! " + shortClassName + "--> " + getType() + ": " + getStart() + "-" + getTextEnd() + (getTextEnd() != getEnd() ? ("/" + getEnd()) : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+ return result;
+ }
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ org.eclipse.wst.sse.core.events.RegionChangedEvent result = null;
+ // FUTURE_TO_DO: need to implement region level parsing in
+ // ITextRegionContainer::updateModel
+ // never being called?
+ return result;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/IntStack.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/IntStack.java
new file mode 100644
index 0000000000..b871545643
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/IntStack.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+/*
+ *
+ * A non-resizable class implementing the behavior of java.util.Stack, but
+ * directly for the <code> integer </code> primitive.
+ */
+import java.util.EmptyStackException;
+
+public class IntStack {
+ private int[] list = null;
+
+ private int size = 0;
+
+ public IntStack() {
+ this(100);
+ }
+
+ public IntStack(int maxdepth) {
+ super();
+ list = new int[maxdepth];
+ initialize();
+ }
+
+ public boolean empty() {
+ return size == 0;
+ }
+
+ public int get(int slot) {
+ return list[slot];
+ }
+
+ void initialize() {
+ for (int i = 0; i < list.length; i++)
+ list[i] = -1;
+ }
+
+ /**
+ * Returns the int at the top of the stack without removing it
+ *
+ * @return int at the top of this stack.
+ * @exception EmptyStackException
+ * when empty.
+ */
+ public int peek() {
+ if (size == 0)
+ throw new EmptyStackException();
+ return list[size - 1];
+ }
+
+ /**
+ * Removes and returns the int at the top of the stack
+ *
+ * @return int at the top of this stack.
+ * @exception EmptyStackException
+ * when empty.
+ */
+ public int pop() {
+ int value = peek();
+ list[size - 1] = -1;
+ size--;
+ return value;
+ }
+
+ /**
+ * Pushes an item onto the top of this stack.
+ *
+ * @param newValue -
+ * the int to be pushed onto this stack.
+ * @return the <code>newValue</code> argument.
+ */
+ public int push(int newValue) {
+ if (size == list.length) {
+ throw new StackOverflowError();
+ }
+ list[size++] = newValue;
+ return newValue;
+ }
+
+ public int size() {
+ return list.length;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/RegionFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/RegionFactory.java
new file mode 100644
index 0000000000..f9c4ab9e08
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/RegionFactory.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+import org.eclipse.wst.sse.core.internal.parser.ContextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionContainer;
+
+
+public class RegionFactory {
+
+ public RegionFactory() {
+ super();
+ }
+
+ public ITextRegion createToken(ITextRegionContainer parent, String context, int start, int textLength, int length) {
+ return this.createToken(parent, context, start, textLength, length, null, null);
+ }
+
+ public ITextRegion createToken(ITextRegionContainer parent, String context, int start, int textLength, int length, String lang, String surroundingTag) {
+ ITextRegion newRegion = createToken(context, start, textLength, length);
+ // DW, 4/16/2003 token regions no longer have parents
+ //newRegion.setParent(parent);
+ return newRegion;
+ }
+
+ public ITextRegion createToken(String context, int start, int textLength, int length) {
+ return this.createToken(context, start, textLength, length, null, null);
+ }
+
+ public ITextRegion createToken(String context, int start, int textLength, int length, String lang, String surroundingTag) {
+ ITextRegion newRegion = new ContextRegion(context, start, textLength, length);
+ return newRegion;
+
+
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XML10Names.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XML10Names.java
new file mode 100644
index 0000000000..1ff05a0a8b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XML10Names.java
@@ -0,0 +1,541 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+/* The following code was generated by JFlex 1.4 on 7/17/04 3:43 AM */
+
+/*nlsXXX*/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+/**
+ * This class is a scanner generated by <a href="http://www.jflex.de/">JFlex
+ * </a> 1.4 on 7/17/04 3:43 AM from the specification file
+ * <tt>XML10Names.jflex</tt>
+ */
+public final class XML10Names {
+
+ /** This character denotes the end of file */
+ private static final int YYEOF = -1;
+
+ /** initial size of the lookahead buffer */
+ private static final int ZZ_BUFFERSIZE = 2048;
+
+ /** lexical states */
+ private static final int YYINITIAL = 0;
+
+ /**
+ * Translates characters to character classes
+ */
+ private static final String ZZ_CMAP_PACKED = "\11\0\1\1\1\2\2\0\1\1\22\0\1\1\14\0\1\0\2\0" + "\12\0\1\3\6\0\32\3\4\0\1\3\1\0\32\3\74\0\1\0" + "\10\0\27\3\1\0\37\3\1\0\72\3\2\0\13\3\2\0\10\3" + "\1\0\65\3\1\0\104\3\11\0\44\3\3\0\2\3\4\0\36\3" + "\70\0\131\3\22\0\7\3\16\0\2\0\56\0\106\0\32\0\2\0" + "\44\0\1\3\1\0\3\3\1\0\1\3\1\0\24\3\1\0\54\3" + "\1\0\7\3\3\0\1\3\1\0\1\3\1\0\1\3\1\0\1\3" + "\1\0\22\3\15\0\14\3\1\0\102\3\1\0\14\3\1\0\44\3" + "\1\0\4\0\11\0\65\3\2\0\2\3\2\0\2\3\3\0\34\3" + "\2\0\10\3\2\0\2\3\67\0\46\3\2\0\1\3\7\0\46\3" + "\12\0\21\0\1\0\27\0\1\0\3\0\1\0\1\0\1\0\2\0" + "\1\0\1\0\13\0\33\3\5\0\3\3\56\0\32\3\5\0\1\0" + "\12\3\10\0\15\0\12\0\6\0\1\0\107\3\2\0\5\3\1\0" + "\17\3\1\0\4\3\1\0\1\3\17\0\2\3\2\0\1\0\4\0" + "\2\0\12\0\u0207\0\3\0\1\0\65\3\2\0\1\0\1\3\20\0" + "\3\0\4\0\3\0\12\3\2\0\2\0\12\0\21\0\3\0\1\0" + "\10\3\2\0\2\3\2\0\26\3\1\0\7\3\1\0\1\3\3\0" + "\4\3\2\0\1\0\1\0\7\0\2\0\2\0\2\0\3\0\11\0" + "\1\0\4\0\2\3\1\0\3\3\2\0\2\0\12\0\2\3\20\0"
+ + "\1\0\2\0\6\3\4\0\2\3\2\0\26\3\1\0\7\3\1\0" + "\2\3\1\0\2\3\1\0\2\3\2\0\1\0\1\0\5\0\4\0" + "\2\0\2\0\3\0\13\0\4\3\1\0\1\3\7\0\12\0\2\0" + "\3\3\14\0\3\0\1\0\7\3\1\0\1\3\1\0\3\3\1\0" + "\26\3\1\0\7\3\1\0\2\3\1\0\5\3\2\0\1\0\1\3" + "\10\0\1\0\3\0\1\0\3\0\22\0\1\3\5\0\12\0\21\0" + "\3\0\1\0\10\3\2\0\2\3\2\0\26\3\1\0\7\3\1\0" + "\2\3\2\0\4\3\2\0\1\0\1\3\6\0\3\0\2\0\2\0" + "\3\0\10\0\2\0\4\0\2\3\1\0\3\3\4\0\12\0\22\0" + "\2\0\1\0\6\3\3\0\3\3\1\0\4\3\3\0\2\3\1\0" + "\1\3\1\0\2\3\3\0\2\3\3\0\3\3\3\0\10\3\1\0" + "\3\3\4\0\5\0\3\0\3\0\1\0\4\0\11\0\1\0\17\0" + "\11\0\21\0\3\0\1\0\10\3\1\0\3\3\1\0\27\3\1\0" + "\12\3\1\0\5\3\4\0\7\0\1\0\3\0\1\0\4\0\7\0" + "\2\0\11\0\2\3\4\0\12\0\22\0\2\0\1\0\10\3\1\0" + "\3\3\1\0\27\3\1\0\12\3\1\0\5\3\4\0\7\0\1\0" + "\3\0\1\0\4\0\7\0\2\0\7\0\1\3\1\0\2\3\4\0" + "\12\0\22\0\2\0\1\0\10\3\1\0\3\3\1\0\27\3\1\0" + "\20\3\4\0\6\0\2\0\3\0\1\0\4\0\11\0\1\0\10\0" + "\2\3\4\0\12\0\221\0\56\3\1\0\1\3\1\0\2\3\7\0"
+ + "\5\0\6\3\1\0\10\0\1\0\12\0\47\0\2\3\1\0\1\3" + "\2\0\2\3\1\0\1\3\2\0\1\3\6\0\4\3\1\0\7\3" + "\1\0\3\3\1\0\1\3\1\0\1\3\2\0\2\3\1\0\2\3" + "\1\0\1\3\1\0\2\3\6\0\1\0\2\0\1\3\2\0\5\3" + "\1\0\1\0\1\0\6\0\2\0\12\0\76\0\2\0\6\0\12\0" + "\13\0\1\0\1\0\1\0\1\0\1\0\4\0\2\0\10\3\1\0" + "\41\3\7\0\24\0\1\0\6\0\4\0\6\0\1\0\1\0\1\0" + "\25\0\3\0\7\0\1\0\1\0\346\0\46\3\12\0\47\3\11\0" + "\1\3\1\0\2\3\1\0\3\3\1\0\1\3\1\0\2\3\1\0" + "\5\3\51\0\1\3\1\0\1\3\1\0\1\3\13\0\1\3\1\0" + "\1\3\1\0\1\3\3\0\2\3\3\0\1\3\5\0\3\3\1\0" + "\1\3\1\0\1\3\1\0\1\3\1\0\1\3\3\0\2\3\3\0" + "\2\3\1\0\1\3\50\0\1\3\11\0\1\3\2\0\1\3\2\0" + "\2\3\7\0\2\3\1\0\1\3\1\0\7\3\50\0\1\3\4\0" + "\1\3\10\0\1\3\u0c06\0\234\3\4\0\132\3\6\0\26\3\2\0" + "\6\3\2\0\46\3\2\0\6\3\2\0\10\3\1\0\1\3\1\0" + "\1\3\1\0\1\3\1\0\37\3\2\0\65\3\1\0\7\3\1\0" + "\1\3\3\0\3\3\1\0\7\3\3\0\4\3\2\0\6\3\4\0" + "\15\3\5\0\3\3\1\0\7\3\323\0\15\0\4\0\1\0\104\0" + "\1\3\3\0\2\3\2\0\1\3\121\0\3\3\u0e82\0\1\0\1\0"
+ + "\1\3\31\0\11\3\6\0\1\0\5\0\13\0\124\3\4\0\2\0" + "\2\0\2\0\2\0\132\3\1\0\3\0\6\0\50\3\u1cd3\0\u51a6\3" + "\u0c5a\0\u2ba4\3\u285c\0";
+
+ /**
+ * Translates characters to character classes
+ */
+ private static final char[] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+ /**
+ * Translates DFA states to action switch labels.
+ */
+ private static final int[] ZZ_ACTION = zzUnpackAction();
+
+ private static final String ZZ_ACTION_PACKED_0 = "\1\0\1\1\1\2\4\1";
+
+ private static int[] zzUnpackAction() {
+ int[] result = new int[7];
+ int offset = 0;
+ offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackAction(String packed, int offset, int[] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int count = packed.charAt(i++);
+ int value = packed.charAt(i++);
+ do
+ result[j++] = value;
+ while (--count > 0);
+ }
+ return j;
+ }
+
+
+ /**
+ * Translates a state to a row index in the transition table
+ */
+ private static final int[] ZZ_ROWMAP = zzUnpackRowMap();
+
+ private static final String ZZ_ROWMAP_PACKED_0 = "\0\0\0\4\0\10\0\14\0\20\0\24\0\30";
+
+ private static int[] zzUnpackRowMap() {
+ int[] result = new int[7];
+ int offset = 0;
+ offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackRowMap(String packed, int offset, int[] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int high = packed.charAt(i++) << 16;
+ result[j++] = high | packed.charAt(i++);
+ }
+ return j;
+ }
+
+ /**
+ * The transition table of the DFA
+ */
+ private static final int ZZ_TRANS[] = {1, 1, -1, 2, -1, -1, -1, -1, 2, 3, 4, 2, 2, 3, 4, 5, -1, 4, 4, 6, 5, 5, 4, 5, 6, 6, -1, 6,};
+
+ /* error codes */
+ private static final int ZZ_UNKNOWN_ERROR = 0;
+ private static final int ZZ_NO_MATCH = 1;
+ private static final int ZZ_PUSHBACK_2BIG = 2;
+
+ /* error messages for the codes above */
+ private static final String ZZ_ERROR_MSG[] = {"Unkown internal scanner error", "Error: could not match input", "Error: pushback value was too large"};
+
+ /**
+ * ZZ_ATTRIBUTE[aState] contains the attributes of state
+ * <code>aState</code>
+ */
+ private static final int[] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+ private static final String ZZ_ATTRIBUTE_PACKED_0 = "\1\0\1\11\5\1";
+
+ private static int[] zzUnpackAttribute() {
+ int[] result = new int[7];
+ int offset = 0;
+ offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackAttribute(String packed, int offset, int[] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int count = packed.charAt(i++);
+ int value = packed.charAt(i++);
+ do
+ result[j++] = value;
+ while (--count > 0);
+ }
+ return j;
+ }
+
+ /** the input device */
+ private java.io.Reader zzReader;
+
+ /** the current state of the DFA */
+ private int zzState;
+
+ /** the current lexical state */
+ private int zzLexicalState = YYINITIAL;
+
+ /**
+ * this buffer contains the current text to be matched and is the source
+ * of the yytext() string
+ */
+ private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
+
+ /** the textposition at the last accepting state */
+ private int zzMarkedPos;
+
+ /** the textposition at the last state to be included in yytext */
+ private int zzPushbackPos;
+
+ /** the current text position in the buffer */
+ private int zzCurrentPos;
+
+ /** startRead marks the beginning of the yytext() string in the buffer */
+ private int zzStartRead;
+
+ /**
+ * endRead marks the last character in the buffer, that has been read from
+ * input
+ */
+ private int zzEndRead;
+
+ /** number of newlines encountered up to the start of the matched text */
+ int yyline;
+
+ /** the number of characters up to the start of the matched text */
+ int yychar;
+
+ /**
+ * the number of characters from the last newline up to the start of the
+ * matched text
+ */
+ int yycolumn;
+
+ /**
+ * zzAtBOL == true <=>the scanner is currently at the beginning of a line
+ */
+ boolean zzAtBOL = true;
+
+ /** zzAtEOF == true <=>the scanner is at the EOF */
+ private boolean zzAtEOF;
+
+ /* user code: */
+
+ /**
+ * Creates a new scanner
+ */
+ public XML10Names() {
+ this.zzReader = null;
+ }
+
+ public boolean isValidXML10Name(String stringToCheck) {
+ boolean result = false;
+ yyreset(new java.io.StringReader(stringToCheck));
+ try {
+ result = isValidXML10Name();
+ } catch (java.io.IOException e) {
+ // should be impossible with strings, but if occurs, just means
+ // "not"
+ result = false;
+ }
+ return result;
+ }
+
+
+
+ /**
+ * Creates a new scanner There is also a java.io.InputStream version of
+ * this constructor.
+ *
+ * @param in
+ * the java.io.Reader to read input from.
+ */
+ public XML10Names(java.io.Reader in) {
+ this.zzReader = in;
+ }
+
+ /**
+ * Creates a new scanner. There is also java.io.Reader version of this
+ * constructor.
+ *
+ * @param in
+ * the java.io.Inputstream to read input from.
+ */
+ public XML10Names(java.io.InputStream in) {
+ this(new java.io.InputStreamReader(in));
+ }
+
+ /**
+ * Unpacks the compressed character translation table.
+ *
+ * @param packed
+ * the packed character translation table
+ * @return the unpacked character translation table
+ */
+ private static char[] zzUnpackCMap(String packed) {
+ char[] map = new char[0x10000];
+ int i = 0; /* index in packed string */
+ int j = 0; /* index in unpacked array */
+ while (i < 1226) {
+ int count = packed.charAt(i++);
+ char value = packed.charAt(i++);
+ do
+ map[j++] = value;
+ while (--count > 0);
+ }
+ return map;
+ }
+
+
+ /**
+ * Refills the input buffer.
+ *
+ * @return <code>false</code>, iff there was new input.
+ *
+ * @exception java.io.IOException
+ * if any I/O-Error occurs
+ */
+ private boolean zzRefill() throws java.io.IOException {
+
+ /* first: make room (if you can) */
+ if (zzStartRead > 0) {
+ System.arraycopy(zzBuffer, zzStartRead, zzBuffer, 0, zzEndRead - zzStartRead);
+
+ /* translate stored positions */
+ zzEndRead -= zzStartRead;
+ zzCurrentPos -= zzStartRead;
+ zzMarkedPos -= zzStartRead;
+ zzPushbackPos -= zzStartRead;
+ zzStartRead = 0;
+ }
+
+ /* is the buffer big enough? */
+ if (zzCurrentPos >= zzBuffer.length) {
+ /* if not: blow it up */
+ char newBuffer[] = new char[zzCurrentPos * 2];
+ System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
+ zzBuffer = newBuffer;
+ }
+
+ /* finally: fill the buffer with new input */
+ int numRead = zzReader.read(zzBuffer, zzEndRead, zzBuffer.length - zzEndRead);
+
+ if (numRead < 0) {
+ return true;
+ } else {
+ zzEndRead += numRead;
+ return false;
+ }
+ }
+
+
+ /**
+ * Closes the input stream.
+ */
+ final void yyclose() throws java.io.IOException {
+ zzAtEOF = true; /* indicate end of file */
+ zzEndRead = zzStartRead; /* invalidate buffer */
+
+ if (zzReader != null)
+ zzReader.close();
+ }
+
+
+ /**
+ * Resets the scanner to read from a new input stream. Does not close the
+ * old reader.
+ *
+ * All internal variables are reset, the old input stream <b>cannot </b>
+ * be reused (internal buffer is discarded and lost). Lexical state is set
+ * to <tt>ZZ_INITIAL</tt>.
+ *
+ * @param reader
+ * the new input stream
+ */
+ private final void yyreset(java.io.Reader reader) {
+ zzReader = reader;
+ //zzAtBOL = true;
+ zzAtEOF = false;
+ zzEndRead = zzStartRead = 0;
+ zzCurrentPos = zzMarkedPos = zzPushbackPos = 0;
+ yyline = yychar = yycolumn = 0;
+ zzLexicalState = YYINITIAL;
+ }
+
+
+ /**
+ * Returns the current lexical state.
+ */
+ final int yystate() {
+ return zzLexicalState;
+ }
+
+
+ /**
+ * Enters a new lexical state
+ *
+ * @param newState
+ * the new lexical state
+ */
+ final void yybegin(int newState) {
+ zzLexicalState = newState;
+ }
+
+
+ /**
+ * Returns the text matched by the current regular expression.
+ */
+ final String yytext() {
+ return new String(zzBuffer, zzStartRead, zzMarkedPos - zzStartRead);
+ }
+
+
+ /**
+ * Returns the character at position <tt>pos</tt> from the matched text.
+ *
+ * It is equivalent to yytext().charAt(pos), but faster
+ *
+ * @param pos
+ * the position of the character to fetch. A value from 0 to
+ * yylength()-1.
+ *
+ * @return the character at position pos
+ */
+ final char yycharat(int pos) {
+ return zzBuffer[zzStartRead + pos];
+ }
+
+
+ /**
+ * Returns the length of the matched text region.
+ */
+ private final int yylength() {
+ return zzMarkedPos - zzStartRead;
+ }
+
+
+ /**
+ * Reports an error that occured while scanning.
+ *
+ * In a wellformed scanner (no or only correct usage of yypushback(int)
+ * and a match-all fallback rule) this method will only be called with
+ * things that "Can't Possibly Happen". If this method is called,
+ * something is seriously wrong (e.g. a JFlex bug producing a faulty
+ * scanner etc.).
+ *
+ * Usual syntax/scanner level error handling should be done in error
+ * fallback rules.
+ *
+ * @param errorCode
+ * the code of the errormessage to display
+ */
+ private void zzScanError(int errorCode) {
+ String message;
+ try {
+ message = ZZ_ERROR_MSG[errorCode];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+ }
+
+ throw new Error(message);
+ }
+
+
+ /**
+ * Pushes the specified amount of characters back into the input stream.
+ *
+ * They will be read again by then next call of the scanning method
+ *
+ * @param number
+ * the number of characters to be read again. This number must
+ * not be greater than yylength()!
+ */
+ void yypushback(int number) {
+ if (number > yylength())
+ zzScanError(ZZ_PUSHBACK_2BIG);
+
+ zzMarkedPos -= number;
+ }
+
+
+ /**
+ * Resumes scanning until the next regular expression is matched, the end
+ * of input is encountered or an I/O-Error occurs.
+ *
+ * @return the next token
+ * @exception java.io.IOException
+ * if any I/O-Error occurs
+ */
+ private boolean isValidXML10Name() throws java.io.IOException {
+ int zzInput;
+ int zzAction;
+
+ // cached fields:
+ int zzCurrentPosL;
+ int zzMarkedPosL;
+ int zzEndReadL = zzEndRead;
+ char[] zzBufferL = zzBuffer;
+ char[] zzCMapL = ZZ_CMAP;
+
+ int[] zzTransL = ZZ_TRANS;
+ int[] zzRowMapL = ZZ_ROWMAP;
+ int[] zzAttrL = ZZ_ATTRIBUTE;
+
+ while (true) {
+ zzMarkedPosL = zzMarkedPos;
+
+ zzAction = -1;
+
+ zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+
+ zzState = zzLexicalState;
+
+
+ zzForAction : {
+ while (true) {
+
+ if (zzCurrentPosL < zzEndReadL)
+ zzInput = zzBufferL[zzCurrentPosL++];
+ else if (zzAtEOF) {
+ zzInput = YYEOF;
+ break zzForAction;
+ } else {
+ // store back cached positions
+ zzCurrentPos = zzCurrentPosL;
+ zzMarkedPos = zzMarkedPosL;
+ boolean eof = zzRefill();
+ // get translated positions and possibly new buffer
+ zzCurrentPosL = zzCurrentPos;
+ zzMarkedPosL = zzMarkedPos;
+ zzBufferL = zzBuffer;
+ zzEndReadL = zzEndRead;
+ if (eof) {
+ zzInput = YYEOF;
+ break zzForAction;
+ } else {
+ zzInput = zzBufferL[zzCurrentPosL++];
+ }
+ }
+ int zzNext = zzTransL[zzRowMapL[zzState] + zzCMapL[zzInput]];
+ if (zzNext == -1)
+ break zzForAction;
+ zzState = zzNext;
+
+ int zzAttributes = zzAttrL[zzState];
+ if ((zzAttributes & 1) == 1) {
+ zzAction = zzState;
+ zzMarkedPosL = zzCurrentPosL;
+ if ((zzAttributes & 8) == 8)
+ break zzForAction;
+ }
+
+ }
+ }
+
+ // store back cached position
+ zzMarkedPos = zzMarkedPosL;
+
+ switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+ case 1 : {
+ return false;
+ }
+ case 3 :
+ break;
+ case 2 : {
+ return true;
+ }
+ case 4 :
+ break;
+ default :
+ if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+ zzAtEOF = true;
+ {
+ {
+ return false;
+ }
+ }
+ } else {
+ zzScanError(ZZ_NO_MATCH);
+ }
+ }
+ }
+ }
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLRegionContexts.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLRegionContexts.java
new file mode 100644
index 0000000000..5c622ab3c0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLRegionContexts.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+/**
+ * @deprecated - use org.eclipse.wst.xml.core.parser.XMLRegionContext
+ */
+public interface XMLRegionContexts extends XMLRegionContext {
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLSourceParser.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLSourceParser.java
new file mode 100644
index 0000000000..63711818d9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLSourceParser.java
@@ -0,0 +1,595 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.document.DocumentReader;
+import org.eclipse.wst.sse.core.internal.text.CharSequenceReader;
+import org.eclipse.wst.sse.core.internal.text.IRegionComparible;
+import org.eclipse.wst.sse.core.parser.BlockMarker;
+import org.eclipse.wst.sse.core.parser.BlockTagParser;
+import org.eclipse.wst.sse.core.parser.BlockTokenizer;
+import org.eclipse.wst.sse.core.parser.RegionParser;
+import org.eclipse.wst.sse.core.parser.StructuredDocumentRegionHandler;
+import org.eclipse.wst.sse.core.parser.StructuredDocumentRegionParser;
+import org.eclipse.wst.sse.core.parser.StructuredDocumentRegionParserExtension;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.xml.core.Logger;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+/**
+ * Takes input from the HTMLTokenizer and creates a tag list
+ */
+
+public class XMLSourceParser implements RegionParser, BlockTagParser, StructuredDocumentRegionParser, IRegionComparible, StructuredDocumentRegionParserExtension {
+ // made public to aid access from inner classes in hierarchy.
+ // TODO: in future, figure out how to solve without exposing data.
+ public CharSequence fCharSequenceSource = null;
+ private IDocument fDocumentInput;
+ protected int fOffset = 0;
+ // DMW: 2/12/03. Removed some state data, since not really needed,
+ // and since it added a lot to overhead (since so many regions are
+ // created.
+ // protected IStructuredDocumentRegion fCurrentNode = null;
+ // protected IStructuredDocumentRegion fNodes = null;
+ // protected List fRegions = null;
+ // protected Object fInput = null;
+ protected String fStringInput = null;
+ protected List fStructuredDocumentRegionHandlers;
+
+ protected BlockTokenizer fTokenizer = null;
+ protected long startTime;
+ protected long stopTime;
+
+ /**
+ * HTMLSourceParser constructor comment.
+ */
+ public XMLSourceParser() {
+ super();
+ fStructuredDocumentRegionHandlers = new ArrayList();
+ }
+
+ /**
+ * This is a simple utility to count nodes. Used only for debug
+ * statements.
+ */
+ protected int _countNodes(IStructuredDocumentRegion nodes) {
+ int result = 0;
+ IStructuredDocumentRegion countNode = nodes;
+ while (countNode != null) {
+ result++;
+ countNode = countNode.getNext();
+ }
+ return result;
+ }
+
+ public void addBlockMarker(BlockMarker marker) {
+ getTokenizer().addBlockMarker(marker);
+ }
+
+ public void addStructuredDocumentRegionHandler(StructuredDocumentRegionHandler handler) {
+ if (fStructuredDocumentRegionHandlers == null)
+ fStructuredDocumentRegionHandlers = new ArrayList();
+ fStructuredDocumentRegionHandlers.add(handler);
+ }
+
+ public void beginBlockScan(String newTagName) {
+ getTokenizer().beginBlockTagScan(newTagName);
+ }
+
+ /**
+ * @return IStructuredDocumentRegion
+ */
+ protected IStructuredDocumentRegion createStructuredDocumentRegion(String type) {
+ IStructuredDocumentRegion newNode = null;
+ if (type == XMLRegionContext.BLOCK_TEXT)
+ newNode = XMLStructuredRegionFactory.createRegion(XMLStructuredRegionFactory.XML_BLOCK);
+ else
+ newNode = XMLStructuredRegionFactory.createRegion(XMLStructuredRegionFactory.XML);
+ return newNode;
+ }
+
+ protected void fireNodeParsed(IStructuredDocumentRegion fCurrentNode) {
+ if (fCurrentNode != null && fStructuredDocumentRegionHandlers != null) {
+ for (int i = 0; i < fStructuredDocumentRegionHandlers.size(); i++)
+ ((StructuredDocumentRegionHandler) fStructuredDocumentRegionHandlers.get(i)).nodeParsed(fCurrentNode);
+ }
+ }
+
+ public BlockMarker getBlockMarker(String tagName) {
+ List markers = getTokenizer().getBlockMarkers();
+ for (int i = 0; i < markers.size(); i++) {
+ BlockMarker marker = (BlockMarker) markers.get(i);
+ if (marker.isCaseSensitive()) {
+ if (marker.getTagName().equals(tagName))
+ return marker;
+ } else {
+ if (marker.getTagName().equalsIgnoreCase(tagName))
+ return marker;
+ }
+ }
+ return null;
+ }
+
+ public List getBlockMarkers() {
+ return getTokenizer().getBlockMarkers();
+ }
+
+ /**
+ * @return IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getDocumentRegions() {
+ IStructuredDocumentRegion headnode = null;
+ if (headnode == null) {
+ if (Debug.perfTest) {
+ startTime = System.currentTimeMillis();
+ }
+ headnode = parseNodes();
+ if (Debug.perfTest) {
+ stopTime = System.currentTimeMillis();
+ System.out.println(" -- creating nodes of IStructuredDocument -- "); //$NON-NLS-1$
+ System.out.println(" Time parse and init all regions: " + (stopTime - startTime) + " (msecs)"); //$NON-NLS-2$//$NON-NLS-1$
+ //System.out.println(" for " + fRegions.size() + "
+ // Regions");//$NON-NLS-2$//$NON-NLS-1$
+ System.out.println(" and " + _countNodes(headnode) + " Nodes"); //$NON-NLS-2$//$NON-NLS-1$
+ }
+ }
+ return headnode;
+ }
+
+ protected ITextRegion getNextRegion() {
+ ITextRegion region = null;
+ try {
+ region = getTokenizer().getNextToken();
+ // DMW: 2/12/03 Removed state
+ // if (region != null) {
+ // fRegions.add(region);
+ // }
+ return region;
+ } catch (StackOverflowError e) {
+ Logger.logException(getClass().getName() + ": input could not be parsed correctly at position " + getTokenizer().getOffset(), e); //$NON-NLS-1$
+ throw e;
+ } catch (Exception e) {
+ Logger.logException(getClass().getName() + ": input could not be parsed correctly at position " + getTokenizer().getOffset() + " (" + e.getLocalizedMessage() + ")", e); //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ }
+ return null;
+ }
+
+ /**
+ * Return the full list of known regions. Typically getNodes should be
+ * used instead of this method.
+ */
+ public List getRegions() {
+ IStructuredDocumentRegion headNode = null;
+ if (!getTokenizer().isEOF()) {
+ headNode = getDocumentRegions();
+ // throw new IllegalStateException("parsing has not finished");
+ }
+ // for memory recovery, we assume if someone
+ // requests all regions, we can reset our big
+ // memory consuming objects
+ // but the new "getRegions" method is then more expensive.
+ // I don't think its used much, though.
+ List localRegionsList = getRegions(headNode);
+ primReset();
+ return localRegionsList;
+ }
+
+ /**
+ * Method getRegions.
+ *
+ * @param headNode
+ * @return List
+ */
+ protected List getRegions(IStructuredDocumentRegion headNode) {
+ List allRegions = new ArrayList();
+ IStructuredDocumentRegion currentNode = headNode;
+ while (currentNode != null) {
+ ITextRegionList nodeRegions = currentNode.getRegions();
+ for (int i = 0; i < nodeRegions.size(); i++) {
+ allRegions.add(nodeRegions.get(i));
+ }
+ currentNode = currentNode.getNext();
+ }
+ return allRegions;
+ }
+
+ /**
+ *
+ * @return java.util.List
+ */
+ public List getStructuredDocumentRegionHandlers() {
+ if (fStructuredDocumentRegionHandlers == null) {
+ fStructuredDocumentRegionHandlers = new ArrayList(0);
+ }
+ return fStructuredDocumentRegionHandlers;
+ }
+
+ /**
+ * Returns text from the current input. Text is only valid before
+ * getNodes() has been called and only when a raw String or DocumentReader
+ * is given as the input.
+ */
+ public String getText(int offset, int length) {
+ String text = null;
+ if (fCharSequenceSource != null) {
+ int start = fOffset + offset;
+ int end = start + length;
+ text = fCharSequenceSource.subSequence(start, end).toString();
+ } else if (fDocumentInput != null) {
+ try {
+ text = fDocumentInput.get(offset, length);
+ } catch (BadLocationException e) {
+ text = "";
+ }
+ } else {
+ if (fStringInput == null || fStringInput.length() == 0 || offset + length > fStringInput.length() || offset < 0) {
+ text = ""; //$NON-NLS-1$
+ } else {
+ // offset is entirely valid during parsing as the parse
+ // numbers haven't been adjusted.
+ text = fStringInput.substring(offset, offset + length);
+ }
+ }
+ return text;
+ }
+
+ protected BlockTokenizer getTokenizer() {
+ if (fTokenizer == null) {
+ fTokenizer = new XMLTokenizer();
+ }
+ return fTokenizer;
+ }
+
+ /**
+ * @see com.ibm.sed.parser.RegionParser#newInstance()
+ */
+ public RegionParser newInstance() {
+ XMLSourceParser newInstance = new XMLSourceParser();
+ newInstance.setTokenizer(getTokenizer().newInstance());
+ return newInstance;
+ }
+
+ protected IStructuredDocumentRegion parseNodes() {
+ // regions are initially reported as complete offsets within the
+ // scanned input
+ // they are adjusted here to be indexes from the currentNode's start
+ // offset
+ IStructuredDocumentRegion headNode = null;
+ IStructuredDocumentRegion lastNode = null;
+ ITextRegion region = null;
+ IStructuredDocumentRegion currentNode = null;
+ String type = null;
+
+ while ((region = getNextRegion()) != null) {
+ type = region.getType();
+ // these types (might) demand a IStructuredDocumentRegion for each
+ // of them
+ if (type == XMLRegionContext.BLOCK_TEXT) {
+ if (currentNode != null && currentNode.getLastRegion().getType() == XMLRegionContext.BLOCK_TEXT) {
+ // multiple block texts indicated embedded containers; no
+ // new IStructuredDocumentRegion
+ currentNode.addRegion(region);
+ currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+ region.adjustStart(-currentNode.getStart());
+ // DW 4/16/2003 regions no longer have parents
+ //region.setParent(currentNode);
+ } else {
+ // not continuing a IStructuredDocumentRegion
+ if (currentNode != null) {
+ // ensure that any existing node is at least
+ // terminated
+ if (!currentNode.isEnded()) {
+ currentNode.setLength(region.getStart() - currentNode.getStart());
+ // fCurrentNode.setTextLength(region.getStart() -
+ // fCurrentNode.getStart());
+ }
+ lastNode = currentNode;
+ }
+ fireNodeParsed(currentNode);
+ currentNode = createStructuredDocumentRegion(type);
+ if (lastNode != null) {
+ lastNode.setNext(currentNode);
+ }
+ currentNode.setPrevious(lastNode);
+ currentNode.setStart(region.getStart());
+ currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+ currentNode.setEnded(true);
+ region.adjustStart(-currentNode.getStart());
+ currentNode.addRegion(region);
+ // DW 4/16/2003 regions no longer have parents
+ //region.setParent(currentNode);
+ }
+ }
+ // the following contexts OPEN new StructuredDocumentRegions
+ else if ((currentNode != null && currentNode.isEnded()) || (type == XMLRegionContext.XML_CONTENT) || (type == XMLRegionContext.XML_CHAR_REFERENCE) || (type == XMLRegionContext.XML_ENTITY_REFERENCE) || (type == XMLRegionContext.XML_PI_OPEN) || (type == XMLRegionContext.XML_TAG_OPEN) || (type == XMLRegionContext.XML_END_TAG_OPEN) || (type == XMLRegionContext.XML_COMMENT_OPEN) || (type == XMLRegionContext.XML_CDATA_OPEN) || (type == XMLRegionContext.XML_DECLARATION_OPEN)) {
+ if (currentNode != null) {
+ // ensure that any existing node is at least terminated
+ if (!currentNode.isEnded()) {
+ currentNode.setLength(region.getStart() - currentNode.getStart());
+ // fCurrentNode.setTextLength(region.getStart() -
+ // fCurrentNode.getStart());
+ }
+ lastNode = currentNode;
+ }
+ fireNodeParsed(currentNode);
+ currentNode = createStructuredDocumentRegion(type);
+ if (lastNode != null) {
+ lastNode.setNext(currentNode);
+ }
+ currentNode.setPrevious(lastNode);
+ currentNode.setStart(region.getStart());
+ currentNode.addRegion(region);
+ currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+ region.adjustStart(-currentNode.getStart());
+ // DW 4/16/2003 regions no longer have parents
+ //region.setParent(currentNode);
+ }
+ // the following contexts neither open nor close
+ // StructuredDocumentRegions; just add to them
+ else if ((type == XMLRegionContext.XML_TAG_NAME) || (type == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) || (type == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) || (type == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) || (type == XMLRegionContext.XML_COMMENT_TEXT) || (type == XMLRegionContext.XML_PI_CONTENT) || (type == XMLRegionContext.XML_DOCTYPE_INTERNAL_SUBSET)) {
+ currentNode.addRegion(region);
+ currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+ region.adjustStart(-currentNode.getStart());
+ // DW 4/16/2003 regions no longer have parents
+ //region.setParent(currentNode);
+ }
+ // the following contexts close off StructuredDocumentRegions
+ // cleanly
+ else if ((type == XMLRegionContext.XML_PI_CLOSE) || (type == XMLRegionContext.XML_TAG_CLOSE) || (type == XMLRegionContext.XML_EMPTY_TAG_CLOSE) || (type == XMLRegionContext.XML_COMMENT_CLOSE) || (type == XMLRegionContext.XML_DECLARATION_CLOSE) || (type == XMLRegionContext.XML_CDATA_CLOSE)) {
+ currentNode.setEnded(true);
+ currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+ currentNode.addRegion(region);
+ region.adjustStart(-currentNode.getStart());
+ // DW 4/16/2003 regions no longer have parents
+ //region.setParent(currentNode);
+ }
+ // this is extremely rare, but valid
+ else if (type == XMLRegionContext.WHITE_SPACE) {
+ ITextRegion lastRegion = currentNode.getLastRegion();
+ // pack the embedded container with this region
+ if (lastRegion instanceof ITextRegionContainer) {
+ ITextRegionContainer container = (ITextRegionContainer) lastRegion;
+ container.getRegions().add(region);
+ // containers must have parent set ...
+ // setting for EACH subregion is redundent, but not sure
+ // where else to do, so will do here for now.
+ container.setParent(currentNode);
+ // DW 4/16/2003 regions no longer have parents
+ //region.setParent(container);
+ region.adjustStart(container.getLength() - region.getStart());
+ }
+ currentNode.getLastRegion().adjustLengthWith(region.getLength());
+ currentNode.adjustLengthWith(region.getLength());
+ } else if (type == XMLRegionContext.UNDEFINED && currentNode != null) {
+ // skip on a very-first region situation as the default
+ // behavior is good enough
+ // combine with previous if also undefined
+ if (currentNode.getLastRegion() != null && currentNode.getLastRegion().getType() == XMLRegionContext.UNDEFINED) {
+ currentNode.getLastRegion().adjustLengthWith(region.getLength());
+ currentNode.adjustLengthWith(region.getLength());
+ }
+ // previous wasn't undefined
+ else {
+ currentNode.addRegion(region);
+ currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+ region.adjustStart(-currentNode.getStart());
+ }
+ } else {
+ // if an unknown type is the first region in the document,
+ // ensure that a node exists
+ if (currentNode == null) {
+ currentNode = createStructuredDocumentRegion(type);
+ currentNode.setStart(region.getStart());
+ }
+ currentNode.addRegion(region);
+ currentNode.setLength(region.getStart() + region.getLength() - currentNode.getStart());
+ region.adjustStart(-currentNode.getStart());
+ // DW 4/16/2003 regions no longer have parents
+ //region.setParent(currentNode);
+ if (Debug.debugTokenizer)
+ System.out.println(getClass().getName() + " found region of not specifically handled type " + region.getType() + " @ " + region.getStart() + "[" + region.getLength() + "]"); //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ }
+
+ // these regions also get their own node, so close them cleanly
+ // NOTE: these regions have new StructuredDocumentRegions created
+ // for them above; it may
+ // be more readable if that is handled here as well, but the
+ // current layout
+ // ensures that they open StructuredDocumentRegions the same way
+ if ((type == XMLRegionContext.XML_CONTENT) || (type == XMLRegionContext.XML_CHAR_REFERENCE) || (type == XMLRegionContext.XML_ENTITY_REFERENCE)) {
+ currentNode.setEnded(true);
+ }
+ if (headNode == null && currentNode != null) {
+ headNode = currentNode;
+ }
+ }
+ if (currentNode != null) {
+ fireNodeParsed(currentNode);
+ currentNode.setPrevious(lastNode);
+ }
+ //fStringInput = null;
+ primReset();
+ return headNode;
+ }
+
+ protected void primReset() {
+ //fNodes = null;
+ //fRegions = null;
+ //fInput = null;
+ fStringInput = null;
+ fCharSequenceSource = null;
+ fDocumentInput = null;
+ fOffset = 0;
+ //fCurrentNode = null;
+ // DMW: also reset tokenizer so it doesn't hold on
+ // to large arrays
+ getTokenizer().reset(new char[0]);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.internal.text.IRegionComparible#regionMatches(int,
+ * int, java.lang.String)
+ */
+ public boolean regionMatches(int offset, int length, String stringToCompare) {
+ // by definition
+ if (stringToCompare == null)
+ return false;
+
+ boolean result = false;
+ if (fCharSequenceSource != null && fCharSequenceSource instanceof IRegionComparible) {
+ result = ((IRegionComparible) fCharSequenceSource).regionMatches(offset, length, stringToCompare);
+ } else {
+ // old fashioned ways
+ String test = null;
+ if (fCharSequenceSource != null) {
+ test = fCharSequenceSource.subSequence(offset, offset + length).toString();
+ } else if (fStringInput != null) {
+ test = fStringInput.substring(offset, offset + length);
+ }
+ result = stringToCompare.equals(test);
+ }
+ return result;
+ }
+
+ public boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare) {
+ // by definition
+ if (stringToCompare == null)
+ return false;
+
+ boolean result = false;
+ if (fCharSequenceSource != null && fCharSequenceSource instanceof IRegionComparible) {
+ result = ((IRegionComparible) fCharSequenceSource).regionMatchesIgnoreCase(offset, length, stringToCompare);
+ } else {
+ // old fashioned ways
+ String test = null;
+ if (fCharSequenceSource != null) {
+ test = fCharSequenceSource.subSequence(offset, offset + length).toString();
+ } else if (fStringInput != null) {
+ test = fStringInput.substring(offset, offset + length);
+ }
+ result = stringToCompare.equalsIgnoreCase(test);
+ }
+ return result;
+ }
+
+ public void removeBlockMarker(BlockMarker marker) {
+ getTokenizer().removeBlockMarker(marker);
+ }
+
+ public void removeBlockMarker(String tagName) {
+ getTokenizer().removeBlockMarker(tagName);
+ }
+
+ public void removeStructuredDocumentRegionHandler(StructuredDocumentRegionHandler handler) {
+ if (fStructuredDocumentRegionHandlers == null)
+ return;
+ if (fStructuredDocumentRegionHandlers.contains(handler))
+ fStructuredDocumentRegionHandlers.remove(handler);
+ }
+
+ /**
+ * Resets the input.
+ */
+ public void reset(java.io.FileInputStream instream) {
+ primReset();
+ //fInput = instream;
+ getTokenizer().reset(instream);
+ }
+
+ /**
+ * Resets the input.
+ */
+ public void reset(java.io.Reader reader) {
+ reset(reader, 0);
+ }
+
+ /**
+ * Resets the input.
+ */
+ public void reset(java.io.Reader reader, int position) {
+ primReset();
+ fOffset = position;
+ getTokenizer().reset(reader, position);
+ if (reader instanceof DocumentReader) {
+ IDocument doc = ((DocumentReader) reader).getDocument();
+ if (doc instanceof CharSequence) {
+ fCharSequenceSource = (CharSequence) doc;
+ } else {
+ // old fashioned IDocument
+ fDocumentInput = ((DocumentReader) reader).getDocument();
+ }
+
+ } else if (reader instanceof CharSequenceReader) {
+ fCharSequenceSource = ((CharSequenceReader) reader).getOriginalSource();
+ }
+ }
+
+ /**
+ * Resets the input. Use this version to allow text to be retrieved
+ * <em>during</em> parsing, such as by the
+ * StructuredDocumentRegionHandler.
+ */
+ public void reset(String sourceString) {
+ reset(new StringReader(sourceString));
+ fStringInput = sourceString;
+ }
+
+ /**
+ * Resets the input. Use this version to allow text to be retrieved
+ * <em>during</em> parsing, such as by the
+ * StructuredDocumentRegionHandler.
+ */
+ public void reset(String sourceString, int position) {
+ StringReader reader = new StringReader(sourceString);
+ reset(reader, position);
+ fStringInput = sourceString;
+ }
+
+ public void resetHandlers() {
+ if (fStructuredDocumentRegionHandlers != null) {
+ int size = fStructuredDocumentRegionHandlers.size();
+ for (int i = 0; i < size; i++)
+ ((StructuredDocumentRegionHandler) fStructuredDocumentRegionHandlers.get(i)).resetNodes();
+ }
+ }
+
+ /**
+ *
+ * @param List
+ */
+ public void setStructuredDocumentRegionHandlers(List newStructuredDocumentRegionHandlers) {
+ fStructuredDocumentRegionHandlers = newStructuredDocumentRegionHandlers;
+ }
+
+ protected void setTokenizer(BlockTokenizer newTokenizer) {
+ // DMW: changed from private to protected, so subclass could use in
+ // creation of 'newInstance'.
+ fTokenizer = newTokenizer;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredDocumentReParser.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredDocumentReParser.java
new file mode 100644
index 0000000000..518d4f63c6
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredDocumentReParser.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+import org.eclipse.wst.sse.core.internal.text.StructuredDocumentReParser;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.IStructuredTextReParser;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class XMLStructuredDocumentReParser extends StructuredDocumentReParser {
+
+ public XMLStructuredDocumentReParser() {
+ super();
+ }
+
+ protected IStructuredDocumentRegion findDirtyEnd(int end) {
+ // Caution: here's one place we have to cast
+ IStructuredDocumentRegion result = fStructuredDocument.getRegionAtCharacterOffset(end);
+ // if not well formed, get one past, if there is something there
+ if ((result != null) && (!result.isEnded())) {
+ if (result.getNext() != null) {
+ result = result.getNext();
+ }
+ }
+ // also, get one past if exactly equal to the end (this was needed
+ // as a simple fix to when a whole exact region is deleted.
+ // there's probably a better way.
+ if ((result != null) && (end == result.getEnd())) {
+ if (result.getNext() != null) {
+ result = result.getNext();
+ }
+ }
+
+ // 12/6/2001 - Since we've changed the parser/scanner to allow a lone
+ // '<' without
+ // always interpretting it as start of a tag name, we need to be a
+ // little fancier, in order
+ // to "skip" over any plain 'ol content between the lone '<' and any
+ // potential meating
+ // regions past plain 'ol content.
+ if (isLoneOpenFollowedByContent(result) && (result.getNext() != null)) {
+ result = result.getNext();
+ }
+
+ if (result != null)
+ fStructuredDocument.setCachedDocumentRegion(result);
+ dirtyEnd = result;
+
+ return dirtyEnd;
+ }
+
+ protected void findDirtyStart(int start) {
+ IStructuredDocumentRegion result = fStructuredDocument.getRegionAtCharacterOffset(start);
+ // heuristic: if the postion is exactly equal to the start, then
+ // go back one more, if it exists. This prevents problems with
+ // insertions
+ // of text that should be merged with the previous node instead of
+ // simply hung
+ // off of it as a separate node (ex.: XML content inserted right
+ // before an open
+ // bracket should become part of the previous content node)
+ if (result != null) {
+ IStructuredDocumentRegion previous = result.getPrevious();
+ if ((previous != null) && ((!(previous.isEnded())) || (start == result.getStart()))) {
+ result = previous;
+ }
+ // If we are now at the end of a "tag dependent" content area (or
+ // JSP area)
+ // then we need to back up all the way to the beginning of that.
+ IStructuredDocumentRegion potential = result;
+ while (isPartOfBlockRegion(potential)) {
+ potential = potential.getPrevious();
+ }
+ if (potential != null) {
+ result = potential;
+ fStructuredDocument.setCachedDocumentRegion(result);
+ }
+ }
+ dirtyStart = result;
+ }
+
+ /**
+ * The rule is, that is we are content, preceded by lone <, then we need
+ * to advance one more for dirty end.
+ */
+ protected boolean isLoneOpenFollowedByContent(IStructuredDocumentRegion flatNode) {
+ boolean result = false;
+ String type = flatNode.getType();
+ if (type == XMLRegionContext.XML_CONTENT) {
+ IStructuredDocumentRegion previous = flatNode.getPrevious();
+ String previousType = null;
+ if (previous != null) {
+ previousType = previous.getType();
+ }
+ if (previousType != null) {
+ result = (previousType == XMLRegionContext.XML_TAG_OPEN);
+ }
+ }
+ return result;
+ }
+
+ protected boolean isPartOfBlockRegion(IStructuredDocumentRegion flatNode) {
+ boolean result = false;
+ String type = flatNode.getType();
+ result = (type == XMLRegionContext.BLOCK_TEXT || type == XMLJSPRegionContexts.JSP_CONTENT);
+ return result;
+ }
+
+ public IStructuredTextReParser newInstance() {
+ return new XMLStructuredDocumentReParser();
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredRegionFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredRegionFactory.java
new file mode 100644
index 0000000000..0411d664e2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLStructuredRegionFactory.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.internal.text.XMLStructuredDocumentRegion;
+
+
+/**
+ * A simple class to generate instances of StructuredRegions.
+ */
+public class XMLStructuredRegionFactory {
+ public final static int JSP_DIRECTIVE = 1003;
+ public final static int XML = 1001;
+ public final static int XML_BLOCK = 1002;
+
+ public static IStructuredDocumentRegion createRegion(int type) {
+ IStructuredDocumentRegion instance = null;
+ switch (type) {
+ case XML :
+ instance = new XMLStructuredDocumentRegion();
+ break;
+ case XML_BLOCK :
+ instance = new BlockStructuredDocumentRegion();
+ break;
+ default :
+ throw new IllegalArgumentException("AbstractRegion::createRegion. Invalid type."); //$NON-NLS-1$
+ }
+ return instance;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLTokenizer.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLTokenizer.java
new file mode 100644
index 0000000000..5f1101f1f8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/XMLTokenizer.java
@@ -0,0 +1,1699 @@
+/*******************************************************************************
+ * Copyright (c) 2004 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
+ *******************************************************************************/
+/* The following code was generated by JFlex 1.2.2 on 9/23/04 1:31 AM */
+
+/*nlsXXX*/
+package org.eclipse.wst.xml.core.internal.parser;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.parser.BlockMarker;
+import org.eclipse.wst.sse.core.parser.BlockTokenizer;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.xml.core.Logger;
+import org.eclipse.wst.xml.core.internal.parser.regions.XMLParserRegionFactory;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+
+/**
+ * This class is a scanner generated by <a
+ * href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex </a> 1.2.2
+ * on 9/23/04 1:31 AM from the specification file
+ * <tt>file:/D:/eclipse.rad/workspace.rad/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/XMLTokenizer.jflex</tt>
+ */
+public class XMLTokenizer implements BlockTokenizer, XMLRegionContext {
+
+ /** this character denotes the end of file */
+ final public static int YYEOF = -1;
+
+ /** lexical states */
+ final public static int ST_XML_DOCTYPE_EXTERNAL_ID = 23;
+ final public static int ST_XML_ELEMENT_DECLARATION_CONTENT = 27;
+ final public static int ST_DHTML_ATTRIBUTE_NAME = 12;
+ final public static int ST_XML_PI_TAG_CLOSE = 11;
+ final public static int ST_XML_DECLARATION_CLOSE = 21;
+ final public static int ST_XML_PI_ATTRIBUTE_VALUE = 10;
+ final public static int ST_DHTML_EQUALS = 13;
+ final public static int ST_XML_TAG_NAME = 16;
+ final public static int ST_XML_ATTRIBUTE_VALUE = 19;
+ final public static int ST_DHTML_ATTRIBUTE_VALUE = 14;
+ final public static int ST_XML_DOCTYPE_ID_SYSTEM = 25;
+ final public static int ST_XML_ATTRIBUTE_NAME = 17;
+ final public static int ST_XML_ELEMENT_DECLARATION = 26;
+ final public static int ST_XML_DOCTYPE_DECLARATION = 22;
+ final public static int ST_XML_ATTLIST_DECLARATION = 28;
+ final public static int ST_XML_COMMENT_END = 4;
+ final public static int ST_CDATA_TEXT = 1;
+ final public static int ST_DHTML_TAG_CLOSE = 15;
+ final public static int ST_XML_COMMENT = 3;
+ final public static int ST_PI_CONTENT = 7;
+ final public static int ST_PI_WS = 6;
+ final public static int ST_CDATA_END = 2;
+ final public static int ST_XML_ATTLIST_DECLARATION_CONTENT = 29;
+ final public static int ST_BLOCK_TAG_SCAN = 30;
+ final public static int ST_XML_PI_EQUALS = 9;
+ final public static int ST_XML_DECLARATION = 20;
+ final public static int YYINITIAL = 0;
+ final public static int ST_XML_DOCTYPE_ID_PUBLIC = 24;
+ final public static int ST_XML_EQUALS = 18;
+ final public static int ST_PI = 5;
+ final public static int ST_XML_PI_ATTRIBUTE_NAME = 8;
+
+ /**
+ * Translates characters to character classes
+ */
+ final private static String yycmap_packed = "\11\0\1\5\1\22\2\0\1\14\22\0\1\14\1\21\1\11\1\51" + "\1\16\1\17\1\12\1\13\1\16\1\16\1\16\1\16\1\16\1\7" + "\1\6\1\3\12\15\1\10\1\54\1\1\1\43\1\2\1\4\1\16" + "\1\32\1\55\1\30\1\31\1\35\1\52\1\34\1\34\1\40\1\34" + "\1\34\1\26\1\25\1\42\1\41\1\45\1\34\1\36\1\37\1\33" + "\1\53\2\34\1\23\1\44\1\34\1\27\1\0\1\20\1\0\1\10" + "\1\0\1\47\1\55\1\56\1\50\1\35\1\52\1\34\1\34\1\40" + "\2\34\1\26\1\25\1\42\1\41\1\45\1\34\1\36\1\37\1\46" + "\1\53\1\34\1\34\1\24\1\44\1\34\1\0\1\0\72\0\1\60" + "\10\0\27\57\1\0\37\57\1\0\72\57\2\0\13\57\2\0\10\57" + "\1\0\65\57\1\0\104\57\11\0\44\57\3\0\2\57\4\0\36\57" + "\70\0\131\57\22\0\7\57\16\0\2\60\56\0\106\60\32\0\2\60" + "\44\0\1\57\1\60\3\57\1\0\1\57\1\0\24\57\1\0\54\57" + "\1\0\7\57\3\0\1\57\1\0\1\57\1\0\1\57\1\0\1\57" + "\1\0\22\57\15\0\14\57\1\0\102\57\1\0\14\57\1\0\44\57" + "\1\0\4\60\11\0\65\57\2\0\2\57\2\0\2\57\3\0\34\57" + "\2\0\10\57\2\0\2\57\67\0\46\57\2\0\1\57\7\0\46\57"
+ + "\12\0\21\60\1\0\27\60\1\0\3\60\1\0\1\60\1\0\2\60" + "\1\0\1\60\13\0\33\57\5\0\3\57\56\0\32\57\5\0\1\60" + "\12\57\10\60\15\0\12\60\6\0\1\60\107\57\2\0\5\57\1\0" + "\17\57\1\0\4\57\1\0\1\57\17\60\2\57\2\60\1\0\4\60" + "\2\0\12\60\u0207\0\3\60\1\0\65\57\2\0\1\60\1\57\20\60" + "\3\0\4\60\3\0\12\57\2\60\2\0\12\60\21\0\3\60\1\0" + "\10\57\2\0\2\57\2\0\26\57\1\0\7\57\1\0\1\57\3\0" + "\4\57\2\0\1\60\1\0\7\60\2\0\2\60\2\0\3\60\11\0" + "\1\60\4\0\2\57\1\0\3\57\2\60\2\0\12\60\2\57\20\0" + "\1\60\2\0\6\57\4\0\2\57\2\0\26\57\1\0\7\57\1\0" + "\2\57\1\0\2\57\1\0\2\57\2\0\1\60\1\0\5\60\4\0" + "\2\60\2\0\3\60\13\0\4\57\1\0\1\57\7\0\12\60\2\60" + "\3\57\14\0\3\60\1\0\7\57\1\0\1\57\1\0\3\57\1\0" + "\26\57\1\0\7\57\1\0\2\57\1\0\5\57\2\0\1\60\1\57" + "\10\60\1\0\3\60\1\0\3\60\22\0\1\57\5\0\12\60\21\0" + "\3\60\1\0\10\57\2\0\2\57\2\0\26\57\1\0\7\57\1\0" + "\2\57\2\0\4\57\2\0\1\60\1\57\6\60\3\0\2\60\2\0" + "\3\60\10\0\2\60\4\0\2\57\1\0\3\57\4\0\12\60\22\0"
+ + "\2\60\1\0\6\57\3\0\3\57\1\0\4\57\3\0\2\57\1\0" + "\1\57\1\0\2\57\3\0\2\57\3\0\3\57\3\0\10\57\1\0" + "\3\57\4\0\5\60\3\0\3\60\1\0\4\60\11\0\1\60\17\0" + "\11\60\21\0\3\60\1\0\10\57\1\0\3\57\1\0\27\57\1\0" + "\12\57\1\0\5\57\4\0\7\60\1\0\3\60\1\0\4\60\7\0" + "\2\60\11\0\2\57\4\0\12\60\22\0\2\60\1\0\10\57\1\0" + "\3\57\1\0\27\57\1\0\12\57\1\0\5\57\4\0\7\60\1\0" + "\3\60\1\0\4\60\7\0\2\60\7\0\1\57\1\0\2\57\4\0" + "\12\60\22\0\2\60\1\0\10\57\1\0\3\57\1\0\27\57\1\0" + "\20\57\4\0\6\60\2\0\3\60\1\0\4\60\11\0\1\60\10\0" + "\2\57\4\0\12\60\221\0\56\57\1\0\1\57\1\60\2\57\7\60" + "\5\0\6\57\1\60\10\60\1\0\12\60\47\0\2\57\1\0\1\57" + "\2\0\2\57\1\0\1\57\2\0\1\57\6\0\4\57\1\0\7\57" + "\1\0\3\57\1\0\1\57\1\0\1\57\2\0\2\57\1\0\2\57" + "\1\0\1\57\1\60\2\57\6\60\1\0\2\60\1\57\2\0\5\57" + "\1\0\1\60\1\0\6\60\2\0\12\60\76\0\2\60\6\0\12\60" + "\13\0\1\60\1\0\1\60\1\0\1\60\4\0\2\60\10\57\1\0" + "\41\57\7\0\24\60\1\0\6\60\4\0\6\60\1\0\1\60\1\0"
+ + "\25\60\3\0\7\60\1\0\1\60\346\0\46\57\12\0\47\57\11\0" + "\1\57\1\0\2\57\1\0\3\57\1\0\1\57\1\0\2\57\1\0" + "\5\57\51\0\1\57\1\0\1\57\1\0\1\57\13\0\1\57\1\0" + "\1\57\1\0\1\57\3\0\2\57\3\0\1\57\5\0\3\57\1\0" + "\1\57\1\0\1\57\1\0\1\57\1\0\1\57\3\0\2\57\3\0" + "\2\57\1\0\1\57\50\0\1\57\11\0\1\57\2\0\1\57\2\0" + "\2\57\7\0\2\57\1\0\1\57\1\0\7\57\50\0\1\57\4\0" + "\1\57\10\0\1\57\u0c06\0\234\57\4\0\132\57\6\0\26\57\2\0" + "\6\57\2\0\46\57\2\0\6\57\2\0\10\57\1\0\1\57\1\0" + "\1\57\1\0\1\57\1\0\37\57\2\0\65\57\1\0\7\57\1\0" + "\1\57\3\0\3\57\1\0\7\57\3\0\4\57\2\0\6\57\4\0" + "\15\57\5\0\3\57\1\0\7\57\323\0\15\60\4\0\1\60\104\0" + "\1\57\3\0\2\57\2\0\1\57\121\0\3\57\u0e82\0\1\60\1\0" + "\1\57\31\0\11\57\6\60\1\0\5\60\13\0\124\57\4\0\2\60" + "\2\0\2\60\2\0\132\57\1\0\3\60\6\0\50\57\u1cd3\0\u51a6\57" + "\u0c5a\0\u2ba4\57\134\0\u0800\0\u1ffe\0\2\0";
+
+ /**
+ * Translates characters to character classes
+ */
+ final private static char[] yycmap = yy_unpack_cmap(yycmap_packed);
+
+ /**
+ * Translates a state to a row index in the transition table
+ */
+ final private static int yy_rowMap[] = {0, 49, 98, 147, 196, 245, 294, 343, 392, 441, 490, 539, 588, 637, 686, 735, 784, 833, 882, 931, 980, 1029, 1078, 1127, 1176, 1225, 1274, 1323, 1372, 1421, 1470, 1519, 1568, 1617, 1666, 1715, 1764, 1715, 1764, 1813, 1715, 1715, 1764, 1862, 1911, 1960, 2009, 2058, 2107, 2156, 1715, 1764, 2205, 2254, 2303, 1715, 2352, 2352, 2401, 2450, 2499, 2205, 1715, 2548, 2597, 1715, 2646, 2695, 2744, 2793, 2842, 2891, 1715, 2940, 2989, 3038, 3087, 1715, 3136, 3185, 3234, 3283, 3332, 1715, 3381, 3430, 3479, 3528, 3577, 3626, 3675, 3724, 3724, 3773, 3822, 3871, 3920, 3920, 3969, 4018, 4067, 4116, 4116, 4165, 4214, 4263, 4312, 1715, 4361, 4361, 4410, 4459, 4508, 4557, 1715, 1715, 1764, 1715, 1715, 4606, 4655, 4704, 4753, 4802, 4851, 4900, 4949, 1715, 4998, 5047, 1715, 1715, 2352, 5096, 2450, 1715, 5145, 2499, 2548, 2646, 2695, 5194, 2744, 1715, 5243, 2793, 1715, 3136, 5292, 3234, 1715, 5341, 3283, 4606, 5390, 5439, 5488, 3528, 1715, 5537, 5586, 3724, 5635,
+ 3773, 1715, 5684, 5733, 5782, 5782, 5831, 5880, 3871, 3724, 3920, 5929, 3969, 1715, 5978, 4018, 4067, 3920, 4116, 6027, 4165, 1715, 6076, 6125, 6174, 6174, 6223, 6272, 6321, 4361, 6370, 4410, 1715, 6419, 6468, 6517, 6517, 6566, 6615, 6664, 6713, 6762, 6811, 6860, 1715, 6909, 6958, 1715, 1715, 1715, 2009, 7007, 7056, 7105, 7154, 7203, 7252, 5684, 7301, 7301, 6076, 7350, 7350, 7399, 6419, 7448, 7448, 7497, 1715, 7546, 7595, 1715, 7644, 7693, 7742, 7791, 7840, 7889, 7938, 5831, 6223, 7987, 6566, 8036, 8085, 8134, 8183, 8232, 8281, 8330, 8379, 8428, 8477, 8526, 2009, 8575, 8624, 8673, 1715, 1715, 8722, 8771, 8820, 1715, 1715, 1715, 8869, 8918, 8967, 9016, 9065, 1715, 4263, 4508};
+
+ /**
+ * The packed transition table of the DFA
+ */
+ final private static String yy_packed = "\1\40\1\41\10\40\1\42\4\40\1\43\41\40\1\44" + "\1\45\57\44\1\46\1\47\16\46\1\50\1\46\1\51" + "\36\46\1\52\1\53\57\52\1\46\1\47\5\46\1\54" + "\12\46\1\51\37\46\1\47\2\46\1\55\1\56\2\46" + "\1\57\3\46\1\56\5\46\1\56\2\60\2\57\1\46" + "\10\57\1\61\2\57\1\46\5\57\1\46\2\57\1\46" + "\3\57\2\46\1\47\2\46\1\55\1\62\6\46\1\62" + "\5\46\1\62\36\46\1\63\1\64\2\63\1\65\15\63" + "\1\51\36\63\1\46\1\47\2\46\1\66\1\56\2\46" + "\1\67\3\46\1\56\5\46\1\56\4\67\1\46\13\67" + "\1\46\5\67\1\46\2\67\1\46\3\67\2\46\1\47" + "\2\46\1\66\1\56\2\46\1\67\3\46\1\56\5\46" + "\1\56\4\67\1\46\13\67\1\70\5\67\1\46\2\67" + "\1\46\3\67\1\46\1\71\1\47\1\46\1\72\1\73" + "\1\56\3\71\1\74\1\71\1\75\1\56\5\71\1\56" + "\36\71\1\46\1\47\2\46\1\76\15\46\1\51\37\46" + "\1\47\1\77\1\100\1\46\1\56\2\46\1\101\3\46" + "\1\56\5\46\1\56\4\101\1\46\13\101\1\46\5\101" + "\1\46\2\101\1\46\3\101\2\46\1\47\1\77\1\100" + "\1\46\1\56\2\46\1\101\3\46\1\56\5\46\1\56"
+ + "\4\101\1\46\13\101\1\102\5\101\1\46\2\101\1\46" + "\3\101\1\46\1\103\1\47\1\77\1\104\1\103\1\56" + "\3\103\1\105\1\103\1\106\1\56\5\103\1\56\36\103" + "\1\46\1\47\3\46\1\56\6\46\1\56\5\46\1\56" + "\36\46\1\107\1\110\1\111\1\112\4\107\1\113\12\107" + "\4\114\1\107\13\114\1\107\5\114\1\107\2\114\1\107" + "\3\114\1\107\1\46\1\110\1\111\1\112\1\46\1\56" + "\2\46\1\115\3\46\1\56\5\46\1\56\4\115\1\46" + "\13\115\1\46\5\115\1\46\2\115\1\46\3\115\2\46" + "\1\110\1\111\1\112\1\46\1\56\2\46\1\115\3\46" + "\1\56\5\46\1\56\4\115\1\46\13\115\1\116\5\115" + "\1\46\2\115\1\46\3\115\1\46\1\117\1\110\1\111" + "\1\120\1\117\1\56\3\117\1\121\1\117\1\122\1\56" + "\5\117\1\56\36\117\1\46\1\123\1\124\2\46\1\56" + "\6\46\1\56\5\46\1\56\6\46\1\125\1\126\2\46" + "\1\127\11\46\1\126\1\125\11\46\1\47\1\124\2\46" + "\1\56\6\46\1\56\5\46\1\56\4\46\1\130\32\46" + "\1\47\1\124\2\46\1\56\2\46\1\131\3\46\1\56" + "\5\46\1\56\4\131\1\130\13\131\1\46\5\131\1\46"
+ + "\2\131\1\46\3\131\2\46\1\47\1\124\2\46\1\56" + "\6\46\1\56\5\46\1\56\4\46\1\130\7\46\1\132" + "\5\46\1\133\13\46\1\134\1\47\1\124\1\135\1\134" + "\1\56\3\134\1\136\1\134\1\137\1\56\5\134\1\56" + "\4\134\1\140\31\134\1\141\1\47\1\124\1\142\1\141" + "\1\56\3\141\1\143\1\141\1\144\1\56\5\141\1\56" + "\4\141\1\145\31\141\1\146\1\47\1\124\1\147\1\146" + "\1\56\3\146\1\150\1\146\1\151\1\56\5\146\1\56" + "\36\146\1\152\1\153\1\154\56\152\1\155\1\47\1\124" + "\1\156\1\155\1\56\3\155\1\157\1\155\1\160\1\56" + "\5\155\1\56\36\155\1\161\1\162\1\163\56\161\1\164" + "\1\165\57\164\1\40\1\0\10\40\1\0\4\40\1\0" + "\41\40\3\0\1\166\1\167\14\0\1\170\44\0\1\171" + "\2\0\1\172\3\0\1\171\5\0\1\171\4\172\1\0" + "\13\172\1\0\5\172\1\173\2\172\1\0\3\172\6\0" + "\1\171\2\0\1\174\3\0\1\171\5\0\1\171\4\174" + "\1\0\13\174\1\0\5\174\1\0\2\174\1\0\3\174" + "\103\0\1\175\57\0\1\176\47\0\1\177\53\0\1\200" + "\63\0\1\56\6\0\1\56\5\0\1\56\44\0\3\57" + "\4\0\1\57\5\0\4\57\1\0\13\57\1\0\5\57"
+ + "\1\0\2\57\1\0\4\57\6\0\3\57\4\0\1\57" + "\5\0\2\57\1\201\1\57\1\0\13\57\1\0\5\57" + "\1\0\2\57\1\0\4\57\6\0\3\57\4\0\1\57" + "\5\0\2\57\1\202\1\57\1\0\13\57\1\0\5\57" + "\1\0\2\57\1\0\4\57\5\0\1\62\6\0\1\62" + "\5\0\1\62\40\0\1\203\60\0\1\204\64\0\3\67" + "\4\0\1\67\5\0\4\67\1\0\13\67\1\0\5\67" + "\1\0\2\67\1\0\4\67\1\71\2\0\1\205\1\71" + "\1\0\3\71\1\0\1\71\2\0\5\71\1\0\37\71" + "\1\0\1\204\1\205\1\71\1\0\3\71\1\0\1\71" + "\2\0\5\71\1\0\36\71\1\74\1\0\1\206\1\207" + "\1\74\1\206\3\74\1\210\1\74\2\206\5\74\1\206" + "\36\74\1\75\1\0\1\211\1\212\1\75\1\211\3\75" + "\1\211\1\75\1\210\1\211\5\75\1\211\36\75\2\0" + "\1\77\1\213\63\0\3\101\4\0\1\101\5\0\4\101" + "\1\0\13\101\1\0\5\101\1\0\2\101\1\0\4\101" + "\1\103\2\0\1\214\1\103\1\0\3\103\1\0\1\103" + "\2\0\5\103\1\0\37\103\1\0\1\77\1\215\1\103" + "\1\0\3\103\1\0\1\103\2\0\5\103\1\0\36\103" + "\1\105\1\0\1\216\1\217\1\105\1\216\3\105\1\220" + "\1\105\2\216\5\105\1\216\36\105\1\106\1\0\1\221"
+ + "\1\222\1\106\1\221\3\106\1\221\1\106\1\220\1\221" + "\5\106\1\221\36\106\1\107\3\0\17\107\4\0\1\107" + "\13\0\1\107\5\0\1\107\2\0\1\107\3\0\1\107" + "\3\0\1\166\15\0\1\170\41\0\1\223\56\0\1\107" + "\3\0\2\107\3\113\4\107\1\113\5\107\4\114\1\107" + "\13\114\1\107\5\114\1\107\2\114\1\107\3\114\1\113" + "\6\0\3\114\4\0\1\114\5\0\4\114\1\0\13\114" + "\1\0\5\114\1\0\2\114\1\0\4\114\6\0\3\115" + "\4\0\1\115\5\0\4\115\1\0\13\115\1\0\5\115" + "\1\0\2\115\1\0\4\115\1\117\2\0\1\224\1\117" + "\1\0\3\117\1\0\1\117\2\0\5\117\1\0\37\117" + "\1\0\1\223\1\224\1\117\1\0\3\117\1\0\1\117" + "\2\0\5\117\1\0\36\117\1\121\1\0\1\225\1\226" + "\1\121\1\225\3\121\1\227\1\121\2\225\5\121\1\225" + "\36\121\1\122\1\0\1\230\1\231\1\122\1\230\3\122" + "\1\230\1\122\1\227\1\230\5\122\1\230\36\122\3\0" + "\1\166\15\0\1\232\100\0\1\233\52\0\1\234\12\0" + "\1\234\40\0\1\235\32\0\20\236\1\237\40\236\6\0" + "\3\131\4\0\1\131\5\0\4\131\1\0\13\131\1\0" + "\5\131\1\0\2\131\1\0\4\131\44\0\1\240\67\0"
+ + "\1\241\5\0\1\134\2\0\1\242\1\134\1\0\3\134" + "\1\0\1\134\2\0\5\134\1\0\36\134\1\136\1\0" + "\1\243\1\244\1\136\1\243\3\136\1\245\1\136\2\243" + "\5\136\1\243\36\136\1\246\1\0\1\247\1\250\1\251" + "\1\247\3\251\1\247\1\246\1\252\1\253\3\251\1\246" + "\1\251\1\253\4\251\1\246\27\251\2\246\1\140\2\236" + "\1\254\1\140\1\236\3\140\1\236\1\140\2\236\3\140" + "\1\255\1\140\1\236\36\140\1\141\2\0\1\256\1\141" + "\1\0\3\141\1\0\1\141\2\0\5\141\1\0\36\141" + "\1\143\2\257\1\260\1\143\1\257\3\143\1\261\1\143" + "\2\257\5\143\1\257\36\143\1\144\2\262\1\263\1\144" + "\1\262\3\144\1\262\1\144\1\261\1\262\5\144\1\262" + "\36\144\1\145\2\236\1\264\1\145\1\236\3\145\1\236" + "\1\145\2\236\3\145\1\265\1\145\1\236\36\145\1\146" + "\2\0\1\266\1\146\1\0\3\146\1\0\1\146\2\0" + "\5\146\1\0\36\146\1\150\1\0\1\267\1\270\1\150" + "\1\267\3\150\1\271\1\150\2\267\5\150\1\267\36\150" + "\1\272\1\0\1\273\1\274\1\275\1\273\3\275\1\273" + "\1\272\1\276\1\277\3\275\1\272\1\275\1\277\4\275"
+ + "\1\272\27\275\2\272\2\152\1\0\60\152\1\0\16\152" + "\1\300\37\152\1\155\2\0\1\301\1\155\1\0\3\155" + "\1\0\1\155\2\0\5\155\1\0\36\155\1\157\1\0" + "\1\302\1\303\1\157\1\302\3\157\1\304\1\157\2\302" + "\5\157\1\302\36\157\1\305\1\0\1\306\1\307\1\310" + "\1\306\3\310\1\306\1\305\1\311\1\312\3\310\1\305" + "\1\310\1\312\4\310\1\305\27\310\2\305\2\161\1\0" + "\60\161\1\0\16\161\1\313\37\161\7\0\1\314\17\0" + "\1\315\36\0\1\171\2\0\1\40\3\0\1\171\5\0" + "\1\171\4\40\1\0\13\40\1\0\5\40\1\0\2\40" + "\1\0\3\40\1\0\1\316\1\0\3\316\1\317\3\172" + "\1\316\1\0\1\316\1\317\1\172\1\316\1\0\2\316" + "\1\317\4\172\1\316\13\172\1\316\5\172\1\316\2\172" + "\1\320\4\172\15\0\1\321\6\0\1\322\34\0\1\316" + "\1\0\3\316\1\317\3\174\1\316\1\0\1\316\1\317" + "\1\174\1\316\1\0\2\316\1\317\4\174\1\316\13\174" + "\1\316\5\174\1\316\2\174\1\323\4\174\27\0\1\315" + "\33\0\1\324\60\0\1\325\64\0\3\57\4\0\1\57" + "\5\0\3\57\1\326\1\0\13\57\1\0\5\57\1\0" + "\2\57\1\0\4\57\6\0\3\57\4\0\1\57\5\0"
+ + "\4\57\1\0\13\57\1\0\1\57\1\327\3\57\1\0" + "\2\57\1\0\4\57\1\206\1\0\7\206\1\210\47\206" + "\1\211\1\0\11\211\1\210\45\211\1\216\1\0\7\216" + "\1\220\47\216\1\221\1\0\11\221\1\220\45\221\1\225" + "\1\0\7\225\1\227\47\225\1\230\1\0\11\230\1\227" + "\45\230\30\0\1\330\25\0\1\330\35\0\1\331\12\0" + "\1\331\47\0\1\332\62\0\1\333\76\0\1\334\3\0" + "\1\243\1\0\7\243\1\245\47\243\1\246\1\0\1\247" + "\1\335\1\246\1\247\3\246\1\247\1\246\1\245\1\247" + "\5\246\1\247\36\246\1\247\1\0\11\247\1\245\45\247" + "\1\246\1\0\1\247\1\335\1\246\1\247\3\246\1\247" + "\1\246\1\336\1\247\5\246\1\247\36\246\13\0\1\337" + "\45\0\1\247\1\0\11\247\1\336\45\247\11\257\1\261" + "\47\257\13\262\1\261\45\262\1\267\1\0\7\267\1\271" + "\47\267\1\272\1\0\1\273\1\340\1\272\1\273\3\272" + "\1\273\1\272\1\271\1\273\5\272\1\273\36\272\1\273" + "\1\0\11\273\1\271\45\273\1\272\1\0\1\273\1\340" + "\1\272\1\273\3\272\1\273\1\272\1\341\1\273\5\272" + "\1\273\36\272\13\0\1\342\45\0\1\273\1\0\11\273"
+ + "\1\341\45\273\2\152\1\0\24\152\1\343\31\152\1\302" + "\1\0\7\302\1\304\47\302\1\305\1\0\1\306\1\344" + "\1\305\1\306\3\305\1\306\1\305\1\304\1\306\5\305" + "\1\306\36\305\1\306\1\0\11\306\1\304\45\306\1\305" + "\1\0\1\306\1\344\1\305\1\306\3\305\1\306\1\305" + "\1\345\1\306\5\305\1\306\36\305\13\0\1\346\45\0" + "\1\306\1\0\11\306\1\345\45\306\2\161\1\0\24\161" + "\1\347\31\161\7\0\1\350\101\0\1\351\30\0\1\316" + "\1\0\10\316\1\0\4\316\1\0\34\316\1\0\5\316" + "\1\0\3\316\1\317\4\316\1\0\1\316\1\317\2\316" + "\1\0\2\316\1\317\31\316\1\352\4\316\15\0\1\321" + "\36\0\1\353\21\0\1\354\12\0\3\354\2\0\1\354" + "\11\0\2\354\1\0\1\354\2\0\2\354\10\0\3\57" + "\4\0\1\57\5\0\4\57\1\0\11\57\1\355\1\57" + "\1\0\5\57\1\0\2\57\1\0\4\57\33\0\1\356" + "\12\0\1\356\40\0\1\357\57\0\1\360\66\0\1\361" + "\12\0\1\361\40\0\1\362\35\0\2\363\1\0\3\363" + "\2\0\1\252\4\363\1\0\6\363\1\0\27\363\5\0" + "\2\364\1\0\3\364\2\0\1\276\4\364\1\0\6\364"
+ + "\1\0\27\364\2\0\2\152\1\0\25\152\1\365\30\152" + "\3\0\2\366\1\0\3\366\2\0\1\311\4\366\1\0" + "\6\366\1\0\27\366\2\0\2\161\1\0\25\161\1\367" + "\30\161\31\0\1\370\103\0\1\352\21\0\1\354\12\0" + "\3\354\2\0\1\354\11\0\2\354\1\0\1\354\1\0" + "\1\353\2\354\10\0\3\57\4\0\1\57\5\0\4\57" + "\1\0\6\57\1\371\4\57\1\0\5\57\1\0\2\57" + "\1\0\4\57\44\0\1\372\54\0\1\373\55\0\1\374" + "\60\0\1\375\63\0\1\376\20\0\2\152\1\0\26\152" + "\1\377\27\152\2\161\1\0\26\161\1\u0100\27\161\32\0" + "\1\u0101\34\0\3\57\4\0\1\57\5\0\4\57\1\0" + "\3\57\1\u0102\7\57\1\0\2\57\1\u0102\2\57\1\0" + "\2\57\1\0\4\57\45\0\1\u0103\52\0\1\u0104\63\0" + "\1\u0105\43\0\1\u0106\63\0\1\u0107\25\0\1\u0107\2\0" + "\2\152\1\0\27\152\1\u0108\26\152\2\161\1\0\27\161" + "\1\u0109\26\161\33\0\1\u010a\62\0\1\u010b\56\0\1\u010c" + "\12\0\1\u010c\45\0\1\u010d\12\0\1\u010d\12\0\2\152" + "\1\0\30\152\1\u010e\25\152\2\161\1\0\30\161\1\u010f" + "\25\161\32\0\1\u0110\26\0\2\152\1\0\27\152\1\u0111"
+ + "\26\152\2\161\1\0\27\161\1\u0112\26\161\27\0\1\u0113" + "\31\0\2\152\1\0\24\152\1\u0114\31\152\2\161\1\0" + "\24\161\1\u0115\31\161";
+
+ /**
+ * The transition table of the DFA
+ */
+ final private static int yytrans[] = yy_unpack(yy_packed);
+
+
+ /* error codes */
+ final private static int YY_UNKNOWN_ERROR = 0;
+ // final private static int YY_ILLEGAL_STATE = 1;
+ final private static int YY_NO_MATCH = 2;
+ final private static int YY_PUSHBACK_2BIG = 3;
+
+ /* error messages for the codes above */
+ final private static String YY_ERROR_MSG[] = {"Unkown internal scanner error", //$NON-NLS-1$
+ "Internal error: unknown state", //$NON-NLS-1$
+ "Error: could not match input", //$NON-NLS-1$
+ "Error: pushback value was too large" //$NON-NLS-1$
+ };
+
+ /**
+ * YY_ATTRIBUTE[aState] contains the attributes of state
+ * <code>aState</code>
+ */
+ private final static byte YY_ATTRIBUTE[] = {1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 9, 1, 9, 1, 1, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 9, 1, 1, 9, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 9, 9, 1, 9, 9, 1, 0, 1, 0, 1, 0, 0, 0, 9, 1, 1, 9, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 9, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 9, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 9, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 9, 0, 0, 9, 9, 9, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 9, 0, 1, 9, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 9, 9, 1, 1, 0, 9, 9, 9, 1, 1, 0, 1, 1, 9, 1, 1};
+
+ /** the input device */
+ private java.io.Reader yy_reader;
+
+ /** the current state of the DFA */
+ private int yy_state;
+
+ /** the current lexical state */
+ private int yy_lexical_state = YYINITIAL;
+
+ /**
+ * this buffer contains the current text to be matched and is the source
+ * of the yytext() string
+ */
+ private char yy_buffer[] = new char[16384];
+
+ /** the textposition at the last accepting state */
+ private int yy_markedPos;
+
+ /** the textposition at the last state to be included in yytext */
+ private int yy_pushbackPos;
+
+ /** the current text position in the buffer */
+ private int yy_currentPos;
+
+ /** startRead marks the beginning of the yytext() string in the buffer */
+ private int yy_startRead;
+
+ /**
+ * endRead marks the last character in the buffer, that has been read from
+ * input
+ */
+ private int yy_endRead;
+
+ /** number of newlines encountered up to the start of the matched text */
+ private int yyline;
+
+ /** the number of characters up to the start of the matched text */
+ private int yychar;
+
+ /**
+ * the number of characters from the last newline up to the start of the
+ * matched text
+ */
+ // private int yycolumn;
+ /**
+ * yy_atBOL == true <=>the scanner is currently at the beginning of a line
+ */
+ // private boolean yy_atBOL;
+ /** yy_atEOF == true <=>the scanner has returned a value for EOF */
+ private boolean yy_atEOF;
+
+ /** denotes if the user-EOF-code has already been executed */
+ private boolean yy_eof_done;
+
+ /* user code: */
+ private int fTokenCount = 0;
+
+ // required holders for white-space compacting
+ private boolean fShouldLoadBuffered = false;
+ private String fBufferedContext = null;
+ private int fBufferedStart = 1;
+ private int fBufferedLength = 0;
+ private ContextRegionContainer fBufferedEmbeddedContainer = null;
+ private String f_context = null;
+
+ // state stack for handling embedded regions
+ private IntStack fStateStack = new IntStack();
+ // a "hint" as to what an embedded region should be evaluated
+ String fEmbeddedHint = UNDEFINED;
+ // a "hint" as to what state to enter once an embedded region has
+ // been completed
+ int fEmbeddedPostState = YYINITIAL;
+ // the container used to create embedded regions
+ private ContextRegionContainer fEmbeddedContainer = null;
+ private static final String PROXY_CONTEXT = "PROXY_CONTEXT";
+
+ private String context = null;
+ private int start = 0;
+ private int textLength = 0;
+ private int length = 0;
+
+ // offset for tracking position specific block tags
+ private int fOffset = 0;
+
+ // the name of the current tag being opened
+ private String fCurrentTagName = null;
+
+ // the list of tag name BlockMarkers
+ private List fBlockMarkers = new ArrayList();
+
+ // required to not seek text blocks on an end tag
+ private boolean fIsBlockingEnabled = false;
+ private boolean fIsCaseSensitiveBlocking = true;
+
+ private XMLParserRegionFactory fRegionFactory = new XMLParserRegionFactory();
+
+ static final String rcsver = "$Id: XMLTokenizer.java,v 1.3 2004/11/11 09:05:07 david_williams Exp $";//$NON-NLS-1$
+
+ /**
+ * user method
+ */
+ public final void addBlockMarker(BlockMarker marker) {
+ if (containsTagName(marker.getTagName()))
+ return;
+ fBlockMarkers.add(marker);
+ }
+
+ /**
+ * user method
+ */
+ public final void removeBlockMarker(BlockMarker marker) {
+ fBlockMarkers.remove(marker);
+ }
+
+ /**
+ * user method
+ */
+ public final void removeBlockMarker(String tagname) {
+ if (fBlockMarkers != null) {
+ Iterator blocks = fBlockMarkers.iterator();
+ while (blocks.hasNext()) {
+ if (((BlockMarker) blocks.next()).getTagName().equals(tagname))
+ blocks.remove();
+ }
+ }
+ }
+
+ /* user method */
+ public final boolean isCaseSensitiveBlocking() {
+ return fIsCaseSensitiveBlocking;
+ }
+
+ /* user method */
+ public final void setCaseSensitiveBlocking(boolean newValue) {
+ fIsCaseSensitiveBlocking = newValue;
+ }
+
+ /* user method */
+ public boolean getBlockMarkerCaseSensitivity() {
+ return getBlockMarkerCaseSensitivity(fCurrentTagName);
+ }
+
+ /* user method */
+ public boolean getBlockMarkerCaseSensitivity(String name) {
+ Iterator iterator = fBlockMarkers.iterator();
+ while (iterator.hasNext()) {
+ BlockMarker marker = (BlockMarker) iterator.next();
+ boolean casesensitive = marker.isCaseSensitive();
+ if (casesensitive && marker.getTagName().equals(name))
+ return casesensitive;
+ else if (!casesensitive && marker.getTagName().equalsIgnoreCase(name))
+ return casesensitive;
+ }
+ return true;
+ }
+
+ /* user method */
+ public String getBlockMarkerContext() {
+ return getBlockMarkerContext(fCurrentTagName);
+ }
+
+ /* user method */
+ public String getBlockMarkerContext(String name) {
+ Iterator iterator = fBlockMarkers.iterator();
+ while (iterator.hasNext()) {
+ BlockMarker marker = (BlockMarker) iterator.next();
+ if (marker.getTagName().equals(name))
+ return marker.getContext();
+ }
+ return BLOCK_TEXT;
+ }
+
+ /* user method */
+ public List getBlockMarkers() {
+ return fBlockMarkers;
+ }
+
+ /* user method */
+ public final int getOffset() {
+ return fOffset + yychar;
+ }
+
+ private final boolean isBlockMarker() {
+ return isBlockMarker(fCurrentTagName);
+ }
+
+ private final boolean isBlockMarker(String tagName) {
+ if (!fIsBlockingEnabled)
+ return false;
+ return containsTagName(tagName);
+ }
+
+ /**
+ * user method
+ */
+ public final void beginBlockTagScan(String newTagName) {
+ beginBlockMarkerScan(newTagName, BLOCK_TEXT);
+ }
+
+ /**
+ * user method
+ *
+ * Special tokenizer setup. Allows tokenization to be initiated at the
+ * start of a text block within a "newTagName" tag.
+ *
+ * Example: Tokenizer toker = new Tokenizer();
+ * toker.setCaseSensitiveBlocking(false); toker.reset(new
+ * java.io.StringReader("afiuhqwkejhtasihgalkwhtq </scripter> </scr>
+ * </script>asgdasga")); toker.beginBlockMarkerScan("script", BLOCK_TEXT);
+ * toker.getRegions();
+ *
+ * Returns: BLOCK_TEXT: 0-40 XML_END_TAG_OPEN: 41-42 XML_TAG_NAME: 43-48
+ * XML_TAG_CLOSE: 49-49 XML_CONTENT: 50-57
+ *
+ */
+ public final void beginBlockMarkerScan(String newTagName, String blockcontext) {
+ yybegin(ST_BLOCK_TAG_SCAN);
+ fCurrentTagName = newTagName;
+ }
+
+ /**
+ * Method doScan.
+ *
+ * Returns a context region for all of the text from the current position
+ * upto the end of input or to right *before* the first occurence of
+ * searchString
+ *
+ * @param searchString -
+ * target string to search for ex.: "-->", " </tagname"
+ * @param requireTailSeparator -
+ * whether the target must be immediately followed by
+ * whitespace or '>'
+ * @param context -
+ * the context of the scanned region if non-zero length
+ * @param exitState -
+ * the state to go to if the region was of non-zero length
+ * @param abortState -
+ * the state to go to if the searchString was found immediately
+ * @return String - the context found: the desired context on a non-zero
+ * length match, the abortContext on immediate success
+ * @throws IOException
+ */
+ private final String doScan(String searchString, boolean requireTailSeparator, String searchContext, int exitState, int immediateFallbackState) throws IOException {
+ boolean stillSearching = true;
+ // Disable further block (probably)
+ fIsBlockingEnabled = false;
+ int searchStringLength = searchString.length();
+ int n = 0;
+ char lastCheckChar;
+ int i;
+ boolean same = false;
+ while (stillSearching) {
+ n = 0;
+ // Ensure that enough data from the input exists to compare
+ // against the search String.
+ n = yy_advance();
+ while (n != YYEOF && yy_currentPos < searchStringLength)
+ n = yy_advance();
+ // If the input was too short or we've exhausted the input, stop
+ // immediately.
+ if (n == YYEOF) {
+ stillSearching = false;
+ } else {
+ same = true;
+ // Ensure that we've not encountered a complete block (<%%>)
+ // that was *shorter* than the closeTagString and
+ // thus found twice at current-targetLength [since the first
+ // scan would have come out this far anyway].
+ // Check the characters in the target versus the last
+ // targetLength characters read from the buffer
+ // and see if it matches
+
+ // safety check for array accesses (yy_currentPos is the
+ // *last* character we can check against)
+ if (yy_currentPos >= searchStringLength && yy_currentPos <= yy_buffer.length) {
+ for (i = 0; i < searchStringLength; i++) {
+ if (same && fIsCaseSensitiveBlocking)
+ same = yy_buffer[i + yy_currentPos - searchStringLength] == searchString.charAt(i);
+ else if (same && !fIsCaseSensitiveBlocking)
+ same = Character.toLowerCase(yy_buffer[i + yy_currentPos - searchStringLength]) == Character.toLowerCase(searchString.charAt(i));
+ }
+ }
+ // safety check failed; no match is possible right now
+ else {
+ same = false;
+ }
+ if (same && requireTailSeparator && yy_currentPos < yy_buffer.length) {
+ // Additional check for close tags to ensure that
+ // targetString="</script" doesn't match
+ // "</scriptS"
+ lastCheckChar = yy_buffer[yy_currentPos];
+ // Succeed on "</script>" and "</script "
+ if (lastCheckChar == '>' || Character.isWhitespace(lastCheckChar))
+ stillSearching = false;
+ } else {
+ stillSearching = !same || (yy_currentPos < yy_startRead + searchStringLength);
+ }
+ }
+ }
+ if (n != YYEOF || same) {
+ // We've stopped short of the end or definitely found a match
+ yy_markedPos = yy_currentPos - searchStringLength;
+ yy_currentPos = yy_markedPos + 1;
+ // If the searchString occurs at the very beginning of what would
+ // have
+ // been a Block, resume scanning normally immediately
+ if (yy_markedPos == yy_startRead) {
+ yybegin(immediateFallbackState);
+ return primGetNextToken();
+ }
+ } else {
+ // We ran through the rest of the input
+ yy_markedPos = yy_currentPos;
+ yy_currentPos++;
+ }
+ yybegin(exitState);
+ // If the ending occurs at the very beginning of what would have
+ // been a Block, resume scanning normally immediately
+ if (yy_markedPos == yy_startRead)
+ return primGetNextToken();
+ return searchContext;
+ }
+
+ /**
+ * user method
+ *
+ * A generic lookahead-like operation
+ */
+ private final String doBlockScan(String target, String targetContext, int immediateFallbackState) throws IOException {
+ return doScan(target, false, targetContext, immediateFallbackState, immediateFallbackState);
+ }
+
+ /**
+ * user method does a lookahead for the current tag name
+ */
+ private final String doBlockTagScan() throws IOException {
+ fIsCaseSensitiveBlocking = getBlockMarkerCaseSensitivity();
+ return doScan("</" + fCurrentTagName, true, getBlockMarkerContext(fCurrentTagName), YYINITIAL, YYINITIAL);
+ }
+
+ /**
+ * user method
+ *
+ * Converts the raw context String returned by the primGetNextToken()
+ * method into a full ITextRegion by pulling in values for the current
+ * offset within the scanning text.
+ *
+ * Returns null when EOF is encountered and attaches intermittently
+ * discovered whitespace onto the end of useful regions.
+ *
+ * Note that this algorithm caches the token following the one being
+ * returned so that whitespace can be collapsed.
+ */
+ public final ITextRegion getNextToken() throws IOException {
+ fEmbeddedContainer = null;
+ // load the starting non-whitespace token (assume that it is so)
+ if (fShouldLoadBuffered) {
+ if (fBufferedEmbeddedContainer != null) {
+ ITextRegion container = fBufferedEmbeddedContainer;
+ fBufferedEmbeddedContainer = null;
+ fShouldLoadBuffered = false;
+ return container;
+ }
+ context = fBufferedContext;
+ start = fBufferedStart;
+ textLength = length = fBufferedLength;
+ fShouldLoadBuffered = false;
+ } else {
+ context = primGetNextToken();
+ if (context == PROXY_CONTEXT) {
+ return fEmbeddedContainer;
+ } else if (context == XML_TAG_NAME) {
+ if (containsTagName(yy_buffer, yy_startRead, yy_markedPos - yy_startRead))
+ fCurrentTagName = yytext();
+ else
+ fCurrentTagName = null;
+ } else if (context == XML_TAG_OPEN) {
+ fIsBlockingEnabled = true;
+ } else if (context == XML_END_TAG_OPEN) {
+ fIsBlockingEnabled = false;
+ }
+ start = yychar;
+ textLength = length = yylength();
+ if (yy_atEOF) {
+ fTokenCount++;
+ return null;
+ }
+ }
+ // store the next token
+ f_context = primGetNextToken();
+ if (f_context == PROXY_CONTEXT) {
+ fBufferedEmbeddedContainer = fEmbeddedContainer;
+ fShouldLoadBuffered = true;
+ } else if (f_context == XML_TAG_NAME) {
+ if (containsTagName(yy_buffer, yy_startRead, yy_markedPos - yy_startRead))
+ fCurrentTagName = yytext();
+ else
+ fCurrentTagName = null;
+ } else if (f_context == XML_TAG_OPEN) {
+ fIsBlockingEnabled = true;
+ } else if (f_context == XML_END_TAG_OPEN) {
+ fIsBlockingEnabled = false;
+ }
+ fBufferedContext = f_context;
+ fBufferedStart = yychar;
+ fBufferedLength = yylength();
+ fShouldLoadBuffered = true;
+ if (fBufferedContext == WHITE_SPACE) {
+ fShouldLoadBuffered = false;
+ length += fBufferedLength;
+ }
+ if (context == null) {
+ // EOF
+ if (Debug.debugTokenizer) {
+ System.out.println(getClass().getName() + " discovered " + fTokenCount + " tokens."); //$NON-NLS-2$//$NON-NLS-1$
+ }
+ return null;
+ }
+ fTokenCount++;
+ return fRegionFactory.createToken(context, start, textLength, length, null, fCurrentTagName);
+ }
+
+ /* user method */
+ public XMLTokenizer() {
+ super();
+ }
+
+ /* user method */
+ public XMLTokenizer(char[] charArray) {
+ this(new CharArrayReader(charArray));
+ }
+
+ /* user method */
+ public void reset(char[] charArray) {
+ reset(new CharArrayReader(charArray), 0);
+ }
+
+ /* user method */
+ public void reset(char[] charArray, int newOffset) {
+ reset(new CharArrayReader(charArray), newOffset);
+ }
+
+ /* user method */
+ public void reset(java.io.InputStream in) {
+ reset(new java.io.InputStreamReader(in), 0);
+ }
+
+ /* user method */
+ public void reset(java.io.InputStream in, int newOffset) {
+ reset(new java.io.InputStreamReader(in), newOffset);
+ }
+
+ /* user method */
+ public void reset(java.io.Reader in) {
+ reset(in, 0);
+ }
+
+ /**
+ * user method *
+ *
+ * Reset internal counters and vars to "newly created" values, in the
+ * hopes that resetting a pre-existing tokenizer is faster than creating a
+ * new one.
+ *
+ * This method contains code blocks that were essentially duplicated from
+ * the <em>generated</em> output of this specification before this
+ * method was added. Those code blocks were under the above copyright.
+ */
+ public void reset(java.io.Reader in, int newOffset) {
+ if (Debug.debugTokenizer) {
+ System.out.println("resetting tokenizer");//$NON-NLS-1$
+ }
+ fOffset = newOffset;
+
+ /* the input device */
+ yy_reader = in;
+
+ /* the current state of the DFA */
+ yy_state = 0;
+
+ /* the current lexical state */
+ yy_lexical_state = YYINITIAL;
+
+ /*
+ * this buffer contains the current text to be matched and is the
+ * source of the yytext() string
+ */
+ java.util.Arrays.fill(yy_buffer, (char) 0);
+
+ /* the textposition at the last accepting state */
+ yy_markedPos = 0;
+
+ /* the textposition at the last state to be included in yytext */
+ yy_pushbackPos = 0;
+
+ /* the current text position in the buffer */
+ yy_currentPos = 0;
+
+ /* startRead marks the beginning of the yytext() string in the buffer */
+ yy_startRead = 0;
+
+ /**
+ * endRead marks the last character in the buffer, that has been read
+ * from input
+ */
+ yy_endRead = 0;
+
+ /* number of newlines encountered up to the start of the matched text */
+ yyline = 0;
+
+ /* the number of characters up to the start of the matched text */
+ yychar = 0;
+
+ /* yy_atEOF == true <=> the scanner has returned a value for EOF */
+ yy_atEOF = false;
+
+ /* denotes if the user-EOF-code has already been executed */
+ yy_eof_done = false;
+
+
+ /* user vars: */
+ fTokenCount = 0;
+
+ fShouldLoadBuffered = false;
+ fBufferedContext = null;
+ fBufferedStart = 1;
+ fBufferedLength = 0;
+ fStateStack = new IntStack();
+
+ context = null;
+ start = 0;
+ textLength = 0;
+ length = 0;
+
+ fEmbeddedContainer = null;
+ }
+
+ /**
+ * user method
+ *
+ * @see com.ibm.sed.parser.BlockTokenizer#newInstance()
+ */
+ public BlockTokenizer newInstance() {
+ XMLTokenizer newInstance = new XMLTokenizer();
+ // global tagmarkers can be shared; they have no state and
+ // are never destroyed (e.g. 'release')
+ for (int i = 0; i < fBlockMarkers.size(); i++) {
+ BlockMarker blockMarker = (BlockMarker) fBlockMarkers.get(i);
+ if (blockMarker.isGlobal())
+ newInstance.addBlockMarker(blockMarker);
+ }
+ return newInstance;
+ }
+
+ /* user method */
+ private final String scanXMLCommentText() throws IOException {
+ // Scan for '-->' and return the text up to that point as
+ // XML_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which
+ // case change to the ST_XML_COMMENT_END state and return the next
+ // context as usual.
+ return doScan("-->", false, XML_COMMENT_TEXT, ST_XML_COMMENT_END, ST_XML_COMMENT_END);
+ }
+
+
+ /**
+ * Creates a new scanner There is also a java.io.InputStream version of
+ * this constructor.
+ *
+ * @param in
+ * the java.io.Reader to read input from.
+ */
+ public XMLTokenizer(java.io.Reader in) {
+ this.yy_reader = in;
+ }
+
+ /**
+ * Creates a new scanner. There is also java.io.Reader version of this
+ * constructor.
+ *
+ * @param in
+ * the java.io.Inputstream to read input from.
+ */
+ public XMLTokenizer(java.io.InputStream in) {
+ this(new java.io.InputStreamReader(in));
+ }
+
+ /**
+ * Unpacks the compressed DFA transition table.
+ *
+ * @param packed
+ * the packed transition table
+ * @return the unpacked transition table
+ */
+ private static int[] yy_unpack(String packed) {
+ int[] trans = new int[9114];
+ int i = 0; /* index in packed string */
+ int j = 0; /* index in unpacked array */
+ while (i < 3174) {
+ int count = packed.charAt(i++);
+ int value = packed.charAt(i++);
+ value--;
+ do
+ trans[j++] = value;
+ while (--count > 0);
+ }
+ return trans;
+ }
+
+ /**
+ * Unpacks the compressed character translation table.
+ *
+ * @param packed
+ * the packed character translation table
+ * @return the unpacked character translation table
+ */
+ private static char[] yy_unpack_cmap(String packed) {
+ char[] map = new char[0x10000];
+ int i = 0; /* index in packed string */
+ int j = 0; /* index in unpacked array */
+ while (i < 1372) {
+ int count = packed.charAt(i++);
+ char value = packed.charAt(i++);
+ do
+ map[j++] = value;
+ while (--count > 0);
+ }
+ return map;
+ }
+
+
+ /**
+ * Gets the next input character.
+ *
+ * @return the next character of the input stream, EOF if the end of the
+ * stream is reached.
+ * @exception IOException
+ * if any I/O-Error occurs
+ */
+ private int yy_advance() throws java.io.IOException {
+
+ /* standard case */
+ if (yy_currentPos < yy_endRead)
+ return yy_buffer[yy_currentPos++];
+
+ /* if the eof is reached, we don't need to work hard */
+ if (yy_atEOF)
+ return YYEOF;
+
+ /* otherwise: need to refill the buffer */
+
+ /* first: make room (if you can) */
+ if (yy_startRead > 0) {
+ System.arraycopy(yy_buffer, yy_startRead, yy_buffer, 0, yy_endRead - yy_startRead);
+
+ /* translate stored positions */
+ yy_endRead -= yy_startRead;
+ yy_currentPos -= yy_startRead;
+ yy_markedPos -= yy_startRead;
+ yy_pushbackPos -= yy_startRead;
+ yy_startRead = 0;
+ }
+
+ /* is the buffer big enough? */
+ if (yy_currentPos >= yy_buffer.length) {
+ /* if not: blow it up */
+ char newBuffer[] = new char[yy_currentPos * 2];
+ System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+ yy_buffer = newBuffer;
+ }
+
+ /* finally: fill the buffer with new input */
+ int numRead = yy_reader.read(yy_buffer, yy_endRead, yy_buffer.length - yy_endRead);
+
+ if (numRead == -1)
+ return YYEOF;
+
+ yy_endRead += numRead;
+
+ return yy_buffer[yy_currentPos++];
+ }
+
+
+ /**
+ * Closes the input stream.
+ */
+ final public void yyclose() throws java.io.IOException {
+ yy_atEOF = true; /* indicate end of file */
+ yy_endRead = yy_startRead; /* invalidate buffer */
+ yy_reader.close();
+ }
+
+
+ /**
+ * Returns the current lexical state.
+ */
+ final public int yystate() {
+ return yy_lexical_state;
+ }
+
+ /**
+ * Enters a new lexical state
+ *
+ * @param newState
+ * the new lexical state
+ */
+ final public void yybegin(int newState) {
+ yy_lexical_state = newState;
+ }
+
+
+ /**
+ * Returns the text matched by the current regular expression.
+ */
+ final public String yytext() {
+ return new String(yy_buffer, yy_startRead, yy_markedPos - yy_startRead);
+ }
+
+ /**
+ * Returns the length of the matched text region.
+ */
+ final public int yylength() {
+ return yy_markedPos - yy_startRead;
+ }
+
+
+ /**
+ * Reports an error that occured while scanning - from the SED JFlex
+ * skeleton
+ *
+ * @param errorCode
+ * the code of the errormessage to display
+ */
+ private void yy_ScanError(int errorCode) {
+ try {
+ Logger.log(Logger.ERROR, YY_ERROR_MSG[errorCode]);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ Logger.log(Logger.ERROR, YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+ }
+ // DO NOT EXIT the VM on an error
+ // System.exit(1);
+ }
+
+
+ /**
+ * Pushes the specified amount of characters back into the input stream.
+ *
+ * They will be read again by then next call of the scanning method
+ *
+ * @param number
+ * the number of characters to be read again. This number must
+ * not be greater than yylength()!
+ */
+ void yypushback(int number) {
+ if (number > yylength())
+ yy_ScanError(YY_PUSHBACK_2BIG);
+
+ yy_markedPos -= number;
+ }
+
+ /**
+ * user method - skeleton.sed
+ */
+ protected final boolean containsTagName(char[] markerTagName, int offset, int tagnameLength) {
+ for (int j = 0; j < fBlockMarkers.size(); j++) {
+ BlockMarker marker = (BlockMarker) fBlockMarkers.get(j);
+ if (marker.getTagName().length() == tagnameLength) {
+ boolean matchesSoFar = true;
+ for (int i = 0; i < tagnameLength && matchesSoFar; i++) {
+ if (marker.isCaseSensitive()) {
+ if (marker.getTagName().charAt(i) != markerTagName[i + offset])
+ matchesSoFar = false;
+ } else {
+ if (Character.toLowerCase(marker.getTagName().charAt(i)) != Character.toLowerCase(markerTagName[i + offset]))
+ matchesSoFar = false;
+ }
+ }
+ if (matchesSoFar)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * user method - skeleton.sed
+ *
+ * Return ALL of the regions scannable within the remaining text Note: for
+ * verification use
+ */
+ public final List getRegions() {
+ List tokens = new ArrayList();
+ ITextRegion region = null;
+ try {
+ region = getNextToken();
+ while (region != null) {
+ if (region != null) {
+ tokens.add(region);
+ }
+ region = getNextToken();
+ }
+ } catch (StackOverflowError e) {
+ Logger.logException(getClass().getName() + ": input could not be tokenized correctly at position " + getOffset(), e);//$NON-NLS-1$
+ throw e;
+ } catch (Exception e) {
+ // Since this is convenience method and NOT the recommended
+ // way of getting tokens, many errors are simply hidden
+ Logger.logException("Exception not handled retrieving regions: " + e.getLocalizedMessage(), e);//$NON-NLS-1$
+ }
+ return tokens;
+ }
+
+ /**
+ * user method - skeleton.sed
+ */
+ private final void dump(String s) {
+ if (Debug.debugTokenizer) {
+ System.out.println(s + " (" + yychar + "-" + //$NON-NLS-2$//$NON-NLS-1$
+ (yylength() + yychar) + "):\'" + //$NON-NLS-1$
+ StringUtils.escape(yytext()) + "\'");//$NON-NLS-1$
+ }
+ }
+
+ /* user method - skeleton.sed */
+ public final boolean isEOF() {
+ return yy_atEOF;
+ }
+
+ /* user method - skeleton.sed */
+ protected final boolean containsTagName(String markerTagName) {
+ Iterator blocks = fBlockMarkers.iterator();
+ while (blocks.hasNext()) {
+ BlockMarker marker = (BlockMarker) blocks.next();
+ if (marker.isCaseSensitive()) {
+ if (marker.getTagName().equals(markerTagName))
+ return true;
+ } else {
+ if (marker.getTagName().equalsIgnoreCase(markerTagName))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Contains user EOF-code, which will be executed exactly once, when the
+ * end of file is reached
+ */
+ private void yy_do_eof() {
+ if (!yy_eof_done) {
+ yy_eof_done = true;
+ // do nothing, this is the downstream parser's job
+
+ }
+ }
+
+
+ /**
+ * Resumes scanning until the next regular expression is matched, the end
+ * of input is encountered or an I/O-Error occurs.
+ *
+ * @return the next token
+ * @exception IOException
+ * if any I/O-Error occurs
+ */
+ public String primGetNextToken() throws java.io.IOException {
+ int yy_input;
+ int yy_action;
+
+
+ while (true) {
+
+ yychar += yylength();
+
+ boolean yy_counted = false;
+ for (yy_currentPos = yy_startRead; yy_currentPos < yy_markedPos; yy_currentPos++) {
+ switch (yy_buffer[yy_currentPos]) {
+ case '\r' :
+ yyline++;
+ yy_counted = true;
+ break;
+ case '\n' :
+ if (yy_counted)
+ yy_counted = false;
+ else {
+ yyline++;
+ }
+ break;
+ default :
+ yy_counted = false;
+ }
+ }
+
+ if (yy_counted) {
+ if (yy_advance() == '\n')
+ yyline--;
+ if (!yy_atEOF)
+ yy_currentPos--;
+ }
+
+ yy_action = -1;
+
+ yy_currentPos = yy_startRead = yy_markedPos;
+
+ yy_state = yy_lexical_state;
+
+
+ yy_forAction : {
+ while (true) {
+
+ yy_input = yy_advance();
+
+ if (yy_input == YYEOF)
+ break yy_forAction;
+
+ int yy_next = yytrans[yy_rowMap[yy_state] + yycmap[yy_input]];
+ if (yy_next == -1)
+ break yy_forAction;
+ yy_state = yy_next;
+
+ int yy_attributes = YY_ATTRIBUTE[yy_state];
+ if ((yy_attributes & 1) > 0) {
+ yy_action = yy_state;
+ yy_markedPos = yy_currentPos;
+ if ((yy_attributes & 8) > 0)
+ break yy_forAction;
+ }
+
+ }
+ }
+
+
+ switch (yy_action) {
+
+ case 274 :
+ case 275 :
+ case 276 : {
+ if (Debug.debugTokenizer)
+ dump("\nCDATA start");//$NON-NLS-1$
+ fStateStack.push(yystate());
+ yybegin(ST_CDATA_TEXT);
+ return XML_CDATA_OPEN;
+ }
+ case 278 :
+ break;
+ case 268 : {
+ if (Debug.debugTokenizer)
+ dump("element");//$NON-NLS-1$
+ yybegin(ST_XML_ELEMENT_DECLARATION);
+ return XML_ELEMENT_DECLARATION;
+ }
+ case 279 :
+ break;
+ case 267 : {
+ if (Debug.debugTokenizer)
+ dump("attlist");//$NON-NLS-1$
+ yybegin(ST_XML_ATTLIST_DECLARATION);
+ return XML_ATTLIST_DECLARATION;
+ }
+ case 280 :
+ break;
+ case 266 : {
+ if (Debug.debugTokenizer)
+ dump("doctype");//$NON-NLS-1$
+ yybegin(ST_XML_DOCTYPE_DECLARATION);
+ return XML_DOCTYPE_DECLARATION;
+ }
+ case 281 :
+ break;
+ case 262 : {
+ if (Debug.debugTokenizer)
+ dump("doctype external id");//$NON-NLS-1$
+ fEmbeddedHint = XML_DOCTYPE_EXTERNAL_ID_PUBREF;
+ yybegin(ST_XML_DOCTYPE_ID_PUBLIC);
+ return XML_DOCTYPE_EXTERNAL_ID_PUBLIC;
+ }
+ case 282 :
+ break;
+ case 261 : {
+ if (Debug.debugTokenizer)
+ dump("doctype external id");//$NON-NLS-1$
+ fEmbeddedHint = XML_DOCTYPE_EXTERNAL_ID_SYSREF;
+ yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+ return XML_DOCTYPE_EXTERNAL_ID_SYSTEM;
+ }
+ case 283 :
+ break;
+ case 257 : {
+ if (Debug.debugTokenizer)
+ dump("DHTML processing instruction target");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+ fEmbeddedPostState = ST_XML_EQUALS;
+ yybegin(ST_DHTML_ATTRIBUTE_NAME);
+ return XML_TAG_NAME;
+ }
+ case 284 :
+ break;
+ case 234 : {
+ if (Debug.debugTokenizer)
+ dump("\nCharRef");//$NON-NLS-1$
+ return XML_CHAR_REFERENCE;
+ }
+ case 285 :
+ break;
+ case 231 : {
+ if (Debug.debugTokenizer)
+ dump("\ncomment start");//$NON-NLS-1$
+ fEmbeddedHint = XML_COMMENT_TEXT;
+ fEmbeddedPostState = ST_XML_COMMENT;
+ yybegin(ST_XML_COMMENT);
+ return XML_COMMENT_OPEN;
+ }
+ case 286 :
+ break;
+ case 213 : {
+ if (Debug.debugTokenizer)
+ dump("XML processing instruction target");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+ fEmbeddedPostState = ST_XML_EQUALS;
+ yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+ return XML_TAG_NAME;
+ }
+ case 287 :
+ break;
+ case 212 : {
+ if (Debug.debugTokenizer)
+ dump("comment end");//$NON-NLS-1$
+ fEmbeddedHint = UNDEFINED;
+ yybegin(YYINITIAL);
+ return XML_COMMENT_CLOSE;
+ }
+ case 288 :
+ break;
+ case 211 : {
+ if (Debug.debugTokenizer)
+ dump("CDATA end");//$NON-NLS-1$
+ yybegin(fStateStack.pop());
+ return XML_CDATA_CLOSE;
+ }
+ case 289 :
+ break;
+ case 210 : {
+ if (Debug.debugTokenizer)
+ dump("\nPEReference");//$NON-NLS-1$
+ return XML_PE_REFERENCE;
+ }
+ case 290 :
+ break;
+ case 207 : {
+ if (Debug.debugTokenizer)
+ dump("\nEntityRef");//$NON-NLS-1$
+ return XML_ENTITY_REFERENCE;
+ }
+ case 291 :
+ break;
+ case 158 :
+ case 172 :
+ case 180 : {
+ return XML_DOCTYPE_INTERNAL_SUBSET;
+ }
+ case 292 :
+ break;
+ case 146 : {
+ yybegin(YYINITIAL);
+ fEmbeddedHint = UNDEFINED;
+ if (Debug.debugTokenizer)
+ dump("empty tag close");//$NON-NLS-1$
+ return XML_EMPTY_TAG_CLOSE;
+ }
+ case 293 :
+ break;
+ case 131 : {
+ if (Debug.debugTokenizer)
+ dump("XML processing instruction end");//$NON-NLS-1$
+ fEmbeddedHint = UNDEFINED;
+ yybegin(YYINITIAL);
+ return XML_PI_CLOSE;
+ }
+ case 294 :
+ break;
+ case 130 : {
+ // ended with nothing inside
+ fEmbeddedHint = UNDEFINED;
+ yybegin(YYINITIAL);
+ return XML_PI_CLOSE;
+ }
+ case 295 :
+ break;
+ case 127 : {
+ if (Debug.debugTokenizer)
+ dump("processing instruction end");//$NON-NLS-1$
+ fEmbeddedHint = UNDEFINED;
+ yybegin(YYINITIAL);
+ return XML_PI_CLOSE;
+ }
+ case 296 :
+ break;
+ case 119 : {
+ fStateStack.push(yystate());
+ if (Debug.debugTokenizer)
+ dump("\ndeclaration start");//$NON-NLS-1$
+ yybegin(ST_XML_DECLARATION);
+ return XML_DECLARATION_OPEN;
+ }
+ case 297 :
+ break;
+ case 118 : {
+ if (Debug.debugTokenizer)
+ dump("\nprocessing instruction start");//$NON-NLS-1$
+ yybegin(ST_PI);
+ return XML_PI_OPEN;
+ }
+ case 298 :
+ break;
+ case 62 : {
+ if (Debug.debugTokenizer)
+ dump("DHTML processing instruction end");//$NON-NLS-1$
+ fEmbeddedHint = UNDEFINED;
+ yybegin(YYINITIAL);
+ return XML_PI_CLOSE;
+ }
+ case 299 :
+ break;
+ case 56 :
+ case 58 :
+ case 59 :
+ case 60 :
+ case 135 : {
+ if (Debug.debugTokenizer)
+ dump("XML processing instruction attribute value");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+ fEmbeddedPostState = ST_XML_EQUALS;
+ yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+ return XML_TAG_ATTRIBUTE_VALUE;
+ }
+ case 300 :
+ break;
+ case 55 : {
+ if (Debug.debugTokenizer)
+ dump("XML processing instruction '='");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+ fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+ yybegin(ST_XML_PI_ATTRIBUTE_VALUE);
+ return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+ case 301 :
+ break;
+ case 54 : {
+ if (Debug.debugTokenizer)
+ dump("XML processing instruction attribute name");//$NON-NLS-1$
+ yybegin(ST_XML_PI_EQUALS);
+ return XML_TAG_ATTRIBUTE_NAME;
+ }
+ case 302 :
+ break;
+ case 50 :
+ case 51 :
+ case 52 : {
+ // block scan until close is found
+ return doScan("?>", false, XML_PI_CONTENT, ST_XML_PI_TAG_CLOSE, ST_XML_PI_TAG_CLOSE);
+ }
+ case 303 :
+ break;
+ case 49 : {
+ yybegin(ST_PI_CONTENT);
+ return WHITE_SPACE;
+ }
+ case 304 :
+ break;
+ case 46 :
+ case 47 :
+ case 48 :
+ case 128 :
+ case 129 :
+ case 214 :
+ case 236 :
+ case 248 : {
+ if (Debug.debugTokenizer)
+ dump("processing instruction target");//$NON-NLS-1$
+ fEmbeddedHint = XML_CONTENT;
+ yybegin(ST_PI_WS);
+ return XML_TAG_NAME;
+ }
+ case 305 :
+ break;
+ case 41 :
+ case 42 : {
+ if (Debug.debugTokenizer)
+ dump("comment content");//$NON-NLS-1$
+ return scanXMLCommentText();
+ }
+ case 306 :
+ break;
+ case 40 : {
+ if (Debug.debugTokenizer)
+ dump("LINE FEED");//$NON-NLS-1$
+ return WHITE_SPACE;
+ }
+ case 307 :
+ break;
+ case 0 :
+ case 31 :
+ case 121 :
+ case 123 :
+ case 205 :
+ case 206 :
+ case 233 : {
+ if (Debug.debugTokenizer)
+ dump("\nXML content");//$NON-NLS-1$
+ return XML_CONTENT;
+ }
+ case 308 :
+ break;
+ case 5 :
+ case 8 :
+ case 9 :
+ case 10 :
+ case 12 :
+ case 13 :
+ case 14 :
+ case 15 :
+ case 17 :
+ case 18 :
+ case 19 :
+ case 20 :
+ case 21 :
+ case 22 :
+ case 23 :
+ case 24 :
+ case 25 :
+ case 26 :
+ case 28 :
+ case 45 : {
+ if (Debug.debugTokenizer)
+ dump("white space");//$NON-NLS-1$
+ return WHITE_SPACE;
+ }
+ case 309 :
+ break;
+ case 16 :
+ case 70 : {
+ if (Debug.debugTokenizer)
+ dump("inappropriate tag name");//$NON-NLS-1$
+ yybegin(YYINITIAL);
+ return XML_CONTENT;
+ }
+ case 310 :
+ break;
+ case 27 :
+ case 105 :
+ case 106 :
+ case 191 :
+ case 226 :
+ case 244 :
+ case 254 :
+ case 263 :
+ case 269 :
+ case 272 : {
+ if (Debug.debugTokenizer)
+ dump("elementdecl contentspec");//$NON-NLS-1$
+ return XML_ELEMENT_DECL_CONTENT;
+ }
+ case 311 :
+ break;
+ case 29 :
+ case 112 :
+ case 113 :
+ case 202 :
+ case 230 :
+ case 246 :
+ case 255 :
+ case 264 :
+ case 270 :
+ case 273 : {
+ if (Debug.debugTokenizer)
+ dump("attlist contentspec");//$NON-NLS-1$
+ return XML_ATTLIST_DECL_CONTENT;
+ }
+ case 312 :
+ break;
+ case 32 :
+ case 71 :
+ case 82 : {
+ if (Debug.debugTokenizer)
+ dump("\nstart tag open");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_NAME;
+ fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+ yybegin(ST_XML_TAG_NAME);
+ return XML_TAG_OPEN;
+ }
+ case 313 :
+ break;
+ case 33 :
+ case 34 :
+ case 37 :
+ case 38 :
+ case 39 :
+ case 43 :
+ case 44 :
+ case 53 :
+ case 57 :
+ case 61 :
+ case 63 :
+ case 67 :
+ case 73 :
+ case 79 :
+ case 84 :
+ case 85 :
+ case 86 :
+ case 87 :
+ case 89 :
+ case 90 :
+ case 92 :
+ case 97 :
+ case 102 :
+ case 109 : {
+ if (Debug.debugTokenizer)
+ System.out.println("!!!unexpected!!!: \"" + yytext() + "\":" + //$NON-NLS-2$//$NON-NLS-1$
+ yychar + "-" + (yychar + yylength()));//$NON-NLS-1$
+ return UNDEFINED;
+ }
+ case 314 :
+ break;
+ case 35 :
+ case 36 : {
+ if (Debug.debugTokenizer)
+ dump("CDATA text");//$NON-NLS-1$
+ fEmbeddedHint = XML_CDATA_TEXT;
+ fEmbeddedPostState = ST_CDATA_TEXT;
+ String blockContext = doBlockScan("]]>", XML_CDATA_TEXT, ST_CDATA_END);//$NON-NLS-1$
+ if (blockContext == XML_CDATA_TEXT)
+ yybegin(ST_CDATA_END);
+ return blockContext;
+ }
+ case 315 :
+ break;
+ case 64 : {
+ if (Debug.debugTokenizer)
+ dump("DHTML processing instruction attribute name");//$NON-NLS-1$
+ yybegin(ST_DHTML_EQUALS);
+ return XML_TAG_ATTRIBUTE_NAME;
+ }
+ case 316 :
+ break;
+ case 65 : {
+ if (Debug.debugTokenizer)
+ dump("DHTML processing instruction '='");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+ fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+ yybegin(ST_DHTML_ATTRIBUTE_VALUE);
+ return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+ case 317 :
+ break;
+ case 66 :
+ case 68 :
+ case 69 :
+ case 143 : {
+ if (Debug.debugTokenizer)
+ dump("DHTML processing instruction attribute value");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+ fEmbeddedPostState = ST_XML_EQUALS;
+ yybegin(ST_DHTML_ATTRIBUTE_NAME);
+ return XML_TAG_ATTRIBUTE_VALUE;
+ }
+ case 318 :
+ break;
+ case 72 : {
+ if (Debug.debugTokenizer)
+ dump("tag close");//$NON-NLS-1$
+ fEmbeddedHint = UNDEFINED;
+ if (isBlockMarker()) {
+ fEmbeddedHint = getBlockMarkerContext();
+ fEmbeddedPostState = ST_BLOCK_TAG_SCAN;
+ yybegin(ST_BLOCK_TAG_SCAN);
+ } else
+ yybegin(YYINITIAL);
+ return XML_TAG_CLOSE;
+ }
+ case 319 :
+ break;
+ case 74 :
+ case 75 : {
+ if (Debug.debugTokenizer)
+ dump("tag name");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+ fEmbeddedPostState = ST_XML_EQUALS;
+ yybegin(ST_XML_ATTRIBUTE_NAME);
+ return XML_TAG_NAME;
+ }
+ case 320 :
+ break;
+ case 76 : {
+ if (Debug.debugTokenizer)
+ dump("attr name");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+ fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+ yybegin(ST_XML_EQUALS);
+ return XML_TAG_ATTRIBUTE_NAME;
+ }
+ case 321 :
+ break;
+ case 77 : {
+ if (Debug.debugTokenizer)
+ dump("equals");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+ fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+ yybegin(ST_XML_ATTRIBUTE_VALUE);
+ return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+ case 322 :
+ break;
+ case 78 :
+ case 80 :
+ case 81 :
+ case 150 : {
+ if (Debug.debugTokenizer)
+ dump("attr value");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+ fEmbeddedPostState = ST_XML_EQUALS;
+ yybegin(ST_XML_ATTRIBUTE_NAME);
+ return XML_TAG_ATTRIBUTE_VALUE;
+ }
+ case 323 :
+ break;
+ case 83 : {
+ if (Debug.debugTokenizer)
+ dump("declaration end");//$NON-NLS-1$
+ if (Debug.debugTokenizer) {
+ if (fStateStack.peek() != YYINITIAL)
+ System.out.println("end embedded region");//$NON-NLS-1$
+ }
+ yybegin(fStateStack.pop());
+ return XML_DECLARATION_CLOSE;
+ }
+ case 324 :
+ break;
+ case 88 : {
+ if (Debug.debugTokenizer)
+ dump("doctype type");//$NON-NLS-1$
+ yybegin(ST_XML_DOCTYPE_EXTERNAL_ID);
+ return XML_DOCTYPE_NAME;
+ }
+ case 325 :
+ break;
+ case 91 :
+ case 93 :
+ case 94 :
+ case 95 :
+ case 164 :
+ case 165 :
+ case 168 :
+ case 169 :
+ case 221 : {
+ if (Debug.debugTokenizer)
+ dump("doctype public reference");//$NON-NLS-1$
+ fEmbeddedHint = UNDEFINED;
+ fEmbeddedPostState = YYINITIAL;
+ yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+ return XML_DOCTYPE_EXTERNAL_ID_PUBREF;
+ }
+ case 326 :
+ break;
+ case 96 :
+ case 98 :
+ case 99 :
+ case 100 :
+ case 176 : {
+ if (Debug.debugTokenizer)
+ dump("doctype system reference");//$NON-NLS-1$
+ fEmbeddedHint = UNDEFINED;
+ fEmbeddedPostState = YYINITIAL;
+ yybegin(ST_XML_DECLARATION_CLOSE);
+ return XML_DOCTYPE_EXTERNAL_ID_SYSREF;
+ }
+ case 327 :
+ break;
+ case 101 :
+ case 103 :
+ case 104 :
+ case 184 :
+ case 185 :
+ case 188 :
+ case 189 :
+ case 224 : {
+ if (Debug.debugTokenizer)
+ dump("elementdecl name");//$NON-NLS-1$
+ fEmbeddedHint = UNDEFINED;
+ fEmbeddedPostState = YYINITIAL;
+ yybegin(ST_XML_ELEMENT_DECLARATION_CONTENT);
+ return XML_ELEMENT_DECL_NAME;
+ }
+ case 328 :
+ break;
+ case 107 : {
+ if (Debug.debugTokenizer)
+ dump("elementdecl close");//$NON-NLS-1$
+ if (Debug.debugTokenizer) {
+ if (fStateStack.peek() != YYINITIAL)
+ System.out.println("end embedded region");//$NON-NLS-1$
+ }
+ yybegin(fStateStack.pop());
+ return XML_DECLARATION_CLOSE;
+ }
+ case 329 :
+ break;
+ case 108 :
+ case 110 :
+ case 111 :
+ case 195 :
+ case 196 :
+ case 199 :
+ case 200 :
+ case 228 : {
+ if (Debug.debugTokenizer)
+ dump("attlist name");//$NON-NLS-1$
+ fEmbeddedHint = UNDEFINED;
+ fEmbeddedPostState = YYINITIAL;
+ yybegin(ST_XML_ATTLIST_DECLARATION_CONTENT);
+ return XML_ATTLIST_DECL_NAME;
+ }
+ case 330 :
+ break;
+ case 114 : {
+ if (Debug.debugTokenizer)
+ dump("attlist close");//$NON-NLS-1$
+ if (Debug.debugTokenizer) {
+ if (fStateStack.peek() != YYINITIAL)
+ System.out.println("end embedded region");//$NON-NLS-1$
+ }
+ yybegin(fStateStack.pop());
+ return XML_DECLARATION_CLOSE;
+ }
+ case 331 :
+ break;
+ case 117 : {
+ if (Debug.debugTokenizer)
+ dump("\nend tag open");//$NON-NLS-1$
+ fEmbeddedHint = XML_TAG_NAME;
+ fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+ yybegin(ST_XML_TAG_NAME);
+ return XML_END_TAG_OPEN;
+ }
+ case 332 :
+ break;
+ case 115 :
+ case 116 : {
+ return doBlockTagScan();
+ }
+ case 333 :
+ break;
+ default :
+ if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+ yy_atEOF = true;
+ yy_do_eof();
+ return null;
+ } else {
+ yy_ScanError(YY_NO_MATCH);
+ }
+ }
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeEqualsRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeEqualsRegion.java
new file mode 100644
index 0000000000..2a577768b8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeEqualsRegion.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+
+public class AttributeEqualsRegion implements ITextRegion {
+ static private final byte fTextLength = 1;
+ static private final String fType = XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS;
+ private short fLength;
+ private int fStart;
+
+
+ public AttributeEqualsRegion() {
+ super();
+ }
+
+ public AttributeEqualsRegion(int start, int textLength, int length) {
+ this();
+ fStart = start;
+ fLength = (short) length;
+ }
+
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+
+ }
+
+ public void adjustTextLength(int i) {
+ // not supported
+
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = (short) region.getLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // can never be updated
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeNameRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeNameRegion.java
new file mode 100644
index 0000000000..fd678bd02c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeNameRegion.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.sse.core.util.Utilities;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class AttributeNameRegion implements ITextRegion {
+ // specify correct type
+ static private final String fType = XMLRegionContext.XML_TAG_ATTRIBUTE_NAME;
+ private int fLength;
+ private int fStart;
+ private int fTextLength;
+
+ public AttributeNameRegion() {
+ super();
+ }
+
+ public AttributeNameRegion(int start, int textLength, int length) {
+ this();
+ fStart = start;
+ fTextLength = textLength;
+ fLength = length;
+ }
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ fTextLength += 1;
+
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = region.getLength();
+ fTextLength = region.getTextLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ RegionChangedEvent result = null;
+ // if the region is an easy type (e.g. attribute value),
+ // and the requested changes are all
+ // alphanumeric, then make the change here locally.
+ // (This can obviously be made more sophisticated as the need arises,
+ // but should
+ // always follow this pattern.)
+ if (Debug.debugStructuredDocument) {
+ System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+ System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+ }
+ boolean canHandle = false;
+ // note: we'll always handle deletes from these
+ // regions ... if its already that region,
+ // deleting something from it won't change its
+ // type. (remember, the calling program needs
+ // to insure we are not called, if not all contained
+ // on one region.
+ if ((changes == null) || (changes.length() == 0)) {
+ // delete case
+ // We can not do the quick delete, if
+ // if all the text in a region is to be deleted.
+ // Or, if the delete starts in the white space region.
+ // In these cases, a reparse is needed.
+ // Minor note, we use textEnd-start since it always
+ // less than or equal to end-start. This might
+ // cause us to miss a few cases we could have handled,
+ // but will prevent us from trying to handle funning cases
+ // involving whitespace.
+ if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+ canHandle = false;
+ } else {
+ canHandle = true;
+ }
+ } else {
+ if ((RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(this, parent, changes, requestStart, lengthToReplace)) {
+ canHandle = true;
+ } else {
+ canHandle = false;
+ }
+
+ }
+ if (canHandle) {
+ // at this point, we still have the old region. We won't create a
+ // new instance, we'll just update the one we have, by changing
+ // its end postion,
+ // The parent flatnode, upon return, has responsibility
+ // for updating sibling regions.
+ // and in turn, the structuredDocument itself has responsibility
+ // for
+ // updating the text store and down stream flatnodes.
+ if (Debug.debugStructuredDocument) {
+ System.out.println("change handled by region"); //$NON-NLS-1$
+ }
+ int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+ // Note: we adjust both end and text end, because for any change
+ // that is in only the trailing whitespace region, we should not
+ // do a quick change,
+ // so 'canHandle' should have been false for those case.
+ // TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+ // If we are handling as whitespace, there is no need to increase
+ // the text length, only
+ // the total length is changing.
+ if (!RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) {
+ fTextLength += lengthDifference;
+ }
+ fLength += lengthDifference;
+ result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+ }
+
+ return result;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeValueRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeValueRegion.java
new file mode 100644
index 0000000000..03eb4634da
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/AttributeValueRegion.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.sse.core.util.Utilities;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class AttributeValueRegion implements ITextRegion {
+ // specify correct type
+ static private final String fType = XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE;
+ private int fLength;
+ private int fStart;
+ private int fTextLength;
+
+ public AttributeValueRegion() {
+ super();
+ }
+
+ public AttributeValueRegion(int start, int textLength, int length) {
+ this();
+ fStart = start;
+ fTextLength = textLength;
+ fLength = length;
+ }
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ fTextLength += 1;
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = region.getLength();
+ fTextLength = region.getTextLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ RegionChangedEvent result = null;
+ // if the region is an easy type (e.g. attribute value),
+ // and the requested changes are all
+ // alphanumeric, then make the change here locally.
+ // (This can obviously be made more sophisticated as the need arises,
+ // but should
+ // always follow this pattern.)
+ if (Debug.debugStructuredDocument) {
+ System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+ System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+ }
+ boolean canHandle = false;
+ // note: we'll always handle deletes from these
+ // regions ... if its already that region,
+ // deleting something from it won't change its
+ // type. (remember, the calling program needs
+ // to insure we are not called, if not all contained
+ // on one region.
+ if ((changes == null) || (changes.length() == 0)) {
+ // delete case
+ // We can not do the quick delete, if
+ // if all the text in a region is to be deleted.
+ // Or, if the delete starts in the white space region.
+ // In these cases, a reparse is needed.
+ // Minor note, we use textEnd-start since it always
+ // less than or equal to end-start. This might
+ // cause us to miss a few cases we could have handled,
+ // but will prevent us from trying to handle funning cases
+ // involving whitespace.
+ if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+ canHandle = false;
+ } else {
+ canHandle = true;
+ }
+ } else {
+ if ((RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(this, parent, changes, requestStart, lengthToReplace)) {
+ canHandle = true;
+ } else {
+ canHandle = false;
+ }
+ }
+ if (canHandle) {
+ // at this point, we still have the old region. We won't create a
+ // new instance, we'll just update the one we have, by changing
+ // its end postion,
+ // The parent flatnode, upon return, has responsibility
+ // for updating sibling regions.
+ // and in turn, the structuredDocument itself has responsibility
+ // for
+ // updating the text store and down stream flatnodes.
+ if (Debug.debugStructuredDocument) {
+ System.out.println("change handled by region"); //$NON-NLS-1$
+ }
+ int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+ // Note: we adjust both end and text end, because for any change
+ // that is in only the trailing whitespace region, we should not
+ // do a quick change,
+ // so 'canHandle' should have been false for those case.
+ // TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+ // If we are handling as whitespace, there is no need to increase
+ // the text length, only
+ // the total length is changing.
+ if (!RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) {
+ fTextLength += lengthDifference;
+ }
+ // update length (and end) after above check for white space,
+ // since
+ // it looks to determine if at end of region.
+ fLength += lengthDifference;
+ result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+ }
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/BlockTextRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/BlockTextRegion.java
new file mode 100644
index 0000000000..b382257d5a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/BlockTextRegion.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.internal.parser.ForeignRegion;
+
+
+
+public class BlockTextRegion extends ForeignRegion {
+
+ /**
+ * BlockTextRegion constructor comment.
+ */
+ public BlockTextRegion() {
+ super();
+ }
+
+ public BlockTextRegion(String newContext, int newStart, int newTextLength, int newLength) {
+ super(newContext, newStart, newTextLength, newLength);
+ }
+
+ public BlockTextRegion(String newContext, int newStart, int newTextLength, int newLength, String newLanguage) {
+ super(newContext, newStart, newTextLength, newLength, newLanguage);
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/GenericTemplateRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/GenericTemplateRegion.java
new file mode 100644
index 0000000000..291a3411e7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/GenericTemplateRegion.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+/**
+ *
+ * This class is not intended to be used, its just present to server as a
+ * generic starting point for adding new specific region types.
+ */
+
+public class GenericTemplateRegion implements ITextRegion {
+ // specify correct type
+ static private final String fType = XMLRegionContext.UNDEFINED;
+ private int fLength;
+ private int fStart;
+ private int fTextLength;
+
+
+ public GenericTemplateRegion() {
+ super();
+ }
+
+ public GenericTemplateRegion(int start, int textLength, int length) {
+ this();
+ fStart = start;
+ fTextLength = textLength;
+ fLength = length;
+ }
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ fTextLength += 1;
+
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = region.getLength();
+ fTextLength = region.getTextLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // can never be updated
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionToStringUtil.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionToStringUtil.java
new file mode 100644
index 0000000000..9693beb913
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionToStringUtil.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+
+public class RegionToStringUtil {
+ static public String toString(ITextRegion region) {
+ String className = region.getClass().getName();
+ String shortClassName = className.substring(className.lastIndexOf(".") + 1); //$NON-NLS-1$
+ // ==> // String resultText = null;
+ String result = shortClassName + "--> " + region.getType() + ": " + region.getStart() + "-" + region.getTextEnd() + (region.getTextEnd() != region.getEnd() ? ("/" + region.getEnd()) : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ // NOTE: if the document held by any region has been updated and the
+ // region offsets have not
+ // yet been updated, the output from this method invalid.
+ //return com.ibm.sed.util.StringUtils.escape("('"+(getFirstRegion()
+ // == null || document == null? "" :
+ // getText(getFirstRegion()))+"'"+getStart()+" -
+ // "+getEnd()+"'"+(getClose() == null || document == null ||
+ // getRegions().size()<2 ? "" : getText(getClose()))+"')
+ // "+getRegions());
+ return result;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionUpdateRule.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionUpdateRule.java
new file mode 100644
index 0000000000..8692688ea3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/RegionUpdateRule.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.sse.core.util.Utilities;
+
+
+/**
+ *
+ * This is a utility class to centralize 'region' update. Note: care must be
+ * taken that is is not used for StructuredDocumentRegions, or container
+ * regions, its only for "token regions"
+ *
+ */
+public class RegionUpdateRule {
+
+ static public boolean allLetterOrDigit(String changes) {
+ boolean result = true;
+ for (int i = 0; i < changes.length(); i++) {
+ // TO_DO_FUTURE: check that a Java Letter or Digit is
+ // the same thing as an XML letter or digit
+ if (!(Character.isLetterOrDigit(changes.charAt(i)))) {
+ result = false;
+ break;
+ }
+ }
+ return result;
+ }
+
+ static public boolean allWhiteSpace(String changes) {
+ boolean result = true;
+ for (int i = 0; i < changes.length(); i++) {
+ if (!Character.isWhitespace(changes.charAt(i))) {
+ result = false;
+ break;
+ }
+ }
+ return result;
+ }
+
+ static public boolean canHandleAsLetterOrDigit(ITextRegion region, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ if (parent == null)
+ return canHandleAsLetterOrDigit(region, changes, requestStart, lengthToReplace);
+ boolean result = false;
+ // Make sure we are in a non-white space area
+ if ((requestStart <= (parent.getTextEndOffset(region))) && (allLetterOrDigit(changes))) {
+ result = true;
+ }
+ return result;
+ }
+
+ static public boolean canHandleAsLetterOrDigit(ITextRegion region, String changes, int requestStart, int lengthToReplace) {
+ boolean result = false;
+ // Make sure we are in a non-white space area
+ if ((requestStart <= (region.getTextEnd())) && (allLetterOrDigit(changes))) {
+ result = true;
+ }
+ return result;
+ }
+
+ static public boolean canHandleAsWhiteSpace(ITextRegion region, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // we don't explect a null parent, but just in case!
+ // (in which case, we must be dealing with regions that are
+ // structuredDocumentRegions).
+ if (parent == null)
+ return canHandleAsWhiteSpace(region, changes, requestStart, lengthToReplace);
+ boolean result = false;
+ // if we are in the "white space" area of a region, then
+ // we don't want to handle, a reparse is needed.
+ // the white space region is consider anywhere that would
+ // leave whitespace between this character and the text part.
+ // and of course, we can insert whitespace in whitespace region
+ //
+ // if there is no whitespace in this region, no need to look further
+ if (region.getEnd() > region.getTextEnd()) {
+ // no need to add one to end of text, as we used to, since we
+ // change definition of length to equate to offset plus one.
+ if (requestStart > parent.getTextEndOffset(region)) {
+ // ok, we are in the whitespace region, so we can't handle,
+ // unless
+ // we are just inserting whitespace.
+ if (allWhiteSpace(changes)) {
+ result = true;
+ } else {
+ result = false;
+ }
+ }
+ }
+ return result;
+ }
+
+ static public boolean canHandleAsWhiteSpace(ITextRegion region, String changes, int requestStart, int lengthToReplace) {
+ boolean result = false;
+ // if we are in the "white space" area of a region, then
+ // we don't want to handle, a reparse is needed.
+ // the white space region is consider anywhere that would
+ // leave whitespace between this character and the text part.
+ // and of course, we can insert whitespace in whitespace region
+ //
+ // if there is no whitespace in this region, no need to look further
+ if (region.getEnd() > region.getTextEnd()) {
+ // no need to add one to end of text, as we used to, since we
+ // change definition of length to equate to offset plus one.
+ if (requestStart > region.getTextEnd()) {
+ // ok, we are in the whitespace region, so we can't handle,
+ // unless
+ // we are just inserting whitespace.
+ if (allWhiteSpace(changes)) {
+ result = true;
+ } else {
+ result = false;
+ }
+ }
+ }
+ return result;
+ }
+
+ // need an adjust text length API before this can be used
+ static public StructuredDocumentEvent updateModel(ITextRegion region, Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ RegionChangedEvent result = null;
+ // if the region is an easy type (e.g. attribute value),
+ // and the requested changes are all
+ // alphanumeric, then make the change here locally.
+ // (This can obviously be made more sophisticated as the need arises,
+ // but should
+ // always follow this pattern.)
+ if (Debug.debugStructuredDocument) {
+ System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+ System.out.println("\t\t\tregion type is " + region.getType()); //$NON-NLS-1$
+ }
+ boolean canHandle = false;
+ // note: we'll always handle deletes from these
+ // regions ... if its already that region,
+ // deleting something from it won't change its
+ // type. (remember, the calling program needs
+ // to insure we are not called, if not all contained
+ // on one region.
+ if ((changes == null) || (changes.length() == 0)) {
+ // delete case
+ // We can not do the quick delete, if
+ // if all the text in a region is to be deleted.
+ // Or, if the delete starts in the white space region.
+ // In these cases, a reparse is needed.
+ // Minor note, we use textEnd-start since it always
+ // less than or equal to end-start. This might
+ // cause us to miss a few cases we could have handled,
+ // but will prevent us from trying to handle funning cases
+ // involving whitespace.
+ if ((region.getStart() >= region.getTextEnd()) || (Math.abs(lengthToReplace) >= region.getTextEnd() - region.getStart())) {
+ canHandle = false;
+ } else {
+ canHandle = true;
+ }
+ } else {
+ if ((RegionUpdateRule.canHandleAsWhiteSpace(region, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(region, parent, changes, requestStart, lengthToReplace)) {
+ canHandle = true;
+ } else {
+ canHandle = false;
+ }
+ }
+ if (canHandle) {
+ // at this point, we still have the old region. We won't create a
+ // new instance, we'll just update the one we have, by changing
+ // its end postion,
+ // The parent flatnode, upon return, has responsibility
+ // for updating sibling regions.
+ // and in turn, the structuredDocument itself has responsibility
+ // for
+ // updating the text store and down stream flatnodes.
+ if (Debug.debugStructuredDocument) {
+ System.out.println("change handled by region"); //$NON-NLS-1$
+ }
+ int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+ // Note: we adjust both end and text end, because for any change
+ // that is in only the trailing whitespace region, we should not
+ // do a quick change,
+ // so 'canHandle' should have been false for those case.
+ region.adjustLengthWith(lengthDifference);
+ // TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+ // If we are handling as whitespace, there is no need to increase
+ // the text length, only
+ // the total length is changing.
+ if (!RegionUpdateRule.canHandleAsWhiteSpace(region, parent, changes, region.getStart(), lengthToReplace)) {
+ // region.adjustTextLength(lengthDifference);
+ }
+ result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, region, changes, requestStart, lengthToReplace);
+ }
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagCloseRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagCloseRegion.java
new file mode 100644
index 0000000000..87044ddc5c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagCloseRegion.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class TagCloseRegion implements ITextRegion {
+ static private final byte fLength = 1;
+ static private final byte fTextLength = 1;
+ static private final String fType = XMLRegionContext.XML_TAG_CLOSE;
+ private int fStart;
+
+
+ public TagCloseRegion() {
+ super();
+ }
+
+ public TagCloseRegion(int start) {
+ this();
+ fStart = start;
+ }
+
+ public void adjustLengthWith(int i) {
+ throw new SourceEditingRuntimeException("invalid for this region type"); //$NON-NLS-1$
+
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ // not supported
+
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // can never be updated
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagNameRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagNameRegion.java
new file mode 100644
index 0000000000..f01e5b017a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagNameRegion.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class TagNameRegion implements ITextRegion {
+ static private final String fType = XMLRegionContext.XML_TAG_NAME;
+ private short fLength;
+ private int fStart;
+ private short fTextLength;
+
+
+ public TagNameRegion() {
+ super();
+ }
+
+ public TagNameRegion(int start, int textLength, int length) {
+ this();
+ fStart = start;
+ fTextLength = (short) textLength;
+ fLength = (short) length;
+ }
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ fTextLength += i;
+
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = (short) region.getLength();
+ fTextLength = (short) region.getTextLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // can never be updated
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java
new file mode 100644
index 0000000000..f09c83dadd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/TagOpenRegion.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class TagOpenRegion implements ITextRegion {
+ static private final String fType = XMLRegionContext.XML_TAG_OPEN;
+ private int fLength;
+ private int fStart;
+ private int fTextLength;
+
+
+ public TagOpenRegion() {
+ super();
+ }
+
+ public TagOpenRegion(int start, int textLength, int length) {
+ this();
+ fStart = start;
+ fTextLength = textLength;
+ fLength = length;
+ }
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ fTextLength += 1;
+
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = region.getLength();
+ fTextLength = region.getTextLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // can never be updated
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/WhiteSpaceOnlyRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/WhiteSpaceOnlyRegion.java
new file mode 100644
index 0000000000..2727095457
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/WhiteSpaceOnlyRegion.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+
+
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.sse.core.util.Utilities;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class WhiteSpaceOnlyRegion implements ITextRegion {
+ static private final byte fTextLength = 0;
+
+ static private final String fType = XMLRegionContext.WHITE_SPACE;
+ protected int fLength;
+ protected int fStart;
+
+ public WhiteSpaceOnlyRegion(int start, int length) {
+ super();
+ fStart = start;
+ fLength = length;
+ }
+
+ public void adjust(int i) {
+ fStart += i;
+ }
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ // not supported
+
+ }
+
+ public boolean contains(int position) {
+
+ return fStart <= position && position < fStart + fLength;
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = region.getLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public void setLength(int i) {
+ fLength = i;
+ }
+
+ public void setStart(int i) {
+ fStart = i;
+ }
+
+ public void setTextLength(short i) {
+ throw new SourceEditingRuntimeException("invalid call"); //$NON-NLS-1$
+ }
+
+ public void setType(String string) {
+ throw new SourceEditingRuntimeException("invalid call"); //$NON-NLS-1$
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+ /**
+ * For this ITextRegion type, the start must in terms of what the region
+ * expects ... that is, its not document offset, but start relative to
+ * what ever contains it.
+ */
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // if the region is an easy type (e.g. attribute value),
+ // and the requested changes are all
+ // alphanumeric, then make the change here locally.
+ // (This can obviously be made more sophisticated as the need arises,
+ // but should
+ // always follow this pattern.)
+ if (Debug.debugStructuredDocument) {
+ System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+ System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+ }
+ boolean canHandle = false;
+ // note: we'll always handle deletes from these
+ // regions ... if its already that region,
+ // deleting something from it won't change its
+ // type. (remember, the calling program needs
+ // to insure we are not called, if not all contained
+ // on one region.
+ if ((changes == null) || (changes.length() == 0)) {
+ // delete case
+ // We can not do the quick delete, if
+ // if all the text in a region is to be deleted.
+ // Or, if the delete starts in the white space region.
+ // In these cases, a reparse is needed.
+ // Minor note, we use textEnd-start since it always
+ // less than or equal to end-start. This might
+ // cause us to miss a few cases we could have handled,
+ // but will prevent us from trying to handle funning cases
+ // involving whitespace.
+ if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+ canHandle = false;
+ } else {
+ canHandle = true;
+ }
+ } else {
+ if (RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) {
+ canHandle = true;
+ } else {
+ canHandle = false;
+ }
+
+ }
+ RegionChangedEvent result = null;
+
+ if (canHandle) {
+ // at this point, we still have the old region. We won't create a
+ // new instance, we'll just update the one we have, by changing
+ // its end postion,
+ // The parent flatnode, upon return, has responsibility
+ // for updating sibling regions.
+ // and in turn, the structuredDocument itself has responsibility
+ // for
+ // updating the text store and down stream flatnodes.
+ if (Debug.debugStructuredDocument) {
+ System.out.println("change handled by region"); //$NON-NLS-1$
+ }
+ int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+ // Note: we adjust both end and text end, because for any change
+ // that is in only the trailing whitespace region, we should not
+ // do a quick change,
+ // so 'canHandle' should have been false for those case.
+ fLength += lengthDifference;
+
+ result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+ }
+
+ return result;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLCDataTextRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLCDataTextRegion.java
new file mode 100644
index 0000000000..e6f3cbecef
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLCDataTextRegion.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.sse.core.util.Utilities;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class XMLCDataTextRegion implements ITextRegion {
+ static private final String fType = XMLRegionContext.XML_CDATA_TEXT;
+ private int fLength;
+ private int fStart;
+ private int fTextLength;
+
+
+ public XMLCDataTextRegion() {
+ super();
+ }
+
+ public XMLCDataTextRegion(int start, int textLength, int length) {
+ this();
+ fStart = start;
+ fTextLength = textLength;
+ fLength = length;
+ }
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ fTextLength += i;
+
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = region.getLength();
+ fTextLength = region.getTextLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ // TODO: shouldn't cdata be like XML Content ... length and text
+ // length
+ // always be the same, regardless of whitespace?
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // TODO: this is a pretty lame method, since XML CData region can have
+ // a much
+ // better rule for region update, but this is what previous
+ // (unfactored)
+ // version had, so I'll carry it over, of now.
+ RegionChangedEvent result = null;
+ // if the region is an easy type (e.g. attribute value),
+ // and the requested changes are all
+ // alphanumeric, then make the change here locally.
+ // (This can obviously be made more sophisticated as the need arises,
+ // but should
+ // always follow this pattern.)
+ if (Debug.debugStructuredDocument) {
+ System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+ System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+ }
+ boolean canHandle = false;
+ // note: we'll always handle deletes from these
+ // regions ... if its already that region,
+ // deleting something from it won't change its
+ // type. (remember, the calling program needs
+ // to insure we are not called, if not all contained
+ // on one region.
+ if ((changes == null) || (changes.length() == 0)) {
+ // delete case
+ // We can not do the quick delete, if
+ // if all the text in a region is to be deleted.
+ // Or, if the delete starts in the white space region.
+ // In these cases, a reparse is needed.
+ // Minor note, we use textEnd-start since it always
+ // less than or equal to end-start. This might
+ // cause us to miss a few cases we could have handled,
+ // but will prevent us from trying to handle funning cases
+ // involving whitespace.
+ if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+ canHandle = false;
+ } else {
+ canHandle = true;
+ }
+ } else {
+ if ((RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(this, parent, changes, requestStart, lengthToReplace)) {
+ canHandle = true;
+ } else {
+ canHandle = false;
+ }
+
+ }
+ if (canHandle) {
+ // at this point, we still have the old region. We won't create a
+ // new instance, we'll just update the one we have, by changing
+ // its end postion,
+ // The parent flatnode, upon return, has responsibility
+ // for updating sibling regions.
+ // and in turn, the structuredDocument itself has responsibility
+ // for
+ // updating the text store and down stream flatnodes.
+ if (Debug.debugStructuredDocument) {
+ System.out.println("change handled by region"); //$NON-NLS-1$
+ }
+ int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+ // Note: we adjust both end and text end, because for any change
+ // that is in only the trailing whitespace region, we should not
+ // do a quick change,
+ // so 'canHandle' should have been false for those case.
+ // TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+ // If we are handling as whitespace, there is no need to increase
+ // the text length, only
+ // the total length is changing.
+ if (!RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) {
+ fTextLength += lengthDifference;
+ }
+ fLength += lengthDifference;
+ result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+ }
+
+ return result;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLContentRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLContentRegion.java
new file mode 100644
index 0000000000..7155dfcedf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLContentRegion.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.sse.core.util.Utilities;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+
+public class XMLContentRegion implements ITextRegion {
+ static private final String fType = XMLRegionContext.XML_CONTENT;
+ // length and textLength are always the same for content region
+ //private int fTextLength;
+ private int fLength;
+ private int fStart;
+
+
+ public XMLContentRegion() {
+ super();
+ }
+
+ public XMLContentRegion(int start, int length) {
+ this();
+ fStart = start;
+ fLength = length;
+ }
+
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ // not supported
+
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = region.getLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public int getTextEnd() {
+ return fStart + fLength;
+ }
+
+ public int getTextLength() {
+ return fLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // TODO: this is a pretty lame method, since XML Content can have a
+ // much
+ // better rule for region update, but this is what previous
+ // (unfactored)
+ // version had, so I'll carry it over, of now.
+ RegionChangedEvent result = null;
+ // if the region is an easy type (e.g. attribute value),
+ // and the requested changes are all
+ // alphanumeric, then make the change here locally.
+ // (This can obviously be made more sophisticated as the need arises,
+ // but should
+ // always follow this pattern.)
+ if (Debug.debugStructuredDocument) {
+ System.out.println("\t\tContextRegion::updateModel"); //$NON-NLS-1$
+ System.out.println("\t\t\tregion type is " + fType); //$NON-NLS-1$
+ }
+ boolean canHandle = false;
+ // note: we'll always handle deletes from these
+ // regions ... if its already that region,
+ // deleting something from it won't change its
+ // type. (remember, the calling program needs
+ // to insure we are not called, if not all contained
+ // on one region.
+ if ((changes == null) || (changes.length() == 0)) {
+ // delete case
+ // We can not do the quick delete, if
+ // if all the text in a region is to be deleted.
+ // Or, if the delete starts in the white space region.
+ // In these cases, a reparse is needed.
+ // Minor note, we use textEnd-start since it always
+ // less than or equal to end-start. This might
+ // cause us to miss a few cases we could have handled,
+ // but will prevent us from trying to handle funning cases
+ // involving whitespace.
+ if ((fStart >= getTextEnd()) || (Math.abs(lengthToReplace) >= getTextEnd() - getStart())) {
+ canHandle = false;
+ } else {
+ canHandle = true;
+ }
+ } else {
+ if ((RegionUpdateRule.canHandleAsWhiteSpace(this, parent, changes, requestStart, lengthToReplace)) || RegionUpdateRule.canHandleAsLetterOrDigit(this, parent, changes, requestStart, lengthToReplace)) {
+ canHandle = true;
+ } else {
+ canHandle = false;
+ }
+
+ }
+ if (canHandle) {
+ // at this point, we still have the old region. We won't create a
+ // new instance, we'll just update the one we have, by changing
+ // its end postion,
+ // The parent flatnode, upon return, has responsibility
+ // for updating sibling regions.
+ // and in turn, the structuredDocument itself has responsibility
+ // for
+ // updating the text store and down stream flatnodes.
+ if (Debug.debugStructuredDocument) {
+ System.out.println("change handled by region"); //$NON-NLS-1$
+ }
+ int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+ // Note: we adjust both end and text end, because for any change
+ // that is in only the trailing whitespace region, we should not
+ // do a quick change,
+ // so 'canHandle' should have been false for those case.
+ fLength += lengthDifference;
+ // TO_DO_FUTURE: cache value of canHandleAsWhiteSpace from above
+ // If we are handling as whitespace, there is no need to increase
+ // the text length, only
+ // the total length is changing.
+ // don't need for content region
+ // if (!RegionUpdateRule.canHandleAsWhiteSpace(this, changes,
+ // fStart, lengthToReplace)) {
+ // fTextLength += lengthDifference;
+ // }
+ result = new RegionChangedEvent(parent.getParentDocument(), requester, parent, this, changes, requestStart, lengthToReplace);
+ }
+
+ return result;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserFactory.java
new file mode 100644
index 0000000000..66d9ee9413
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserFactory.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.text.ITextRegion;
+
+public class XMLHeadParserFactory {
+ public ITextRegion createToken(String context, int start, int textLength, int length, String text) {
+ ITextRegion newRegion = null;
+ // if (context == XMLRegionContext.XML_CDATA_TEXT) {
+ newRegion = new XMLHeadParserRegion(context, start, textLength, length, text);
+ // }
+ return newRegion;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserRegion.java
new file mode 100644
index 0000000000..98dad747b4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLHeadParserRegion.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+/**
+ *
+ * This class is not intended to be used, its just present to server as a
+ * generic starting point for adding new specific region types.
+ */
+
+public class XMLHeadParserRegion implements ITextRegion {
+ private int fLength;
+ private int fStart;
+ private String fText;
+ private int fTextLength;
+ // specify correct type
+ private String fType = XMLRegionContext.UNDEFINED;
+
+ public XMLHeadParserRegion() {
+ super();
+ }
+
+ public XMLHeadParserRegion(String context, int start, int textLength, int length, String text) {
+ this();
+ fType = context;
+ fStart = start;
+ fTextLength = textLength;
+ fLength = length;
+ fText = text;
+ }
+
+ public void adjustLengthWith(int i) {
+ fLength += i;
+
+ }
+
+ public void adjustStart(int i) {
+ fStart += i;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
+ */
+ public void adjustTextLength(int i) {
+ fTextLength += 1;
+
+ }
+
+ public void equatePositions(ITextRegion region) {
+ fStart = region.getStart();
+ fLength = region.getLength();
+ fTextLength = region.getTextLength();
+ }
+
+ public int getEnd() {
+ return fStart + fLength;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public int getStart() {
+ return fStart;
+ }
+
+ public String getText() {
+ return fText;
+ }
+
+ public int getTextEnd() {
+ return fStart + fTextLength;
+ }
+
+ public int getTextLength() {
+ return fTextLength;
+ }
+
+ public String getType() {
+ return fType;
+ }
+
+ public String toString() {
+ return RegionToStringUtil.toString(this);
+ }
+
+ public StructuredDocumentEvent updateModel(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+ // can never be updated
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java
new file mode 100644
index 0000000000..6b03796502
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/parser/regions/XMLParserRegionFactory.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.parser.regions;
+
+
+
+import org.eclipse.wst.sse.core.internal.parser.ContextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionContainer;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+/**
+ *
+ * This region factory is very specific to the parser output, and the specific
+ * implementation classes for various regions.
+ */
+
+public class XMLParserRegionFactory {
+
+ public XMLParserRegionFactory() {
+ super();
+ }
+
+ public ITextRegion createToken(ITextRegionContainer parent, String context, int start, int textLength, int length) {
+ return this.createToken(parent, context, start, textLength, length, null, null);
+ }
+
+ public ITextRegion createToken(ITextRegionContainer parent, String context, int start, int textLength, int length, String lang, String surroundingTag) {
+ ITextRegion newRegion = createToken(context, start, textLength, length);
+ // DW, 4/16/2003 token regions no longer have parents
+ //newRegion.setParent(parent);
+ return newRegion;
+ }
+
+ public ITextRegion createToken(String context, int start, int textLength, int length) {
+ return this.createToken(context, start, textLength, length, null, null);
+ }
+
+ public ITextRegion createToken(String context, int start, int textLength, int length, String lang, String surroundingTag) {
+ ITextRegion newRegion = null;
+ if (context == XMLRegionContext.XML_CDATA_TEXT) {
+ newRegion = new XMLCDataTextRegion(start, textLength, length);
+ } else if (context == XMLRegionContext.XML_CONTENT) {
+ newRegion = new XMLContentRegion(start, length);
+ } else if (context == XMLRegionContext.XML_TAG_NAME) {
+ newRegion = new TagNameRegion(start, textLength, length);
+ } else if (context == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+ newRegion = new AttributeNameRegion(start, textLength, length);
+ } else if (context == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+ newRegion = new AttributeEqualsRegion(start, textLength, length);
+ } else if (context == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+ newRegion = new AttributeValueRegion(start, textLength, length);
+ } else if (context == XMLRegionContext.XML_TAG_OPEN) {
+ newRegion = new TagOpenRegion(start, textLength, length);
+ } else if (context == XMLRegionContext.XML_TAG_CLOSE) {
+ newRegion = new TagCloseRegion(start);
+ } else if (context == XMLRegionContext.WHITE_SPACE) {
+ newRegion = new WhiteSpaceOnlyRegion(start, length);
+ } else
+ // removed this condition during transition, and implemented in
+ // subclass
+ // if (context == XMLJSPRegionContexts.JSP_CONTENT) {
+ // newRegion = new JSPCodeRegion(context, start, textLength, length);
+ // } else
+ if (context == XMLRegionContext.BLOCK_TEXT) {
+ newRegion = new BlockTextRegion(context, start, textLength, length);
+ ((BlockTextRegion) newRegion).setSurroundingTag(surroundingTag);
+ } else {
+ newRegion = new ContextRegion(context, start, textLength, length);
+ }
+ return newRegion;
+ }
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterFactoryImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterFactoryImpl.java
new file mode 100644
index 0000000000..ed13b8a959
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterFactoryImpl.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.propagate;
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.PropagatingAdapter;
+import org.eclipse.wst.sse.core.PropagatingAdapterFactory;
+
+
+/**
+ * The PropagatingAdapterFactory is part of the "adapt on create" mechanism. A
+ * PropagatingAdapter, once added to a node, will cause proagating adapters to
+ * be created for all child nodes. A side effect of creating a
+ * PropagatingAdapter for a node is that is is also creates adapters for and
+ * adapts the Node for all other registered 'create on adapt' Adapters. This
+ * other adapters are registered by registering their factories via plugin
+ * extension point.
+ */
+public class PropagatingAdapterFactoryImpl extends AbstractAdapterFactory implements PropagatingAdapterFactory {
+
+ private PropagatingAdapter adapterInstance;
+ protected List contributedFactories = null;
+
+ /**
+ * PropagatingAdapterFactory constructor comment.
+ */
+ public PropagatingAdapterFactoryImpl() {
+ this(PropagatingAdapter.class, true);
+ }
+
+ protected PropagatingAdapterFactoryImpl(Object adapterKey, boolean registerAdapters) { //,
+ // Object
+ // modelType)
+ // {
+ super(adapterKey, registerAdapters);
+ }
+
+ public void addContributedFactories(AdapterFactory factory) {
+ if (contributedFactories != null) {
+ contributedFactories.add(factory);
+ }
+
+ }
+
+ public AdapterFactory copy() {
+ PropagatingAdapterFactory clonedInstance = new PropagatingAdapterFactoryImpl(this.adapterKey, this.shouldRegisterAdapter);
+ // clone this adapters specific list of adapter factories too
+ if (contributedFactories != null) {
+ Iterator iterator = contributedFactories.iterator();
+ clonedInstance.setContributedFactories(new ArrayList());
+ while (iterator.hasNext()) {
+ AdapterFactory existingFactory = (AdapterFactory) iterator.next();
+ clonedInstance.addContributedFactories(existingFactory.copy());
+ }
+ }
+ return clonedInstance;
+ }
+
+ /**
+ * createAdapter method comment.
+ */
+ protected INodeAdapter createAdapter(INodeNotifier target) {
+ // every notifier get's one of these
+ // (and the same instance of it)
+ return getAdapterInstance();
+ }
+
+ /**
+ * Gets the adapterInstance.
+ *
+ * @return Returns a PropagatingAdapter
+ */
+ protected PropagatingAdapter getAdapterInstance() {
+ if (adapterInstance == null) {
+ adapterInstance = new PropagatingAdapterImpl();
+ if (contributedFactories != null) {
+ for (int i = 0; i < contributedFactories.size(); i++)
+ adapterInstance.addAdaptOnCreateFactory((PropagatingAdapterFactory) contributedFactories.get(i));
+ }
+ }
+ return adapterInstance;
+ }
+
+ public void release() {
+ // give the adapter instance a chance to release its factories
+ getAdapterInstance().release();
+
+ }
+
+ public void setContributedFactories(ArrayList list) {
+ contributedFactories = list;
+
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterImpl.java
new file mode 100644
index 0000000000..4f0b3201f0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/propagate/PropagatingAdapterImpl.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.propagate;
+
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.PropagatingAdapter;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class PropagatingAdapterImpl implements PropagatingAdapter {
+
+ public static final Class PropagatingAdapterClass = PropagatingAdapter.class;
+ // because so many of these are created in huge file,
+ // Jeffrey Liu suggested these be done lazily, since not all
+ // models and not all nodes actually have a list of factories.
+ private List adaptOnCreateFactories = null;
+
+ /**
+ * AbstractPropagatingAdapterImpl constructor comment.
+ */
+ public PropagatingAdapterImpl() {
+ super();
+ }
+
+ protected void adaptOnCreate(XMLNode node) {
+ // give each of the factories a chance to adapt the node, if it
+ // chooses to
+ if (adaptOnCreateFactories != null) {
+ Iterator iterator = adaptOnCreateFactories.iterator();
+ while (iterator.hasNext()) {
+ AdapterFactory factory = (AdapterFactory) iterator.next();
+ factory.adapt(node);
+ }
+ }
+
+ }
+
+ /**
+ * This mechanism can be made "easier to use" later.
+ */
+ public void addAdaptOnCreateFactory(AdapterFactory factory) {
+ //adaptOnCreateFactories.add(factory);
+ getAdaptOnCreateFactories().add(factory);
+ }
+
+ /**
+ * Gets the adaptOnCreateFactories.
+ *
+ * @return Returns a List
+ */
+ public List getAdaptOnCreateFactories() {
+ if (adaptOnCreateFactories == null)
+ adaptOnCreateFactories = new ArrayList();
+ return adaptOnCreateFactories;
+ }
+
+ // protected void unadaptOnRemove(INodeNotifier node) {
+ // // give each of the factories a chance to process remove event
+ // // This is a bit out of the normal adapter pattern, but I couldn't
+ // // think of a better way to "remove" pageDirectiveWatchers, if and
+ // // when the page directive was 'removed' (edited).
+ // //
+ // Iterator iterator = adaptOnCreateFactories.iterator();
+ // while (iterator.hasNext()) {
+ // AdapterFactory factory = (AdapterFactory) iterator.next();
+ // if (factory instanceof PropagatingAdapterFactory) {
+ // ((PropagatingAdapterFactory)factory).unadapt(node);
+ // }
+ // }
+ //
+ // }
+
+ /**
+ * @see PropagatingAdapter#initializeForFactory(AdapterFactory,
+ * INodeNotifier)
+ */
+ public void initializeForFactory(AdapterFactory factory, INodeNotifier node) {
+ // we're DOM specific implimentation
+ if (node instanceof XMLNode) {
+ XMLNode xmlNode = (XMLNode) node;
+ propagateTo(xmlNode);
+ }
+ }
+
+ /**
+ * Allowing the INodeAdapter to compare itself against the type allows it
+ * to return true in more than one case.
+ */
+ public boolean isAdapterForType(Object type) {
+ return type.equals(PropagatingAdapterClass);
+ }
+
+ protected boolean isInteresting(Object newValue) {
+ return (newValue != null && (newValue instanceof Element || newValue instanceof Document || newValue instanceof DocumentType));
+ }
+
+ /**
+ */
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ // DMW, 2002.8.10. I changed this so we only propagate to Elements ...
+ // not attributes too!
+ // I'm assuming this will help performance and memory, but don't know
+ // if anyone was depending on
+ // this being proagate to attributes.
+ if (eventType == INodeNotifier.ADD && isInteresting(newValue)) {
+ propagateTo((XMLNode) newValue);
+ }
+ // else if (eventType == INodeNotifier.CONTENT_CHANGED) {
+ // notifier.getAdapterFor(PropagatingAdapterClass);
+ // }
+ // else if (eventType == INodeNotifier.CHANGE) {
+ // }
+ // else if (eventType == INodeNotifier.REMOVE &&
+ // isInteresting(oldValue)) {
+ // unadaptOnRemove((XMLNode)oldValue);
+ // }
+ // else if (eventType == INodeNotifier.STRUCTURE_CHANGED) {
+ // }
+ }
+
+ protected void propagateTo(XMLNode node) {
+ // get adapter to ensure its created
+ node.getAdapterFor(PropagatingAdapterClass);
+ adaptOnCreate(node);
+ propagateToChildren(node);
+ }
+
+ protected void propagateToChildren(XMLNode parent) {
+ for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+ propagateTo((XMLNode) child);
+ }
+ }
+
+ /**
+ * @see PropagatingAdapter#release()
+ */
+ public void release() {
+ if (adaptOnCreateFactories != null) {
+ Iterator iterator = adaptOnCreateFactories.iterator();
+ while (iterator.hasNext()) {
+ AdapterFactory factory = (AdapterFactory) iterator.next();
+ factory.release();
+ }
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/XMLStructuredDocumentRegion.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/XMLStructuredDocumentRegion.java
new file mode 100644
index 0000000000..77de14a4e7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/text/XMLStructuredDocumentRegion.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.text;
+
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class XMLStructuredDocumentRegion extends BasicStructuredDocumentRegion implements IStructuredDocumentRegion {
+
+ public XMLStructuredDocumentRegion() {
+ super();
+ }
+
+ public String getType() {
+ String result = super.getType();
+ // normally, we want the second region as the flatnode type ... since
+ // the
+ // first one is usually just "open tag".
+ if ((result != XMLRegionContext.XML_PI_OPEN) && (getRegions().size() > 1)) {
+ result = getRegions().get(1).getType();
+ }
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/util/DebugDocument.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/util/DebugDocument.java
new file mode 100644
index 0000000000..13afbc8647
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/util/DebugDocument.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.util;
+
+import java.io.PrintStream;
+
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class DebugDocument {
+
+ public static void dump(Document document) {
+ if (document == null)
+ return;
+ System.out.println("Dump of DOM"); //$NON-NLS-1$
+
+ dump(document, System.out);
+
+ //
+ System.out.println();
+ System.out.println("= = = = = ="); //$NON-NLS-1$
+ System.out.println();
+
+ }
+
+ public static void dump(Document document, PrintStream out) {
+ Node node = document.getFirstChild();
+ while (node != null) {
+ dump(node, out);
+ node = node.getNextSibling();
+ }
+
+ }
+
+ public static void dump(Node topNode) {
+ dump(topNode, System.out);
+ }
+
+ public static void dump(Node topNode, PrintStream out) {
+ if (topNode == null)
+ return;
+ // print out this node
+ //
+ printNode(topNode, out);
+
+ // now print out its children
+ //NodeList nodes = topNode.getChildNodes();
+ //int len = nodes.getLength();
+ //for (int i = 0; i < len; i++) {
+
+ //Node node = nodes.item(i);
+ //dump(node, out);
+ //}
+ }
+
+ public static void printNode(Node topNode) {
+ printNode(topNode, System.out);
+
+ }
+
+ public static void printNode(Node topNode, PrintStream out) {
+ // print out this node
+ //
+ IStructuredDocumentRegion firstStructuredDocumentRegion = ((XMLNode) topNode).getFirstStructuredDocumentRegion();
+ IStructuredDocumentRegion lastStructuredDocumentRegion = ((XMLNode) topNode).getLastStructuredDocumentRegion();
+ if ((firstStructuredDocumentRegion == null) || (lastStructuredDocumentRegion == null)) {
+ // no text to output
+ } else {
+ int start = firstStructuredDocumentRegion.getStart();
+ int end = lastStructuredDocumentRegion.getEnd();
+
+ String outString = topNode.toString();
+ outString = org.eclipse.wst.sse.core.util.StringUtils.escape(outString);
+ out.println("[" + start + ", " + end + "]" + outString); //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ }
+ // now do its children
+ NodeList nodes = topNode.getChildNodes();
+ int len = nodes.getLength();
+ for (int i = 0; i < len; i++) {
+ Node childNode = nodes.item(i);
+ printNode(childNode, out);
+ }
+
+ }
+
+ public DebugDocument() {
+ super();
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/AbstractPropagatingValidator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/AbstractPropagatingValidator.java
new file mode 100644
index 0000000000..9144662bd2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/AbstractPropagatingValidator.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validate;
+
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.validate.ValidationAdapter;
+import org.w3c.dom.Node;
+
+
+public abstract class AbstractPropagatingValidator extends ValidationComponent {
+
+ /**
+ * Constructor for AbstractPropagatingValidator.
+ */
+ public AbstractPropagatingValidator() {
+ super();
+ }
+
+ protected abstract ValidationComponent getPropagatee();
+
+ protected abstract ValidationAdapter getValidator();
+
+ /**
+ * @see com.ibm.sed.adapters.validate.ValidationAdapter#validate(IndexedRegion)
+ */
+ public void validate(IndexedRegion node) {
+ if (node == null)
+ return;
+ getValidator().validate(node);
+
+
+ Propagator.propagateToChildElements(getPropagatee(), (Node) node);
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/Propagator.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/Propagator.java
new file mode 100644
index 0000000000..3cdcca5312
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/Propagator.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validate;
+
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.validate.ValidationAdapter;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class Propagator {
+
+ public static void propagateToChildElements(ValidationComponent validator, Node parent) {
+ if (parent == null)
+ return;
+ Class clazz = validator.getClass();
+
+ NodeList children = parent.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ Node child = children.item(i);
+ if (child == null || child.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ INodeNotifier notifier = (INodeNotifier) child;
+ ValidationAdapter va = (ValidationAdapter) notifier.getExistingAdapter(clazz);
+ if (va == null) {
+ notifier.addAdapter(validator);
+ va = validator;
+ }
+ va.validate((IndexedRegion) child);
+ }
+ }
+
+ /**
+ * Propagator is just a placeholder of utilities. Don't instantiate.
+ */
+ private Propagator() {
+ super();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/ValidationComponent.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/ValidationComponent.java
new file mode 100644
index 0000000000..797d9cbf0a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/validate/ValidationComponent.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.internal.validate;
+
+
+
+import org.eclipse.wst.sse.core.validate.ValidationAdapter;
+import org.eclipse.wst.sse.core.validate.ValidationReporter;
+
+public abstract class ValidationComponent implements ValidationAdapter {
+
+ protected ValidationReporter reporter = null;
+
+ /**
+ * ValidationComponent constructor comment.
+ */
+ public ValidationComponent() {
+ super();
+ }
+
+ /**
+ * Allowing the INodeAdapter to compare itself against the type allows it
+ * to return true in more than one case.
+ */
+ public boolean isAdapterForType(Object type) {
+ return (type == ValidationAdapter.class);
+ }
+
+ /**
+ */
+ public void notifyChanged(org.eclipse.wst.sse.core.INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ // This method will be implemented in the V2.
+ }
+
+ /**
+ */
+ public void setReporter(ValidationReporter reporter) {
+ this.reporter = reporter;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/jsp/model/parser/temp/XMLJSPRegionContexts.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/jsp/model/parser/temp/XMLJSPRegionContexts.java
new file mode 100644
index 0000000000..26a8e1ca96
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/jsp/model/parser/temp/XMLJSPRegionContexts.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.jsp.model.parser.temp;
+
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+/**
+ * //TODO
+ *
+ * @deprecated - marked as deprecated to warn of pending changes. See the
+ * package.html file for full explaination.
+ */
+
+public interface XMLJSPRegionContexts extends XMLRegionContext {
+ public static final String JSP_CLOSE = "JSP_CLOSE"; //$NON-NLS-1$
+ public static final String JSP_COMMENT_CLOSE = "JSP_COMMENT_CLOSE"; //$NON-NLS-1$
+
+ public static final String JSP_COMMENT_OPEN = "JSP_COMMENT_OPEN"; //$NON-NLS-1$
+ public static final String JSP_COMMENT_TEXT = "JSP_COMMENT_TEXT"; //$NON-NLS-1$
+
+ public static final String JSP_CONTENT = "JSP_CONTENT"; //$NON-NLS-1$
+ public static final String JSP_DECLARATION_OPEN = "JSP_DECLARATION_OPEN"; //$NON-NLS-1$
+ public static final String JSP_DIRECTIVE_CLOSE = "JSP_DIRECTIVE_CLOSE"; //$NON-NLS-1$
+ public static final String JSP_DIRECTIVE_NAME = "JSP_DIRECTIVE_NAME"; //$NON-NLS-1$
+
+ public static final String JSP_DIRECTIVE_OPEN = "JSP_DIRECTIVE_OPEN"; //$NON-NLS-1$
+ public static final String JSP_EL_CLOSE = "JSP_EL_CLOSE"; //$NON-NLS-1$
+ public static final String JSP_EL_CONTENT = "JSP_EL_CONTENT"; //$NON-NLS-1$
+ public static final String JSP_EL_DQUOTE = "JSP_EL_DQUOTE"; //$NON-NLS-1$
+
+ public static final String JSP_EL_OPEN = "JSP_EL_OPEN"; //$NON-NLS-1$
+ public static final String JSP_EL_QUOTED_CONTENT = "JSP_EL_QUOTED_CONTENT"; //$NON-NLS-1$
+ public static final String JSP_EL_SQUOTE = "JSP_EL_SQUOTE"; //$NON-NLS-1$
+ public static final String JSP_EXPRESSION_OPEN = "JSP_EXPRESSION_OPEN"; //$NON-NLS-1$
+
+ public static final String JSP_ROOT_TAG_NAME = "JSP_ROOT_TAG_NAME"; //$NON-NLS-1$
+
+ public static final String JSP_SCRIPTLET_OPEN = "JSP_SCRIPTLET_OPEN"; //$NON-NLS-1$
+ public static final String JSP_VBL_CLOSE = "JSP_VBL_CLOSE"; //$NON-NLS-1$
+ public static final String JSP_VBL_CONTENT = "JSP_VBL_CONTENT"; //$NON-NLS-1$
+ public static final String JSP_VBL_DQUOTE = "JSP_VBL_DQUOTE"; //$NON-NLS-1$
+ public static final String JSP_VBL_OPEN = "JSP_VBL_OPEN"; //$NON-NLS-1$
+ public static final String JSP_VBL_QUOTED_CONTENT = "JSP_VBL_QUOTED_CONTENT"; //$NON-NLS-1$
+ public static final String JSP_VBL_SQUOTE = "JSP_VBL_SQUOTE"; //$NON-NLS-1$
+ public static final String XML_TAG_ATTRIBUTE_VALUE_DQUOTE = "XML_TAG_ATTRIBUTE_VALUE_DQUOTE"; //$NON-NLS-1$
+
+ public static final String XML_TAG_ATTRIBUTE_VALUE_SQUOTE = "XML_TAG_ATTRIBUTE_VALUE_SQUOTE"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/jsp/model/parser/temp/package.html b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/jsp/model/parser/temp/package.html
new file mode 100644
index 0000000000..8e9ef20b30
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/jsp/model/parser/temp/package.html
@@ -0,0 +1,8 @@
+<HTML>
+This package is located here in the XML project
+temporarily. Once the DOM Parser is cleaningly split
+to XML and JSP components, this package will move
+back to JSP project. (If its not here temporarily,
+its easy to get circluar references in plugin.xml
+dependancies.
+</HTML> \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/EmbeddedXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/EmbeddedXML.java
new file mode 100644
index 0000000000..db6917779e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/EmbeddedXML.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.modelhandler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.IFactoryRegistry;
+import org.eclipse.wst.sse.core.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.parser.JSPCapableParser;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryAdapterFactoryForEmbeddedXML;
+
+
+public class EmbeddedXML implements EmbeddedTypeHandler {
+
+ private static List supportedMimeTypes;
+ public String ContentTypeID_EmbeddedXML = "org.eclipse.wst.xml.core.contenttype.EmbeddedXML"; //$NON-NLS-1$
+
+ /**
+ * Constructor for EmbeddedXML.
+ */
+ public EmbeddedXML() {
+ super();
+ }
+
+ /*
+ * @see EmbeddedContentType#getAdapterFactories()
+ */
+ public List getAdapterFactories() {
+ List factories = new ArrayList();
+ factories.add(new ModelQueryAdapterFactoryForEmbeddedXML());
+ // factories.addAll(PluginContributedFactoryReader.getInstance().getFactories(this));
+ return factories;
+ }
+
+ /**
+ * @see EmbeddedContentType#getFamilyId()
+ */
+ public String getFamilyId() {
+ return ModelHandlerForXML.AssociatedContentTypeID;
+ }
+
+ public List getSupportedMimeTypes() {
+ if (supportedMimeTypes == null) {
+ supportedMimeTypes = new ArrayList();
+ supportedMimeTypes.add("text/xml"); //$NON-NLS-1$
+ }
+ return supportedMimeTypes;
+ }
+
+ public void initializeFactoryRegistry(IFactoryRegistry registry) {
+ //TODO: initialize
+ }
+
+ /*
+ * @see EmbeddedContentType#initializeParser(RegionParser)
+ */
+ public void initializeParser(JSPCapableParser parser) {
+ // nothing to initialize for "pure" XML
+ // compare with XHTML
+ }
+
+ public boolean isDefault() {
+ return false;
+ }
+
+ public EmbeddedTypeHandler newInstance() {
+ return new EmbeddedXML();
+ }
+
+ public void uninitializeFactoryRegistry(IFactoryRegistry registry) {
+ // TODO: need to undo anything we did in initialize
+
+ }
+
+ public void uninitializeParser(JSPCapableParser parser) {
+ // need to undo anything we did in initialize
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/ModelHandlerForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/ModelHandlerForXML.java
new file mode 100644
index 0000000000..5589f6d15d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/ModelHandlerForXML.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.modelhandler;
+
+import org.eclipse.wst.sse.core.ModelLoader;
+import org.eclipse.wst.sse.core.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.modelhandler.AbstractModelHandler;
+import org.eclipse.wst.sse.core.modelhandler.IModelHandler;
+import org.eclipse.wst.xml.core.document.DocumentLoaderForXML;
+import org.eclipse.wst.xml.core.encoding.XMLDocumentCharsetDetector;
+import org.eclipse.wst.xml.core.encoding.XMLDocumentLoader;
+
+
+/**
+ * Provides generic XML model handling. It is also marked as the default
+ * content type handler. There should be only one implementation of the
+ * default.
+ */
+public class ModelHandlerForXML extends AbstractModelHandler implements IModelHandler {
+ /**
+ * Needs to match what's in plugin registry. In fact, can be overwritten
+ * at run time with what's in registry! (so should never be 'final')
+ */
+ static String AssociatedContentTypeID = "org.eclipse.wst.xml.core.xmlsource"; //$NON-NLS-1$
+ /**
+ * Needs to match what's in plugin registry. In fact, can be overwritten
+ * at run time with what's in registry! (so should never be 'final')
+ */
+ private static String ModelHandlerID = "org.eclipse.wst.sse.core.handler.xml"; //$NON-NLS-1$
+
+ public ModelHandlerForXML() {
+ super();
+ setId(ModelHandlerID);
+ setAssociatedContentTypeId(AssociatedContentTypeID);
+ }
+
+ public IDocumentLoader getDocumentLoader() {
+ if (USE_FILE_BUFFERS)
+ return new DocumentLoaderForXML();
+ else
+ return new XMLDocumentLoader();
+ }
+
+ public IDocumentCharsetDetector getEncodingDetector() {
+ return new XMLDocumentCharsetDetector();
+ }
+
+ public ModelLoader getModelLoader() {
+ return new XMLModelLoader();
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/XMLModelLoader.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/XMLModelLoader.java
new file mode 100644
index 0000000000..dc50328715
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelhandler/XMLModelLoader.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.modelhandler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.AbstractModelLoader;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.ModelLoader;
+import org.eclipse.wst.sse.core.PropagatingAdapter;
+import org.eclipse.wst.sse.core.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.encoding.XMLDocumentLoader;
+import org.eclipse.wst.xml.core.internal.DebugAdapterFactory;
+import org.eclipse.wst.xml.core.internal.document.XMLModelImpl;
+import org.eclipse.wst.xml.core.internal.propagate.PropagatingAdapterFactoryImpl;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryAdapterFactoryForXML;
+
+
+/**
+ * This class reads an XML file and creates an XML Structured Model.
+ *
+ */
+public class XMLModelLoader extends AbstractModelLoader {
+
+ // private static final String STR_ENCODING = "encoding"; //$NON-NLS-1$
+
+ /**
+ * XMLLoader constructor comment.
+ */
+ public XMLModelLoader() {
+ super();
+ }
+
+ public List getAdapterFactories() {
+ List result = new ArrayList();
+ AdapterFactory factory = null;
+ // TODO different ModelQueryAdapterFactories need to be made for each
+ // type/loader
+ factory = new ModelQueryAdapterFactoryForXML();
+ result.add(factory);
+ // Does XML need propagating adapter? Or just JSP?
+ factory = new PropagatingAdapterFactoryImpl();
+ result.add(factory);
+ return result;
+ }
+
+ public IDocumentLoader getDocumentLoader() {
+ if (documentLoaderInstance == null) {
+ documentLoaderInstance = new XMLDocumentLoader();
+ }
+ return documentLoaderInstance;
+ }
+
+ public ModelLoader newInstance() {
+ return new XMLModelLoader();
+ }
+
+ public IStructuredModel newModel() {
+ return new XMLModelImpl();
+ }
+
+ protected void preLoadAdapt(IStructuredModel structuredModel) {
+ super.preLoadAdapt(structuredModel);
+ XMLModel domModel = (XMLModel) structuredModel;
+ // if there is a model in the adapter, this will adapt it to
+ // first node. After that the PropagatingAdater spreads over the
+ // children being
+ // created. Each time that happends, a side effect is to
+ // also "spread" sprecific registered adapters,
+ // they two can propigate is needed.
+ ((INodeNotifier) domModel.getDocument()).getAdapterFor(PropagatingAdapter.class);
+
+ if (Debug.debugNotificationAndEvents) {
+ PropagatingAdapter propagatingAdapter = (PropagatingAdapter) ((INodeNotifier) domModel.getDocument()).getAdapterFor(PropagatingAdapter.class);
+ propagatingAdapter.addAdaptOnCreateFactory(new DebugAdapterFactory());
+ }
+
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryAdapterFactoryForEmbeddedXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryAdapterFactoryForEmbeddedXML.java
new file mode 100644
index 0000000000..f5b28101ac
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryAdapterFactoryForEmbeddedXML.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.modelquery;
+
+
+
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.modelquery.ModelQueryAdapter;
+
+
+public class ModelQueryAdapterFactoryForEmbeddedXML extends ModelQueryAdapterFactoryForXML {
+
+
+ /**
+ * Constructor for ModelQueryAdapterFactoryForEmbeddedXML.
+ */
+ public ModelQueryAdapterFactoryForEmbeddedXML() {
+ this(ModelQueryAdapter.class, false);
+ }
+
+ /**
+ * Constructor for ModelQueryAdapterFactoryForEmbeddedXML.
+ *
+ * @param adapterKey
+ * @param registerAdapters
+ */
+ protected ModelQueryAdapterFactoryForEmbeddedXML(Object adapterKey, boolean registerAdapters) {
+ super(adapterKey, registerAdapters);
+ }
+
+ /**
+ * @see AdapterFactory#adapt(INodeNotifier)
+ */
+ public INodeAdapter adapt(INodeNotifier object) {
+ return adaptNew(object);
+ }
+
+ protected void configureDocumentManager(CMDocumentManager mgr) {
+ super.configureDocumentManager(mgr);
+ mgr.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, true);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryAdapterFactoryForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryAdapterFactoryForXML.java
new file mode 100644
index 0000000000..eed96c316d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryAdapterFactoryForXML.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.modelquery;
+
+
+
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.sse.core.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.IModelStateListener;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.modelquery.ModelQueryAdapter;
+import org.eclipse.wst.sse.core.modelquery.ModelQueryAdapterImpl;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.uriresolver.util.IdResolver;
+
+
+public class ModelQueryAdapterFactoryForXML extends AbstractAdapterFactory implements IModelStateListener {
+
+ protected ModelQueryAdapterImpl modelQueryAdapterImpl;
+ protected IStructuredModel stateNotifier = null;
+
+ /**
+ * ModelQueryAdapterFactoryForXML constructor comment.
+ */
+ public ModelQueryAdapterFactoryForXML() {
+ this(ModelQueryAdapter.class, true);
+ }
+
+ /**
+ * ModelQueryAdapterFactoryForXML constructor comment.
+ *
+ * @param adapterKey
+ * java.lang.Object
+ * @param registerAdapters
+ * boolean
+ */
+ public ModelQueryAdapterFactoryForXML(Object adapterKey, boolean registerAdapters) {
+ super(adapterKey, registerAdapters);
+ }
+
+ protected boolean autoLoadCM() {
+ // until the existence of a CMDocumentRequesterFactory to create the
+ // load requests,
+ // return true
+ return true;
+ }
+
+ protected void configureDocumentManager(CMDocumentManager mgr) {
+ // this depends on there being a CMDocumentRequesterFactory installed
+ mgr.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, autoLoadCM());
+ }
+
+ public AdapterFactory copy() {
+
+ return new ModelQueryAdapterFactoryForXML(this.adapterKey, this.shouldRegisterAdapter);
+ }
+
+ /**
+ * createAdapter method comment.
+ */
+ protected INodeAdapter createAdapter(INodeNotifier target) {
+
+ if (org.eclipse.wst.sse.core.util.Debug.displayInfo)
+ System.out.println("-----------------------ModelQueryAdapterFactoryForXML.createAdapter" + target); //$NON-NLS-1$
+ if (modelQueryAdapterImpl == null) {
+ if (target instanceof XMLNode) {
+ XMLNode xmlNode = (XMLNode) target;
+ IStructuredModel model = stateNotifier = xmlNode.getModel();
+ stateNotifier.addModelStateListener(this);
+ String baseLocation = model.getBaseLocation();
+ if (org.eclipse.wst.sse.core.util.Debug.displayInfo)
+ System.out.println("----------------ModelQueryAdapterFactoryForXML... baseLocation : " + baseLocation); //$NON-NLS-1$
+
+ CMDocumentCache cmDocumentCache = new CMDocumentCache();
+ ModelQuery modelQuery = null;
+ IdResolver idResolver = null;
+
+ if (org.eclipse.wst.sse.core.util.Debug.displayInfo)
+ System.out.println("********XMLModelQueryImpl"); //$NON-NLS-1$
+ idResolver = new XMLCatalogIdResolver(baseLocation, model.getResolver());
+ modelQuery = new XMLModelQueryImpl(cmDocumentCache, idResolver);
+
+ // cs todo...
+ // for now we create a CMDocumentCache on a 'per editor' basis
+ // in the future we need to support a CMDocumentCache that is
+ // shared between editors
+ // nsd comment: may not be appropriate depending on
+ CMDocumentManager documentManager = modelQuery.getCMDocumentManager();
+ if (documentManager != null) {
+ configureDocumentManager(documentManager);
+ }
+ modelQueryAdapterImpl = new ModelQueryAdapterImpl(cmDocumentCache, modelQuery, idResolver);
+ }
+ }
+ return modelQueryAdapterImpl;
+ }
+
+ /**
+ * @see IModelStateListener#modelAboutToBeChanged(IStructuredModel)
+ */
+ public void modelAboutToBeChanged(IStructuredModel model) {
+ }
+
+ /**
+ * @see IModelStateListener#modelChanged(IStructuredModel)
+ */
+ public void modelChanged(IStructuredModel model) {
+ }
+
+ /**
+ * @see IModelStateListener#modelDirtyStateChanged(IStructuredModel,
+ * boolean)
+ */
+ public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
+ }
+
+ /**
+ * @see IModelStateListener#modelResourceDeleted(IStructuredModel)
+ */
+ public void modelResourceDeleted(IStructuredModel model) {
+ }
+
+ /**
+ * @see IModelStateListener#modelResourceMoved(IStructuredModel,
+ * IStructuredModel)
+ */
+ public void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel) {
+ stateNotifier.removeModelStateListener(this);
+ stateNotifier = newModel;
+ updateResolver(stateNotifier);
+ stateNotifier.addModelStateListener(this);
+ }
+
+ public void release() {
+ super.release();
+ if (stateNotifier != null)
+ stateNotifier.removeModelStateListener(this);
+ stateNotifier = null;
+ if (modelQueryAdapterImpl != null)
+ modelQueryAdapterImpl.release();
+ }
+
+ protected void updateResolver(IStructuredModel model) {
+ modelQueryAdapterImpl.setIdResolver(new XMLCatalogIdResolver(model.getBaseLocation(), model.getResolver()));
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryUtil.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryUtil.java
new file mode 100644
index 0000000000..61f8cd4d32
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/ModelQueryUtil.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.modelquery;
+
+
+
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.modelquery.ModelQueryAdapter;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.uriresolver.util.IdResolver;
+import org.w3c.dom.Document;
+
+
+/**
+ * This class is used to associate ModelQuery (and related data) with a
+ * Document (or IStructuredModel).
+ */
+public class ModelQueryUtil {
+
+ public static CMDocumentCache getCMDocumentCache(Document node) {
+ ModelQueryAdapter modelQueryAdapter = getModelQueryAdapter(node);
+ return modelQueryAdapter != null ? modelQueryAdapter.getCMDocumentCache() : null;
+ }
+
+ public static IdResolver getIdResolver(Document node) {
+ ModelQueryAdapter modelQueryAdapter = getModelQueryAdapter(node);
+ return modelQueryAdapter != null ? modelQueryAdapter.getIdResolver() : null;
+ }
+
+ public static ModelQuery getModelQuery(Document node) {
+ ModelQueryAdapter modelQueryAdapter = getModelQueryAdapter(node);
+ return modelQueryAdapter != null ? modelQueryAdapter.getModelQuery() : null;
+ }
+
+ public static ModelQuery getModelQuery(IStructuredModel model) {
+ if ((!(model instanceof XMLModel)) || model == null)
+ return null;
+ return getModelQuery(((XMLModel) model).getDocument());
+ }
+
+ public static ModelQueryAdapter getModelQueryAdapter(Document node) {
+ ModelQueryAdapter result = null;
+
+ if (node instanceof INodeNotifier) {
+ INodeNotifier notifier = (INodeNotifier) node;
+ result = (ModelQueryAdapter) notifier.getAdapterFor(ModelQueryAdapter.class);
+ }
+
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLCatalogIdResolver.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLCatalogIdResolver.java
new file mode 100644
index 0000000000..cc8da655bb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLCatalogIdResolver.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.modelquery;
+
+import org.eclipse.wst.sse.core.util.URIResolver;
+import org.eclipse.wst.xml.uriresolver.XMLCatalog;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogPlugin;
+import org.eclipse.wst.xml.uriresolver.util.IdResolver;
+import org.eclipse.wst.xml.uriresolver.util.URIHelper;
+
+
+public class XMLCatalogIdResolver implements IdResolver {
+ protected String resourceLocation;
+
+ protected URIResolver uriresolver;
+
+ public XMLCatalogIdResolver(String resourceLocation) {
+ this.resourceLocation = resourceLocation;
+ }
+
+ public XMLCatalogIdResolver(String resourceLocation, URIResolver uriresolver) {
+ this.resourceLocation = resourceLocation;
+ this.uriresolver = uriresolver;
+ }
+
+
+ /**
+ * Gets the resourceLocation.
+ *
+ * @return Returns a String
+ */
+ public String getResourceLocation() {
+ String location = resourceLocation;
+ if (location == null) {
+ if (uriresolver != null)
+ location = uriresolver.getFileBaseLocation();
+ }
+ return location;
+ }
+
+ /**
+ * @deprecated in superclass
+ */
+ public String resolveId(String publicId, String systemId) {
+ return resolveId(getResourceLocation(), publicId, systemId);
+ }
+
+ public String resolveId(String base, String publicId, String systemId) {
+ // first see if we can map the publicId to an alternative systemId
+ // note: should probably verify the mappedSystemId before ignoring the
+ // systemId
+ XMLCatalog xmlCatalog = XMLCatalogPlugin.getInstance().getDefaultXMLCatalog();
+ String mappedSystemId = xmlCatalog.getMappedSystemId(publicId, systemId);
+ if (mappedSystemId != null) {
+ systemId = mappedSystemId;
+ }
+
+ // normalize the systemId
+ boolean normalized = false;
+ // account for Web Projects and others where *any* string may legally
+ // resolve somehow
+ if (this.uriresolver != null && systemId != null) {
+ // check the provided URIResolver
+ String resolvedValue = this.uriresolver.getLocationByURI(systemId, base);
+ if (resolvedValue != null && resolvedValue.length() > 0) {
+ systemId = resolvedValue;
+ normalized = true;
+ }
+ }
+ if (!normalized) {
+ // no URIResolver available; ask the URIHelper directly
+ systemId = URIHelper.normalize(systemId, base, null);
+ normalized = true;
+ }
+ return systemId;
+ }
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLModelQueryAssociationProvider.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLModelQueryAssociationProvider.java
new file mode 100644
index 0000000000..b5a55d6d7b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLModelQueryAssociationProvider.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.modelquery;
+
+
+
+import org.eclipse.wst.common.contentmodel.modelqueryimpl.XMLAssociationProvider;
+import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.xml.uriresolver.util.IdResolver;
+import org.w3c.dom.Document;
+
+/**
+ * XMLModelQueryAssociationProvider
+ */
+class XMLModelQueryAssociationProvider extends XMLAssociationProvider {
+
+ protected IdResolver idResolver;
+
+ public XMLModelQueryAssociationProvider(CMDocumentCache cache, IdResolver idResolver) {
+ super(cache);
+ this.idResolver = idResolver;
+ }
+
+ protected String resolveGrammarURI(Document document, String publicId, String systemId) {
+ return idResolver.resolveId(publicId, systemId);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLModelQueryImpl.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLModelQueryImpl.java
new file mode 100644
index 0000000000..1ac1c16d78
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/modelquery/XMLModelQueryImpl.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.modelquery;
+
+
+
+import org.eclipse.wst.common.contentmodel.modelqueryimpl.ModelQueryImpl;
+import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.sse.core.modelquery.MovableModelQuery;
+import org.eclipse.wst.xml.uriresolver.util.IdResolver;
+
+
+public class XMLModelQueryImpl extends ModelQueryImpl implements MovableModelQuery {
+
+ protected CMDocumentCache fCache = null;
+
+ public XMLModelQueryImpl(CMDocumentCache cache, IdResolver idResolver) {
+ super(new XMLModelQueryAssociationProvider(cache, idResolver));
+ fCache = cache;
+ }
+
+ /**
+ * @see MovableModelQuery#setIdResolver(IdResolver)
+ */
+ public void setIdResolver(IdResolver newIdResolver) {
+ modelQueryAssociationProvider = new XMLModelQueryAssociationProvider(fCache, newIdResolver);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/parser/XMLRegionContext.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/parser/XMLRegionContext.java
new file mode 100644
index 0000000000..d0b42040e2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/parser/XMLRegionContext.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.parser;
+
+public interface XMLRegionContext {
+
+ public static final String BLOCK_TEXT = "BLOCK_TEXT"; //$NON-NLS-1$
+
+ public static final String UNDEFINED = "UNDEFINED"; //$NON-NLS-1$
+
+ public static final String WHITE_SPACE = "WHITE_SPACE"; //$NON-NLS-1$
+ public static final String XML_ATTLIST_DECL_CLOSE = "XML_ATTLIST_DECL_CLOSE"; //$NON-NLS-1$
+ public static final String XML_ATTLIST_DECL_CONTENT = "XML_ATTLIST_DECL_CONTENT"; //$NON-NLS-1$
+ public static final String XML_ATTLIST_DECL_NAME = "XML_ATTLIST_DECL_NAME"; //$NON-NLS-1$
+
+ public static final String XML_ATTLIST_DECLARATION = "XML_ATTLIST_DECLARATION"; //$NON-NLS-1$
+ public static final String XML_CDATA_CLOSE = "XML_CDATA_CLOSE"; //$NON-NLS-1$
+ public static final String XML_CDATA_OPEN = "XML_CDATA_OPEN"; //$NON-NLS-1$
+ public static final String XML_CDATA_TEXT = "XML_CDATA_TEXT"; //$NON-NLS-1$
+ public static final String XML_CHAR_REFERENCE = "XML_CHAR_REFERENCE"; //$NON-NLS-1$
+ public static final String XML_COMMENT_CLOSE = "XML_COMMENT_CLOSE"; //$NON-NLS-1$
+
+ public static final String XML_COMMENT_OPEN = "XML_COMMENT_OPEN"; //$NON-NLS-1$
+ public static final String XML_COMMENT_TEXT = "XML_COMMENT_TEXT"; //$NON-NLS-1$
+
+ public static final String XML_CONTENT = "XML_CONTENT"; //$NON-NLS-1$
+ public static final String XML_DECLARATION_CLOSE = "XML_DECLARATION_CLOSE"; //$NON-NLS-1$
+
+ public static final String XML_DECLARATION_OPEN = "XML_DECLARATION_OPEN"; //$NON-NLS-1$
+
+ public static final String XML_DOCTYPE_DECLARATION = "XML_DOCTYPE_DECLARATION"; //$NON-NLS-1$
+ public static final String XML_DOCTYPE_DECLARATION_CLOSE = "XML_DOCTYPE_DECLARATION_CLOSE"; //$NON-NLS-1$
+ public static final String XML_DOCTYPE_EXTERNAL_ID_PUBLIC = "XML_DOCTYPE_EXTERNAL_ID_PUBLIC"; //$NON-NLS-1$
+ public static final String XML_DOCTYPE_EXTERNAL_ID_PUBREF = "XML_DOCTYPE_EXTERNAL_ID_PUBREF"; //$NON-NLS-1$
+ public static final String XML_DOCTYPE_EXTERNAL_ID_SYSREF = "XML_DOCTYPE_EXTERNAL_ID_SYSREF"; //$NON-NLS-1$
+ public static final String XML_DOCTYPE_EXTERNAL_ID_SYSTEM = "XML_DOCTYPE_EXTERNAL_ID_SYSTEM"; //$NON-NLS-1$
+ public static final String XML_DOCTYPE_INTERNAL_SUBSET = "XML_DOCTYPE_INTERNAL_SUBSET"; //$NON-NLS-1$
+ public static final String XML_DOCTYPE_NAME = "XML_DOCTYPE_NAME"; //$NON-NLS-1$
+ public static final String XML_ELEMENT_DECL_CLOSE = "XML_ELEMENT_DECL_CLOSE"; //$NON-NLS-1$
+ public static final String XML_ELEMENT_DECL_CONTENT = "XML_ELEMENT_DECL_CONTENT"; //$NON-NLS-1$
+ public static final String XML_ELEMENT_DECL_NAME = "XML_ELEMENT_DECL_NAME"; //$NON-NLS-1$
+
+ public static final String XML_ELEMENT_DECLARATION = "XML_ELEMENT_DECLARATION"; //$NON-NLS-1$
+ public static final String XML_EMPTY_TAG_CLOSE = "XML_EMPTY_TAG_CLOSE"; //$NON-NLS-1$
+ public static final String XML_END_TAG_OPEN = "XML_END_TAG_OPEN"; //$NON-NLS-1$
+ public static final String XML_ENTITY_REFERENCE = "XML_ENTITY_REFERENCE"; //$NON-NLS-1$
+
+ public static final String XML_PE_REFERENCE = "XML_PE_REFERENCE"; //$NON-NLS-1$
+ public static final String XML_PI_CLOSE = "XML_PI_CLOSE"; //$NON-NLS-1$
+ public static final String XML_PI_CONTENT = "XML_PI_CONTENT"; //$NON-NLS-1$
+ public static final String XML_PI_OPEN = "XML_PI_OPEN"; //$NON-NLS-1$
+ public static final String XML_TAG_ATTRIBUTE_EQUALS = "XML_TAG_ATTRIBUTE_EQUALS"; //$NON-NLS-1$
+ public static final String XML_TAG_ATTRIBUTE_NAME = "XML_TAG_ATTRIBUTE_NAME"; //$NON-NLS-1$
+ public static final String XML_TAG_ATTRIBUTE_VALUE = "XML_TAG_ATTRIBUTE_VALUE"; //$NON-NLS-1$
+ public static final String XML_TAG_CLOSE = "XML_TAG_CLOSE"; //$NON-NLS-1$
+ public static final String XML_TAG_NAME = "XML_TAG_NAME"; //$NON-NLS-1$
+
+ public static final String XML_TAG_OPEN = "XML_TAG_OPEN"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/text/rules/StructuredTextPartitionerForXML.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/text/rules/StructuredTextPartitionerForXML.java
new file mode 100644
index 0000000000..471629675c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/text/rules/StructuredTextPartitionerForXML.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.core.text.rules;
+
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.sse.core.internal.parser.ForeignRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.IStructuredTextPartitioner;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.rules.StructuredTextPartitioner;
+import org.eclipse.wst.xml.core.internal.parser.regions.BlockTextRegion;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class StructuredTextPartitionerForXML extends StructuredTextPartitioner implements IStructuredTextPartitioner {
+ public final static String ST_DEFAULT_XML = "org.eclipse.wst.xml.DEFAULT_XML"; //$NON-NLS-1$
+ public final static String ST_XML_CDATA = "org.eclipse.wst.xml.XML_CDATA"; //$NON-NLS-1$
+ public final static String ST_XML_PI = "org.eclipse.wst.xml.XML_PI"; //$NON-NLS-1$
+ public final static String ST_XML_DECLARATION = "org.eclipse.wst.xml.XML_DECL"; //$NON-NLS-1$
+ public final static String ST_XML_COMMENT = "org.eclipse.wst.xml.XML_COMMENT"; //$NON-NLS-1$
+
+ /**
+ * Should match
+ * org.eclipse.wst.sse.core.dtd.partitioning.StructuredTextPartitionerForDTD.ST_DTD_SUBSET
+ */
+ public static final String ST_DTD_SUBSET = "org.eclipse.wst.xml.dtd.internal_subset"; //$NON-NLS-1$
+
+ private final static String[] configuredContentTypes = new String[]{ST_DEFAULT_XML, ST_XML_CDATA, ST_XML_PI, ST_XML_DECLARATION, ST_XML_COMMENT, ST_DTD_SUBSET};
+
+ /**
+ * Constructor for JSPDocumentPartioner.
+ */
+ public StructuredTextPartitionerForXML() {
+ super();
+ }
+
+ protected void setInternalPartition(int offset, int length, String type) {
+ super.setInternalPartition(offset, length, type);
+ }
+
+ protected void initLegalContentTypes() {
+ fSupportedTypes = configuredContentTypes;
+ }
+
+ /**
+ * @see com.ibm.sed.model.StructuredTextPartitioner#getPartitionType(com.ibm.sed.structuredDocument.ITextRegion)
+ */
+ public String getPartitionType(ITextRegion region, int offset) {
+ String result = null;
+ if (region.getType() == XMLRegionContext.XML_COMMENT_TEXT)
+ result = ST_XML_COMMENT;
+ else if (region.getType() == XMLRegionContext.XML_CDATA_TEXT)
+ result = ST_XML_CDATA;
+ else if (region.getType() == XMLRegionContext.XML_PI_OPEN)
+ result = ST_XML_PI;
+ else if (region.getType() == XMLRegionContext.XML_DOCTYPE_DECLARATION)
+ result = ST_XML_DECLARATION;
+ else if (region.getType() == XMLRegionContext.XML_DOCTYPE_INTERNAL_SUBSET)
+ result = ST_DTD_SUBSET;
+ else
+ result = super.getPartitionType(region, offset);
+ return result;
+ }
+
+ protected String getPartitionType(ForeignRegion region, int offset) {
+ // temp added just to dis-ambiguate call from subclass
+ return super.getPartitionType(region, offset);
+ }
+
+ /**
+ * @see com.ibm.sed.structuredDocument.partition.IStructuredTextPartitioner#getPartitionTypeBetween(com.ibm.sed.structuredDocument.ITextRegion,
+ * com.ibm.sed.structuredDocument.ITextRegion)
+ */
+ public String getPartitionTypeBetween(IStructuredDocumentRegion previousNode, ITextRegion previousStartTagNameRegion, IStructuredDocumentRegion nextNode, ITextRegion nextEndTagNameRegion) {
+ return super.getPartitionTypeBetween(previousNode, previousStartTagNameRegion, nextNode, nextEndTagNameRegion);
+ }
+
+ public String getDefault() {
+ return ST_DEFAULT_XML;
+ }
+
+ public IDocumentPartitioner newInstance() {
+ StructuredTextPartitionerForXML instance = new StructuredTextPartitionerForXML();
+ return instance;
+ }
+
+ /**
+ * @return
+ */
+ public static String[] getConfiguredContentTypes() {
+ return configuredContentTypes;
+ }
+
+ protected String getPartitionFromBlockedText(ITextRegion region, int offset, String result) {
+ // was moved to subclass for quick transition
+ String newResult = result;
+ // nsd_TODO: David and I need to discuss, design, and implement this
+ // for all block tags and comments
+ // and make sure is part of "extensible" design of block tags
+ if (region.getType() == XMLRegionContext.BLOCK_TEXT) {
+ // for code safety, we'll always check instanceof, but I think
+ // always true.
+ if (region instanceof BlockTextRegion) {
+ // super is used below so won't be ambiguous
+ newResult = getPartitionType((BlockTextRegion) region, offset);
+ } else if (region instanceof ForeignRegion) {
+ newResult = getPartitionType((ForeignRegion) region, offset);
+ } else {
+ newResult = getUnknown();
+ }
+ }
+ return newResult;
+ }
+
+ protected boolean doParserSpecificCheck(int offset, boolean partitionFound, IStructuredDocumentRegion sdRegion, IStructuredDocumentRegion previousStructuredDocumentRegion, ITextRegion next, ITextRegion previousStart) {
+ // this was moved down to subclass of StructuredTextPartioner
+ // for quick fix to transition problems. Heirarchy needs lots of
+ // cleanup.
+ if (previousStart != null && previousStart.getType() == XMLRegionContext.XML_TAG_OPEN && next.getType() == XMLRegionContext.XML_END_TAG_OPEN) {
+ ITextRegion previousName = previousStructuredDocumentRegion.getRegionAtCharacterOffset(previousStructuredDocumentRegion.getEndOffset(previousStart));
+ ITextRegion nextName = sdRegion.getRegionAtCharacterOffset(sdRegion.getEndOffset(next));
+ if (previousName != null && nextName != null && previousName.getType() == XMLRegionContext.XML_TAG_NAME && nextName.getType() == XMLRegionContext.XML_TAG_NAME) {
+ setInternalPartition(offset, 0, getPartitionTypeBetween(previousStructuredDocumentRegion, previousName, sdRegion, nextName));
+ partitionFound = true;
+ }
+ }
+ return partitionFound;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/COPYRIGHT.html b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/COPYRIGHT.html
new file mode 100644
index 0000000000..26049b750f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/COPYRIGHT.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+ "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>W3C IPR SOFTWARE NOTICE</title>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <h1>
+ W3C IPR SOFTWARE NOTICE
+ </h1>
+ <h3>
+ Copyright &copy; 2000 <loc href="http://www.w3.org/">World Wide Web
+ Consortium</loc>, (<loc href="http://www.lcs.mit.edu/">Massachusetts
+ Institute of Technology</loc>, <loc href="http://www.inria.fr/">Institut
+ National de Recherche en Informatique et en Automatique</loc>, <loc
+ href="http://www.keio.ac.jp/">Keio University</loc>). All Rights
+ Reserved.
+ </h3>
+ <p>
+ The DOM bindings are published under the W3C Software Copyright Notice
+ and License. The software license requires "Notice of any changes or
+ modifications to the W3C files, including the date changes were made."
+ Consequently, modified versions of the DOM bindings must document that
+ they do not conform to the W3C standard; in the case of the IDL binding,
+ the pragma prefix can no longer be 'w3c.org'; in the case of the Java
+ binding, the package names can no longer be in the 'org.w3c' package.
+ </p>
+ <p>
+ <b>Note:</b> The original version of the W3C Software Copyright Notice
+ and License could be found at <a
+ href='http://www.w3.org/Consortium/Legal/copyright-software-19980720'>http://www.w3.org/Consortium/Legal/copyright-software-19980720</a>
+ </p>
+ <h3>
+ Copyright &copy; 1994-2000 <a href="http://www.w3.org/">World Wide Web
+ Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts
+ Institute of Technology</a>, <a href="http://www.inria.fr/">Institut
+ National de Recherche en Informatique et en Automatique</a>, <a
+ href="http://www.keio.ac.jp/">Keio University</a>). All Rights
+ Reserved. http://www.w3.org/Consortium/Legal/
+ </h3>
+ <p>
+ This W3C work (including software, documents, or other related items) is
+ being provided by the copyright holders under the following license. By
+ obtaining, using and/or copying this work, you (the licensee) agree that
+ you have read, understood, and will comply with the following terms and
+ conditions:
+ </p>
+ <p>
+ Permission to use, copy, and modify this software and its documentation,
+ with or without modification,&nbsp; for any purpose and without fee or
+ royalty is hereby granted, provided that you include the following on ALL
+ copies of the software and documentation or portions thereof, including
+ modifications, that you make:
+ </p>
+ <ol>
+ <li>
+ The full text of this NOTICE in a location viewable to users of the
+ redistributed or derivative work.
+ </li>
+ <li>
+ Any pre-existing intellectual property disclaimers, notices, or terms
+ and conditions. If none exist, a short notice of the following form
+ (hypertext is preferred, text is permitted) should be used within the
+ body of any redistributed or derivative code: "Copyright &copy;
+ [$date-of-software] <a href="http://www.w3.org/">World Wide Web
+ Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts
+ Institute of Technology</a>, <a href="http://www.inria.fr/">Institut
+ National de Recherche en Informatique et en Automatique</a>, <a
+ href="http://www.keio.ac.jp/">Keio University</a>). All Rights
+ Reserved. http://www.w3.org/Consortium/Legal/"
+ </li>
+ <li>
+ Notice of any changes or modifications to the W3C files, including the
+ date changes were made. (We recommend you provide URIs to the location
+ from which the code is derived.)
+ </li>
+ </ol>
+ <p>
+ THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT
+ HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS
+ FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR
+ DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS.
+ </p>
+ <p>
+ COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR
+ DOCUMENTATION.
+ </p>
+ <p>
+ The name and trademarks of copyright holders may NOT be used in
+ advertising or publicity pertaining to the software without specific,
+ written prior permission. Title to copyright in this software and any
+ associated documentation will at all times remain with copyright
+ holders.
+ </p>
+ </body>
+</html>
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/DocumentRange.java b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/DocumentRange.java
new file mode 100644
index 0000000000..e40d080700
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/DocumentRange.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+package org.w3c.dom.ranges;
+
+/**
+ * <p>
+ * See also the <a
+ * href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document
+ * Object Model (DOM) Level 2 Traversal and Range Specification </a>.
+ *
+ * @since DOM Level 2
+ */
+public interface DocumentRange {
+ /**
+ * This interface can be obtained from the object implementing the
+ * <code>Document</code> interface using binding-specific casting
+ * methods.
+ *
+ * @return The initial state of the Range returned from this method is
+ * such that both of its boundary-points are positioned at the
+ * beginning of the corresponding Document, before any content.
+ * The Range returned can only be used to select content
+ * associated with this Document, or with DocumentFragments and
+ * Attrs for which this Document is the <code>ownerDocument</code>.
+ */
+ public Range createRange();
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/Range.java b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/Range.java
new file mode 100644
index 0000000000..63c366533f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/Range.java
@@ -0,0 +1,434 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+package org.w3c.dom.ranges;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Node;
+
+/**
+ * <p>
+ * See also the <a
+ * href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document
+ * Object Model (DOM) Level 2 Traversal and Range Specification </a>.
+ *
+ * @since DOM Level 2
+ */
+public interface Range {
+ /**
+ * Compare end boundary-point of <code>sourceRange</code> to end
+ * boundary-point of Range on which <code>compareBoundaryPoints</code>
+ * is invoked.
+ */
+ public static final short END_TO_END = 2;
+ /**
+ * Compare end boundary-point of <code>sourceRange</code> to start
+ * boundary-point of Range on which <code>compareBoundaryPoints</code>
+ * is invoked.
+ */
+ public static final short END_TO_START = 3;
+ /**
+ * Compare start boundary-point of <code>sourceRange</code> to end
+ * boundary-point of Range on which <code>compareBoundaryPoints</code>
+ * is invoked.
+ */
+ public static final short START_TO_END = 1;
+
+ // CompareHow
+ /**
+ * Compare start boundary-point of <code>sourceRange</code> to start
+ * boundary-point of Range on which <code>compareBoundaryPoints</code>
+ * is invoked.
+ */
+ public static final short START_TO_START = 0;
+
+ /**
+ * Duplicates the contents of a Range
+ *
+ * @return A DocumentFragment that contains content equivalent to this
+ * Range.
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if a DocumentType node
+ * would be extracted into the new DocumentFragment. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public DocumentFragment cloneContents() throws DOMException;
+
+ /**
+ * Produces a new Range whose boundary-points are equal to the
+ * boundary-points of the Range.
+ *
+ * @return The duplicated Range.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public Range cloneRange() throws DOMException;
+
+ /**
+ * Collapse a Range onto one of its boundary-points
+ *
+ * @param toStartIf
+ * TRUE, collapses the Range onto its start; if FALSE,
+ * collapses it onto its end.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void collapse(boolean toStart) throws DOMException;
+
+ /**
+ * Compare the boundary-points of two Ranges in a document.
+ *
+ * @param howA
+ * code representing the type of comparison, as defined above.
+ * @param sourceRangeThe
+ * <code>Range</code> on which this current
+ * <code>Range</code> is compared to.
+ * @return -1, 0 or 1 depending on whether the corresponding
+ * boundary-point of the Range is respectively before, equal to,
+ * or after the corresponding boundary-point of
+ * <code>sourceRange</code>.
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in
+ * the same Document or DocumentFragment. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public short compareBoundaryPoints(short how, Range sourceRange) throws DOMException;
+
+ /**
+ * Removes the contents of a Range from the containing document or
+ * document fragment without returning a reference to the removed content.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of
+ * the content of the Range is read-only or any of the
+ * nodes that contain any of the content of the Range are
+ * read-only. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void deleteContents() throws DOMException;
+
+ /**
+ * Called to indicate that the Range is no longer in use and that the
+ * implementation may relinquish any resources associated with this Range.
+ * Subsequent calls to any methods or attribute getters on this Range will
+ * result in a <code>DOMException</code> being thrown with an error code
+ * of <code>INVALID_STATE_ERR</code>.
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void detach() throws DOMException;
+
+ /**
+ * Moves the contents of a Range from the containing document or document
+ * fragment to a new DocumentFragment.
+ *
+ * @return A DocumentFragment containing the extracted contents.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of
+ * the content of the Range is read-only or any of the
+ * nodes which contain any of the content of the Range are
+ * read-only. <br>
+ * HIERARCHY_REQUEST_ERR: Raised if a DocumentType node
+ * would be extracted into the new DocumentFragment. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public DocumentFragment extractContents() throws DOMException;
+
+ /**
+ * TRUE if the Range is collapsed
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public boolean getCollapsed() throws DOMException;
+
+ /**
+ * The deepest common ancestor container of the Range's two
+ * boundary-points.
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public Node getCommonAncestorContainer() throws DOMException;
+
+ /**
+ * Node within which the Range ends
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public Node getEndContainer() throws DOMException;
+
+ /**
+ * Offset within the ending node of the Range.
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public int getEndOffset() throws DOMException;
+
+ /**
+ * Node within which the Range begins
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public Node getStartContainer() throws DOMException;
+
+ /**
+ * Offset within the starting node of the Range.
+ *
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public int getStartOffset() throws DOMException;
+
+ /**
+ * Inserts a node into the Document or DocumentFragment at the start of
+ * the Range. If the container is a Text node, this will be split at the
+ * start of the Range (as if the Text node's splitText method was
+ * performed at the insertion point) and the insertion will occur between
+ * the two resulting Text nodes. Adjacent Text nodes will not be
+ * automatically merged. If the node to be inserted is a DocumentFragment
+ * node, the children will be inserted rather than the DocumentFragment
+ * node itself.
+ *
+ * @param newNodeThe
+ * node to insert at the start of the Range
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor
+ * container of the start of the Range is read-only. <br>
+ * WRONG_DOCUMENT_ERR: Raised if <code>newNode</code> and
+ * the container of the start of the Range were not created
+ * from the same document. <br>
+ * HIERARCHY_REQUEST_ERR: Raised if the container of the
+ * start of the Range is of a type that does not allow
+ * children of the type of <code>newNode</code> or if
+ * <code>newNode</code> is an ancestor of the container.
+ * <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if <code>newNode</code>
+ * is an Attr, Entity, Notation, or Document node.
+ */
+ public void insertNode(Node newNode) throws DOMException, RangeException;
+
+ /**
+ * Select a node and its contents
+ *
+ * @param refNodeThe
+ * node to select.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if an ancestor of
+ * <code>refNode</code> is an Entity, Notation or
+ * DocumentType node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void selectNode(Node refNode) throws RangeException, DOMException;
+
+ /**
+ * Select the contents within a node
+ *
+ * @param refNodeNode
+ * to select from
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code>
+ * or an ancestor of <code>refNode</code> is an Entity,
+ * Notation or DocumentType node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void selectNodeContents(Node refNode) throws RangeException, DOMException;
+
+ /**
+ * Sets the attributes describing the end of a Range.
+ *
+ * @param refNodeThe
+ * <code>refNode</code> value. This parameter must be
+ * different from <code>null</code>.
+ * @param offsetThe
+ * <code>endOffset</code> value.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code>
+ * or an ancestor of <code>refNode</code> is an Entity,
+ * Notation, or DocumentType node.
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if <code>offset</code> is
+ * negative or greater than the number of child units in
+ * <code>refNode</code>. Child units are 16-bit units if
+ * <code>refNode</code> is a type of CharacterData node
+ * (e.g., a Text or Comment node) or a
+ * ProcessingInstruction node. Child units are Nodes in all
+ * other cases. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setEnd(Node refNode, int offset) throws RangeException, DOMException;
+
+ /**
+ * Sets the end of a Range to be after a node
+ *
+ * @param refNodeRange
+ * ends after <code>refNode</code>.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if the root container of
+ * <code>refNode</code> is not an Attr, Document or
+ * DocumentFragment node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setEndAfter(Node refNode) throws RangeException, DOMException;
+
+ /**
+ * Sets the end position to be before a node.
+ *
+ * @param refNodeRange
+ * ends before <code>refNode</code>
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if the root container of
+ * <code>refNode</code> is not an Attr, Document, or
+ * DocumentFragment node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setEndBefore(Node refNode) throws RangeException, DOMException;
+
+ /**
+ * Sets the attributes describing the start of the Range.
+ *
+ * @param refNodeThe
+ * <code>refNode</code> value. This parameter must be
+ * different from <code>null</code>.
+ * @param offsetThe
+ * <code>startOffset</code> value.
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if <code>refNode</code>
+ * or an ancestor of <code>refNode</code> is an Entity,
+ * Notation, or DocumentType node.
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if <code>offset</code> is
+ * negative or greater than the number of child units in
+ * <code>refNode</code>. Child units are 16-bit units if
+ * <code>refNode</code> is a type of CharacterData node
+ * (e.g., a Text or Comment node) or a
+ * ProcessingInstruction node. Child units are Nodes in all
+ * other cases. <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setStart(Node refNode, int offset) throws RangeException, DOMException;
+
+ /**
+ * Sets the start position to be after a node
+ *
+ * @param refNodeRange
+ * starts after <code>refNode</code>
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if the root container of
+ * <code>refNode</code> is not an Attr, Document, or
+ * DocumentFragment node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setStartAfter(Node refNode) throws RangeException, DOMException;
+
+ /**
+ * Sets the start position to be before a node
+ *
+ * @param refNodeRange
+ * starts before <code>refNode</code>
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if the root container of
+ * <code>refNode</code> is not an Attr, Document, or
+ * DocumentFragment node or if <code>refNode</code> is a
+ * Document, DocumentFragment, Attr, Entity, or Notation
+ * node.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public void setStartBefore(Node refNode) throws RangeException, DOMException;
+
+ /**
+ * Reparents the contents of the Range to the given node and inserts the
+ * node at the position of the start of the Range.
+ *
+ * @param newParentThe
+ * node to surround the contents with.
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor
+ * container of either boundary-point of the Range is
+ * read-only. <br>
+ * WRONG_DOCUMENT_ERR: Raised if <code> newParent</code>
+ * and the container of the start of the Range were not
+ * created from the same document. <br>
+ * HIERARCHY_REQUEST_ERR: Raised if the container of the
+ * start of the Range is of a type that does not allow
+ * children of the type of <code>newParent</code> or if
+ * <code>newParent</code> is an ancestor of the container
+ * or if <code>node</code> would end up with a child node
+ * of a type not allowed by the type of <code>node</code>.
+ * <br>
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ * @exception RangeException
+ * BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially
+ * selects a non-text node. <br>
+ * INVALID_NODE_TYPE_ERR: Raised if <code> node</code> is
+ * an Attr, Entity, DocumentType, Notation, Document, or
+ * DocumentFragment node.
+ */
+ public void surroundContents(Node newParent) throws DOMException, RangeException;
+
+ /**
+ * Returns the contents of a Range as a string. This string contains only
+ * the data characters, not any markup.
+ *
+ * @return The contents of the Range.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if <code>detach()</code> has
+ * already been invoked on this object.
+ */
+ public String toString() throws DOMException;
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/RangeException.java b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/RangeException.java
new file mode 100644
index 0000000000..54d29d7d78
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/RangeException.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+package org.w3c.dom.ranges;
+
+/**
+ * Range operations may throw a <code>RangeException</code> as specified in
+ * their method descriptions.
+ * <p>
+ * See also the <a
+ * href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document
+ * Object Model (DOM) Level 2 Traversal and Range Specification </a>.
+ *
+ * @since DOM Level 2
+ */
+public class RangeException extends RuntimeException {
+ // RangeExceptionCode
+ /**
+ * If the boundary-points of a Range do not meet specific requirements.
+ */
+ public static final short BAD_BOUNDARYPOINTS_ERR = 1;
+ /**
+ * If the container of an boundary-point of a Range is being set to either
+ * a node of an invalid type or a node with an ancestor of an invalid
+ * type.
+ */
+ public static final short INVALID_NODE_TYPE_ERR = 2;
+
+ public short code;
+
+ public RangeException(short code, String message) {
+ super(message);
+ this.code = code;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/package.html b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/package.html
new file mode 100644
index 0000000000..d8fbae65d9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/ranges/package.html
@@ -0,0 +1,3 @@
+<html>
+This package contains unmodified sources provided by http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113/java-binding.zip
+</html> \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/COPYRIGHT.html b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/COPYRIGHT.html
new file mode 100644
index 0000000000..26049b750f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/COPYRIGHT.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+ "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>W3C IPR SOFTWARE NOTICE</title>
+ </head>
+ <body bgcolor="#FFFFFF" text="#000000">
+ <h1>
+ W3C IPR SOFTWARE NOTICE
+ </h1>
+ <h3>
+ Copyright &copy; 2000 <loc href="http://www.w3.org/">World Wide Web
+ Consortium</loc>, (<loc href="http://www.lcs.mit.edu/">Massachusetts
+ Institute of Technology</loc>, <loc href="http://www.inria.fr/">Institut
+ National de Recherche en Informatique et en Automatique</loc>, <loc
+ href="http://www.keio.ac.jp/">Keio University</loc>). All Rights
+ Reserved.
+ </h3>
+ <p>
+ The DOM bindings are published under the W3C Software Copyright Notice
+ and License. The software license requires "Notice of any changes or
+ modifications to the W3C files, including the date changes were made."
+ Consequently, modified versions of the DOM bindings must document that
+ they do not conform to the W3C standard; in the case of the IDL binding,
+ the pragma prefix can no longer be 'w3c.org'; in the case of the Java
+ binding, the package names can no longer be in the 'org.w3c' package.
+ </p>
+ <p>
+ <b>Note:</b> The original version of the W3C Software Copyright Notice
+ and License could be found at <a
+ href='http://www.w3.org/Consortium/Legal/copyright-software-19980720'>http://www.w3.org/Consortium/Legal/copyright-software-19980720</a>
+ </p>
+ <h3>
+ Copyright &copy; 1994-2000 <a href="http://www.w3.org/">World Wide Web
+ Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts
+ Institute of Technology</a>, <a href="http://www.inria.fr/">Institut
+ National de Recherche en Informatique et en Automatique</a>, <a
+ href="http://www.keio.ac.jp/">Keio University</a>). All Rights
+ Reserved. http://www.w3.org/Consortium/Legal/
+ </h3>
+ <p>
+ This W3C work (including software, documents, or other related items) is
+ being provided by the copyright holders under the following license. By
+ obtaining, using and/or copying this work, you (the licensee) agree that
+ you have read, understood, and will comply with the following terms and
+ conditions:
+ </p>
+ <p>
+ Permission to use, copy, and modify this software and its documentation,
+ with or without modification,&nbsp; for any purpose and without fee or
+ royalty is hereby granted, provided that you include the following on ALL
+ copies of the software and documentation or portions thereof, including
+ modifications, that you make:
+ </p>
+ <ol>
+ <li>
+ The full text of this NOTICE in a location viewable to users of the
+ redistributed or derivative work.
+ </li>
+ <li>
+ Any pre-existing intellectual property disclaimers, notices, or terms
+ and conditions. If none exist, a short notice of the following form
+ (hypertext is preferred, text is permitted) should be used within the
+ body of any redistributed or derivative code: "Copyright &copy;
+ [$date-of-software] <a href="http://www.w3.org/">World Wide Web
+ Consortium</a>, (<a href="http://www.lcs.mit.edu/">Massachusetts
+ Institute of Technology</a>, <a href="http://www.inria.fr/">Institut
+ National de Recherche en Informatique et en Automatique</a>, <a
+ href="http://www.keio.ac.jp/">Keio University</a>). All Rights
+ Reserved. http://www.w3.org/Consortium/Legal/"
+ </li>
+ <li>
+ Notice of any changes or modifications to the W3C files, including the
+ date changes were made. (We recommend you provide URIs to the location
+ from which the code is derived.)
+ </li>
+ </ol>
+ <p>
+ THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT
+ HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS
+ FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR
+ DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS.
+ </p>
+ <p>
+ COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR
+ DOCUMENTATION.
+ </p>
+ <p>
+ The name and trademarks of copyright holders may NOT be used in
+ advertising or publicity pertaining to the software without specific,
+ written prior permission. Title to copyright in this software and any
+ associated documentation will at all times remain with copyright
+ holders.
+ </p>
+ </body>
+</html>
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/DocumentTraversal.java b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/DocumentTraversal.java
new file mode 100644
index 0000000000..dec93312af
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/DocumentTraversal.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+package org.w3c.dom.traversal;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+/**
+ * <code>DocumentTraversal</code> contains methods that create iterators and
+ * tree-walkers to traverse a node and its children in document order (depth
+ * first, pre-order traversal, which is equivalent to the order in which the
+ * start tags occur in the text representation of the document). In DOMs which
+ * support the Traversal feature, <code>DocumentTraversal</code> will be
+ * implemented by the same objects that implement the Document interface.
+ * <p>
+ * See also the <a
+ * href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document
+ * Object Model (DOM) Level 2 Traversal and Range Specification </a>.
+ *
+ * @since DOM Level 2
+ */
+public interface DocumentTraversal {
+ /**
+ * Create a new <code>NodeIterator</code> over the subtree rooted at the
+ * specified node.
+ *
+ * @param rootThe
+ * node which will be iterated together with its children. The
+ * iterator is initially positioned just before this node. The
+ * <code>whatToShow</code> flags and the filter, if any, are
+ * not considered when setting this position. The root must not
+ * be <code>null</code>.
+ * @param whatToShowThis
+ * flag specifies which node types may appear in the logical
+ * view of the tree presented by the iterator. See the
+ * description of <code>NodeFilter</code> for the set of
+ * possible <code>SHOW_</code> values.These flags can be
+ * combined using <code>OR</code>.
+ * @param filterThe
+ * <code>NodeFilter</code> to be used with this
+ * <code>TreeWalker</code>, or <code>null</code> to
+ * indicate no filter.
+ * @param entityReferenceExpansionThe
+ * value of this flag determines whether entity reference nodes
+ * are expanded.
+ * @return The newly created <code>NodeIterator</code>.
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if the specified
+ * <code>root</code> is <code>null</code>.
+ */
+ public NodeIterator createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException;
+
+ /**
+ * Create a new <code>TreeWalker</code> over the subtree rooted at the
+ * specified node.
+ *
+ * @param rootThe
+ * node which will serve as the <code>root</code> for the
+ * <code>TreeWalker</code>. The <code>whatToShow</code>
+ * flags and the <code>NodeFilter</code> are not considered
+ * when setting this value; any node type will be accepted as
+ * the <code>root</code>. The <code>currentNode</code> of
+ * the <code>TreeWalker</code> is initialized to this node,
+ * whether or not it is visible. The <code>root</code>
+ * functions as a stopping point for traversal methods that
+ * look upward in the document structure, such as
+ * <code>parentNode</code> and nextNode. The
+ * <code>root</code> must not be <code>null</code>.
+ * @param whatToShowThis
+ * flag specifies which node types may appear in the logical
+ * view of the tree presented by the tree-walker. See the
+ * description of <code>NodeFilter</code> for the set of
+ * possible SHOW_ values.These flags can be combined using
+ * <code>OR</code>.
+ * @param filterThe
+ * <code>NodeFilter</code> to be used with this
+ * <code>TreeWalker</code>, or <code>null</code> to
+ * indicate no filter.
+ * @param entityReferenceExpansionIf
+ * this flag is false, the contents of
+ * <code>EntityReference</code> nodes are not presented in
+ * the logical view.
+ * @return The newly created <code>TreeWalker</code>.
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if the specified
+ * <code>root</code> is <code>null</code>.
+ */
+ public TreeWalker createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException;
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/NodeFilter.java b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/NodeFilter.java
new file mode 100644
index 0000000000..48c746a1bd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/NodeFilter.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+package org.w3c.dom.traversal;
+
+import org.w3c.dom.Node;
+
+/**
+ * Filters are objects that know how to "filter out" nodes. If a
+ * <code>NodeIterator</code> or <code>TreeWalker</code> is given a
+ * <code>NodeFilter</code>, it applies the filter before it returns the
+ * next node. If the filter says to accept the node, the traversal logic
+ * returns it; otherwise, traversal looks for the next node and pretends that
+ * the node that was rejected was not there.
+ * <p>
+ * The DOM does not provide any filters. <code>NodeFilter</code> is just an
+ * interface that users can implement to provide their own filters.
+ * <p>
+ * <code>NodeFilters</code> do not need to know how to traverse from node to
+ * node, nor do they need to know anything about the data structure that is
+ * being traversed. This makes it very easy to write filters, since the only
+ * thing they have to know how to do is evaluate a single node. One filter may
+ * be used with a number of different kinds of traversals, encouraging code
+ * reuse.
+ * <p>
+ * See also the <a
+ * href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document
+ * Object Model (DOM) Level 2 Traversal and Range Specification </a>.
+ *
+ * @since DOM Level 2
+ */
+public interface NodeFilter {
+ // Constants returned by acceptNode
+ /**
+ * Accept the node. Navigation methods defined for
+ * <code>NodeIterator</code> or <code>TreeWalker</code> will return
+ * this node.
+ */
+ public static final short FILTER_ACCEPT = 1;
+ /**
+ * Reject the node. Navigation methods defined for
+ * <code>NodeIterator</code> or <code>TreeWalker</code> will not
+ * return this node. For <code>TreeWalker</code>, the children of this
+ * node will also be rejected. <code>NodeIterators</code> treat this as
+ * a synonym for <code>FILTER_SKIP</code>.
+ */
+ public static final short FILTER_REJECT = 2;
+ /**
+ * Skip this single node. Navigation methods defined for
+ * <code>NodeIterator</code> or <code>TreeWalker</code> will not
+ * return this node. For both <code>NodeIterator</code> and
+ * <code>TreeWalker</code>, the children of this node will still be
+ * considered.
+ */
+ public static final short FILTER_SKIP = 3;
+
+ // Constants for whatToShow
+ /**
+ * Show all <code>Nodes</code>.
+ */
+ public static final int SHOW_ALL = 0xFFFFFFFF;
+ /**
+ * Show <code>Element</code> nodes.
+ */
+ public static final int SHOW_ELEMENT = 0x00000001;
+ /**
+ * Show <code>Attr</code> nodes. This is meaningful only when creating
+ * an iterator or tree-walker with an attribute node as its
+ * <code>root</code>; in this case, it means that the attribute node
+ * will appear in the first position of the iteration or traversal. Since
+ * attributes are never children of other nodes, they do not appear when
+ * traversing over the document tree.
+ */
+ public static final int SHOW_ATTRIBUTE = 0x00000002;
+ /**
+ * Show <code>Text</code> nodes.
+ */
+ public static final int SHOW_TEXT = 0x00000004;
+ /**
+ * Show <code>CDATASection</code> nodes.
+ */
+ public static final int SHOW_CDATA_SECTION = 0x00000008;
+ /**
+ * Show <code>EntityReference</code> nodes.
+ */
+ public static final int SHOW_ENTITY_REFERENCE = 0x00000010;
+ /**
+ * Show <code>Entity</code> nodes. This is meaningful only when creating
+ * an iterator or tree-walker with an <code> Entity</code> node as its
+ * <code>root</code>; in this case, it means that the
+ * <code>Entity</code> node will appear in the first position of the
+ * traversal. Since entities are not part of the document tree, they do
+ * not appear when traversing over the document tree.
+ */
+ public static final int SHOW_ENTITY = 0x00000020;
+ /**
+ * Show <code>ProcessingInstruction</code> nodes.
+ */
+ public static final int SHOW_PROCESSING_INSTRUCTION = 0x00000040;
+ /**
+ * Show <code>Comment</code> nodes.
+ */
+ public static final int SHOW_COMMENT = 0x00000080;
+ /**
+ * Show <code>Document</code> nodes.
+ */
+ public static final int SHOW_DOCUMENT = 0x00000100;
+ /**
+ * Show <code>DocumentType</code> nodes.
+ */
+ public static final int SHOW_DOCUMENT_TYPE = 0x00000200;
+ /**
+ * Show <code>DocumentFragment</code> nodes.
+ */
+ public static final int SHOW_DOCUMENT_FRAGMENT = 0x00000400;
+ /**
+ * Show <code>Notation</code> nodes. This is meaningful only when
+ * creating an iterator or tree-walker with a <code>Notation</code> node
+ * as its <code>root</code>; in this case, it means that the
+ * <code>Notation</code> node will appear in the first position of the
+ * traversal. Since notations are not part of the document tree, they do
+ * not appear when traversing over the document tree.
+ */
+ public static final int SHOW_NOTATION = 0x00000800;
+
+ /**
+ * Test whether a specified node is visible in the logical view of a
+ * <code>TreeWalker</code> or <code>NodeIterator</code>. This
+ * function will be called by the implementation of
+ * <code>TreeWalker</code> and <code>NodeIterator</code>; it is not
+ * normally called directly from user code. (Though you could do so if you
+ * wanted to use the same filter to guide your own application logic.)
+ *
+ * @param nThe
+ * node to check to see if it passes the filter or not.
+ * @return a constant to determine whether the node is accepted, rejected,
+ * or skipped, as defined above.
+ */
+ public short acceptNode(Node n);
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/NodeIterator.java b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/NodeIterator.java
new file mode 100644
index 0000000000..b34a39c8e2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/NodeIterator.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+package org.w3c.dom.traversal;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+/**
+ * <code>Iterators</code> are used to step through a set of nodes, e.g. the
+ * set of nodes in a <code>NodeList</code>, the document subtree governed
+ * by a particular <code>Node</code>, the results of a query, or any other
+ * set of nodes. The set of nodes to be iterated is determined by the
+ * implementation of the <code>NodeIterator</code>. DOM Level 2 specifies a
+ * single <code>NodeIterator</code> implementation for document-order
+ * traversal of a document subtree. Instances of these iterators are created
+ * by calling <code>DocumentTraversal</code>
+ * <code>.createNodeIterator()</code>.
+ * <p>
+ * See also the <a
+ * href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document
+ * Object Model (DOM) Level 2 Traversal and Range Specification </a>.
+ *
+ * @since DOM Level 2
+ */
+public interface NodeIterator {
+ /**
+ * The root node of the <code>NodeIterator</code>, as specified when it
+ * was created.
+ */
+ public Node getRoot();
+
+ /**
+ * This attribute determines which node types are presented via the
+ * iterator. The available set of constants is defined in the
+ * <code>NodeFilter</code> interface. Nodes not accepted by
+ * <code>whatToShow</code> will be skipped, but their children may still
+ * be considered. Note that this skip takes precedence over the filter, if
+ * any.
+ */
+ public int getWhatToShow();
+
+ /**
+ * The <code>NodeFilter</code> used to screen nodes.
+ */
+ public NodeFilter getFilter();
+
+ /**
+ * The value of this flag determines whether the children of entity
+ * reference nodes are visible to the iterator. If false, they and their
+ * descendants will be rejected. Note that this rejection takes precedence
+ * over <code>whatToShow</code> and the filter. Also note that this is
+ * currently the only situation where <code>NodeIterators</code> may
+ * reject a complete subtree rather than skipping individual nodes. <br>
+ * <br>
+ * To produce a view of the document that has entity references expanded
+ * and does not expose the entity reference node itself, use the
+ * <code>whatToShow</code> flags to hide the entity reference node and
+ * set <code>expandEntityReferences</code> to true when creating the
+ * iterator. To produce a view of the document that has entity reference
+ * nodes but no entity expansion, use the <code>whatToShow</code> flags
+ * to show the entity reference node and set
+ * <code>expandEntityReferences</code> to false.
+ */
+ public boolean getExpandEntityReferences();
+
+ /**
+ * Returns the next node in the set and advances the position of the
+ * iterator in the set. After a <code>NodeIterator</code> is created,
+ * the first call to <code>nextNode()</code> returns the first node in
+ * the set.
+ *
+ * @return The next <code>Node</code> in the set being iterated over, or
+ * <code>null</code> if there are no more members in that set.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if this method is called after
+ * the <code>detach</code> method was invoked.
+ */
+ public Node nextNode() throws DOMException;
+
+ /**
+ * Returns the previous node in the set and moves the position of the
+ * <code>NodeIterator</code> backwards in the set.
+ *
+ * @return The previous <code>Node</code> in the set being iterated
+ * over, or <code>null</code> if there are no more members in
+ * that set.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if this method is called after
+ * the <code>detach</code> method was invoked.
+ */
+ public Node previousNode() throws DOMException;
+
+ /**
+ * Detaches the <code>NodeIterator</code> from the set which it iterated
+ * over, releasing any computational resources and placing the iterator in
+ * the INVALID state. After <code>detach</code> has been invoked, calls
+ * to <code>nextNode</code> or <code>previousNode</code> will raise
+ * the exception INVALID_STATE_ERR.
+ */
+ public void detach();
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/TreeWalker.java b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/TreeWalker.java
new file mode 100644
index 0000000000..3747d603be
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/TreeWalker.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+package org.w3c.dom.traversal;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Node;
+
+/**
+ * <code>TreeWalker</code> objects are used to navigate a document tree or
+ * subtree using the view of the document defined by their
+ * <code>whatToShow</code> flags and filter (if any). Any function which
+ * performs navigation using a <code>TreeWalker</code> will automatically
+ * support any view defined by a <code>TreeWalker</code>.
+ * <p>
+ * Omitting nodes from the logical view of a subtree can result in a structure
+ * that is substantially different from the same subtree in the complete,
+ * unfiltered document. Nodes that are siblings in the <code>TreeWalker</code>
+ * view may be children of different, widely separated nodes in the original
+ * view. For instance, consider a <code>NodeFilter</code> that skips all
+ * nodes except for Text nodes and the root node of a document. In the logical
+ * view that results, all text nodes will be siblings and appear as direct
+ * children of the root node, no matter how deeply nested the structure of the
+ * original document.
+ * <p>
+ * See also the <a
+ * href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document
+ * Object Model (DOM) Level 2 Traversal and Range Specification </a>.
+ *
+ * @since DOM Level 2
+ */
+public interface TreeWalker {
+ /**
+ * The <code>root</code> node of the <code>TreeWalker</code>, as
+ * specified when it was created.
+ */
+ public Node getRoot();
+
+ /**
+ * This attribute determines which node types are presented via the
+ * <code>TreeWalker</code>. The available set of constants is defined
+ * in the <code>NodeFilter</code> interface. Nodes not accepted by
+ * <code>whatToShow</code> will be skipped, but their children may still
+ * be considered. Note that this skip takes precedence over the filter, if
+ * any.
+ */
+ public int getWhatToShow();
+
+ /**
+ * The filter used to screen nodes.
+ */
+ public NodeFilter getFilter();
+
+ /**
+ * The value of this flag determines whether the children of entity
+ * reference nodes are visible to the <code>TreeWalker</code>. If
+ * false, they and their descendants will be rejected. Note that this
+ * rejection takes precedence over <code>whatToShow</code> and the
+ * filter, if any. <br>
+ * To produce a view of the document that has entity references expanded
+ * and does not expose the entity reference node itself, use the
+ * <code>whatToShow</code> flags to hide the entity reference node and
+ * set <code>expandEntityReferences</code> to true when creating the
+ * <code>TreeWalker</code>. To produce a view of the document that has
+ * entity reference nodes but no entity expansion, use the
+ * <code>whatToShow</code> flags to show the entity reference node and
+ * set <code>expandEntityReferences</code> to false.
+ */
+ public boolean getExpandEntityReferences();
+
+ /**
+ * The node at which the <code>TreeWalker</code> is currently
+ * positioned. <br>
+ * Alterations to the DOM tree may cause the current node to no longer be
+ * accepted by the <code>TreeWalker</code>'s associated filter.
+ * <code>currentNode</code> may also be explicitly set to any node,
+ * whether or not it is within the subtree specified by the
+ * <code>root</code> node or would be accepted by the filter and
+ * <code>whatToShow</code> flags. Further traversal occurs relative to
+ * <code>currentNode</code> even if it is not part of the current view,
+ * by applying the filters in the requested direction; if no traversal is
+ * possible, <code>currentNode</code> is not changed.
+ *
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if an attempt is made to set
+ * <code>currentNode</code> to <code>null</code>.
+ */
+ public Node getCurrentNode();
+
+ public void setCurrentNode(Node currentNode) throws DOMException;
+
+ /**
+ * Moves to and returns the closest visible ancestor node of the current
+ * node. If the search for <code>parentNode</code> attempts to step
+ * upward from the <code>TreeWalker</code>'s<code>root</code> node,
+ * or if it fails to find a visible ancestor node, this method retains the
+ * current position and returns <code>null</code>.
+ *
+ * @return The new parent node, or <code>null</code> if the current node
+ * has no parent in the <code>TreeWalker</code>'s logical view.
+ */
+ public Node parentNode();
+
+ /**
+ * Moves the <code>TreeWalker</code> to the first visible child of the
+ * current node, and returns the new node. If the current node has no
+ * visible children, returns <code>null</code>, and retains the current
+ * node.
+ *
+ * @return The new node, or <code>null</code> if the current node has no
+ * visible children in the <code>TreeWalker</code>'s logical
+ * view.
+ */
+ public Node firstChild();
+
+ /**
+ * Moves the <code>TreeWalker</code> to the last visible child of the
+ * current node, and returns the new node. If the current node has no
+ * visible children, returns <code>null</code>, and retains the current
+ * node.
+ *
+ * @return The new node, or <code>null</code> if the current node has no
+ * children in the <code>TreeWalker</code>'s logical view.
+ */
+ public Node lastChild();
+
+ /**
+ * Moves the <code>TreeWalker</code> to the previous sibling of the
+ * current node, and returns the new node. If the current node has no
+ * visible previous sibling, returns <code>null</code>, and retains the
+ * current node.
+ *
+ * @return The new node, or <code>null</code> if the current node has no
+ * previous sibling. in the <code>TreeWalker</code>'s logical
+ * view.
+ */
+ public Node previousSibling();
+
+ /**
+ * Moves the <code>TreeWalker</code> to the next sibling of the current
+ * node, and returns the new node. If the current node has no visible next
+ * sibling, returns <code>null</code>, and retains the current node.
+ *
+ * @return The new node, or <code>null</code> if the current node has no
+ * next sibling. in the <code>TreeWalker</code>'s logical view.
+ */
+ public Node nextSibling();
+
+ /**
+ * Moves the <code>TreeWalker</code> to the previous visible node in
+ * document order relative to the current node, and returns the new node.
+ * If the current node has no previous node, or if the search for
+ * <code>previousNode</code> attempts to step upward from the
+ * <code>TreeWalker</code>'s<code>root</code> node, returns
+ * <code>null</code>, and retains the current node.
+ *
+ * @return The new node, or <code>null</code> if the current node has no
+ * previous node in the <code>TreeWalker</code>'s logical view.
+ */
+ public Node previousNode();
+
+ /**
+ * Moves the <code>TreeWalker</code> to the next visible node in
+ * document order relative to the current node, and returns the new node.
+ * If the current node has no next node, or if the search for nextNode
+ * attempts to step upward from the <code>TreeWalker</code>'s
+ * <code>root</code> node, returns <code>null</code>, and retains the
+ * current node.
+ *
+ * @return The new node, or <code>null</code> if the current node has no
+ * next node in the <code>TreeWalker</code>'s logical view.
+ */
+ public Node nextNode();
+
+}
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/package.html b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/package.html
new file mode 100644
index 0000000000..d8fbae65d9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.core/src/org/w3c/dom/traversal/package.html
@@ -0,0 +1,3 @@
+<html>
+This package contains unmodified sources provided by http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113/java-binding.zip
+</html> \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/.classpath b/bundles/org.eclipse.wst.xml.ui/.classpath
new file mode 100644
index 0000000000..c5a45758cf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="src" path="src-multipage"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.wst.xml.ui/.compatibility b/bundles/org.eclipse.wst.xml.ui/.compatibility
new file mode 100644
index 0000000000..2e4834a775
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.compatibility
@@ -0,0 +1,2 @@
+#Wed Mar 24 13:53:52 EST 2004
+.project=6269
diff --git a/bundles/org.eclipse.wst.xml.ui/.cvsignore b/bundles/org.eclipse.wst.xml.ui/.cvsignore
new file mode 100644
index 0000000000..c244b73b57
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/.cvsignore
@@ -0,0 +1,7 @@
+bin
+temp.folder
+xmleditor.jar
+.project
+org.eclipse.wst.xml.ui_6.0.0.jar
+dev.properties
+build.xml
diff --git a/bundles/org.eclipse.wst.xml.ui/build.properties b/bundles/org.eclipse.wst.xml.ui/build.properties
new file mode 100644
index 0000000000..9372072cea
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/build.properties
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+bin.includes = plugin.xml,\
+ *.jar,\
+ xml.jar,\
+ icons/,\
+ plugin.properties,\
+ templates/
+source.xmleditor.jar = src/
+src.includes = plugin.xml,\
+ plugin.properties,\
+ icons/,\
+ build.xml,\
+ templates/
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse.gif
new file mode 100644
index 0000000000..ce74721ea2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse_all.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse_all.gif
new file mode 100644
index 0000000000..7dc0de5130
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/collapse_all.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainoff.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainoff.gif
new file mode 100644
index 0000000000..4bdceb84e9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainoff.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainon.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainon.gif
new file mode 100644
index 0000000000..e823d572a3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/constrainon.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand.gif
new file mode 100644
index 0000000000..bc37b7a4e5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand_all.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand_all.gif
new file mode 100644
index 0000000000..492c14f6e1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/expand_all.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/new_xml.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/new_xml.gif
new file mode 100644
index 0000000000..e1cfdf7eb3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/new_xml.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/rldgrmr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/rldgrmr.gif
new file mode 100644
index 0000000000..49325dd8ea
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/rldgrmr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/validate.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/validate.gif
new file mode 100644
index 0000000000..561d1463ef
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/dtool16/validate.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse.gif
new file mode 100644
index 0000000000..b75bc19602
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse_all.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse_all.gif
new file mode 100644
index 0000000000..a2d80a9044
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/collapse_all.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainoff.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainoff.gif
new file mode 100644
index 0000000000..c1ab04c81c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainoff.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainon.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainon.gif
new file mode 100644
index 0000000000..082f9c0ae8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/constrainon.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand.gif
new file mode 100644
index 0000000000..b2f45306c9
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand_all.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand_all.gif
new file mode 100644
index 0000000000..0205b29176
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/expand_all.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/new_xml.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/new_xml.gif
new file mode 100644
index 0000000000..9dfb62d35b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/new_xml.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/rldgrmr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/rldgrmr.gif
new file mode 100644
index 0000000000..049cac696c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/rldgrmr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/validate.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/validate.gif
new file mode 100644
index 0000000000..2b347ac458
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/etool16/validate.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/XSDFile.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/XSDFile.gif
new file mode 100644
index 0000000000..cc0eeb7196
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/XSDFile.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/add_correction.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/add_correction.gif
new file mode 100644
index 0000000000..252d7ebcb8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/add_correction.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/att_req_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/att_req_obj.gif
new file mode 100644
index 0000000000..a8c66d5016
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/att_req_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/attribute_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/attribute_obj.gif
new file mode 100644
index 0000000000..79d49d037b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/attribute_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/cdatasection.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/cdatasection.gif
new file mode 100644
index 0000000000..6b0872c909
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/cdatasection.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/choice.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/choice.gif
new file mode 100644
index 0000000000..d13ba2e5b0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/choice.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/comment_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/comment_obj.gif
new file mode 100644
index 0000000000..28c2ccb1e7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/comment_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/correction_change.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/correction_change.gif
new file mode 100644
index 0000000000..af83c528dd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/correction_change.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/doctype.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/doctype.gif
new file mode 100644
index 0000000000..3300f82862
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/doctype.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/dtdfile.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/dtdfile.gif
new file mode 100644
index 0000000000..3c0acadd2d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/dtdfile.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/element_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/element_obj.gif
new file mode 100644
index 0000000000..3567815907
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/element_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity.gif
new file mode 100644
index 0000000000..61fd3d4caa
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity_reference.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity_reference.gif
new file mode 100644
index 0000000000..3af9149125
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/entity_reference.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/enum.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/enum.gif
new file mode 100644
index 0000000000..5c0a48115b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/enum.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/error-overlay.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/error-overlay.gif
new file mode 100644
index 0000000000..119dcccd5a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/error-overlay.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/localvariable_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/localvariable_obj.gif
new file mode 100644
index 0000000000..3244b26ef4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/localvariable_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/notation.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/notation.gif
new file mode 100644
index 0000000000..57ad089a69
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/notation.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/occurone_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/occurone_obj.gif
new file mode 100644
index 0000000000..7bb65c9d51
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/occurone_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/proinst_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/proinst_obj.gif
new file mode 100644
index 0000000000..74436d8d3c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/proinst_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-generic.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-generic.gif
new file mode 100644
index 0000000000..65f516e80a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-generic.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-macro.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-macro.gif
new file mode 100644
index 0000000000..5d1f81b6d4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/tag-macro.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/text.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/text.gif
new file mode 100644
index 0000000000..efa7a38014
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/text.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/txtext.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/txtext.gif
new file mode 100644
index 0000000000..b226e41c52
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/txtext.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/warning_obj.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/warning_obj.gif
new file mode 100644
index 0000000000..1e5f5eb367
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/obj16/warning_obj.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/error_ovr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/error_ovr.gif
new file mode 100644
index 0000000000..119dcccd5a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/error_ovr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/stale_error_ovr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/stale_error_ovr.gif
new file mode 100644
index 0000000000..5b0471b5eb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/stale_error_ovr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/warn_ovr.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/warn_ovr.gif
new file mode 100644
index 0000000000..c350704fa1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/ovr16/warn_ovr.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/full/view16/attibute.gif b/bundles/org.eclipse.wst.xml.ui/icons/full/view16/attibute.gif
new file mode 100644
index 0000000000..79d49d037b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/full/view16/attibute.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/sourceEditor.gif b/bundles/org.eclipse.wst.xml.ui/icons/sourceEditor.gif
new file mode 100644
index 0000000000..75ebdb8586
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/sourceEditor.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/icons/xmldoc.gif b/bundles/org.eclipse.wst.xml.ui/icons/xmldoc.gif
new file mode 100644
index 0000000000..14eb1be095
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/icons/xmldoc.gif
Binary files differ
diff --git a/bundles/org.eclipse.wst.xml.ui/plugin.properties b/bundles/org.eclipse.wst.xml.ui/plugin.properties
new file mode 100644
index 0000000000..1ad158bcac
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/plugin.properties
@@ -0,0 +1,40 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+SSE_XML_Source_Editor.name=SSE XML Source Editor
+SSE_XML_Source_Editor_NL_Support.name=SSE XML Source Editor NL Support
+XML_Source_Page_Editor.name=XML Source Page Editor
+XML_Files.name=XML Files
+XML_Source.name=XML Source
+XML_Templates.name=XML Templates
+XML_Styles.name=XML Styles
+XML_Annotations.name=XML Annotations
+###############################################################################
+SSE_XML_Editor.name=SSE XML Editor
+SSE_XML_Editor_NL_Support.name=SSE XML Editor NL Support
+XML_Editor.name=XML Editor
+###############################################################################
+XMLTableTreeViewer.0=Design
+XMLMultiPageEditorPart.0=Source
+XMLTreeExtension.0=Structure
+XMLTreeExtension.1=Value
+XMLTreeExtension.3=The document is empty.
+XMLTreeExtension.4=Right mouse click here to insert content.
+XMLTableTreeActionBarContributor.0=&XML
+XMLTableTreeActionBarContributor.1=&Expand All
+XMLTableTreeActionBarContributor.2=&Collapse All
+XMLTableTreeActionBarContributor.3=Turn Grammar Constraints Off
+XMLTableTreeActionBarContributor.4=&Turn Grammar Constraints Off
+XMLTableTreeActionBarContributor.5=Turn Grammar Constraints On
+XMLTableTreeActionBarContributor.6=&Turn Grammar Constraints On
+XMLTableTreeActionBarContributor.7=Reload Dependencies
+XMLTableTreeActionBarContributor.8=&Reload Dependencies \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/plugin.xml b/bundles/org.eclipse.wst.xml.ui/plugin.xml
new file mode 100644
index 0000000000..38f7fe765c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/plugin.xml
@@ -0,0 +1,248 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+ id="org.eclipse.wst.xml.ui"
+ name="%SSE_XML_Source_Editor.name"
+ version="1.0.0"
+ provider-name="IBM"
+ class="org.eclipse.wst.xml.ui.XMLEditorPlugin">
+
+ <runtime>
+ <library name="xmleditor.jar">
+ <export name="*"/>
+ </library>
+ </runtime>
+ <requires>
+ <import plugin="org.eclipse.core.runtime.compatibility"/>
+ <import plugin="org.eclipse.ui.ide"/>
+ <import plugin="org.eclipse.ui.views"/>
+ <import plugin="org.eclipse.jface.text"/>
+ <import plugin="org.eclipse.ui.workbench.texteditor"/>
+ <import plugin="org.eclipse.ui.editors"/>
+ <import plugin="org.eclipse.wst.sse.ui"/>
+ <import plugin="org.eclipse.wst.dtd.ui"/>
+ <import plugin="org.eclipse.wst.sse.core"/>
+ <import plugin="org.eclipse.ui"/>
+ <import plugin="org.eclipse.wst.common.contentmodel"/>
+ <import plugin="org.eclipse.core.resources"/>
+ <import plugin="org.eclipse.core.runtime"/>
+ <import plugin="org.eclipse.wst.common.encoding"/>
+ <import plugin="org.eclipse.wst.xml.uriresolver.ui"/>
+ <import plugin="org.eclipse.wst.uriresolver"/>
+ <import plugin="org.eclipse.wst.xml.uriresolver"/>
+ <import plugin="org.eclipse.wst.xml.core"/>
+ <import plugin="org.eclipse.wst.ui"/>
+ </requires>
+
+
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ name="%XML_Source_Page_Editor.name"
+ icon="icons/sourceEditor.gif"
+ extensions="tld, nst, xmi, dadx, wsdl"
+ contributorClass="org.eclipse.wst.xml.ui.actions.ActionContributorXML"
+ class="org.eclipse.wst.xml.ui.StructuredTextEditorXML"
+ symbolicFontName="org.eclipse.wst.sse.ui.textfont"
+ id="org.eclipse.wst.xml.ui.StructuredTextEditorXML2">
+ </editor>
+ <!-- Separate editor definition for xml source page to mark it as the default editor -->
+ <editor
+ name="%XML_Source_Page_Editor.name"
+ icon="icons/sourceEditor.gif"
+ extensions="xml"
+ default="true"
+ contributorClass="org.eclipse.wst.xml.ui.actions.ActionContributorXML"
+ class="org.eclipse.wst.xml.ui.StructuredTextEditorXML"
+ symbolicFontName="org.eclipse.wst.sse.ui.textfont"
+ id="org.eclipse.wst.xml.ui.StructuredTextEditorXML">
+ </editor>
+ </extension>
+ <extension
+ point="org.eclipse.wst.sse.ui.extendedconfiguration">
+ <textviewerconfiguration
+ class="org.eclipse.wst.xml.ui.StructuredTextViewerConfigurationXML"
+ target="org.eclipse.wst.xml.core.xmlsource">
+ </textviewerconfiguration>
+ <contentoutlineconfiguration
+ class="org.eclipse.wst.xml.ui.views.contentoutline.XMLContentOutlineConfiguration"
+ target="org.eclipse.wst.xml.core.xmlsource">
+ </contentoutlineconfiguration>
+ <propertysheetconfiguration
+ class="org.eclipse.wst.xml.ui.views.properties.XMLPropertySheetConfiguration"
+ target="org.eclipse.wst.xml.core.xmlsource">
+ </propertysheetconfiguration>
+ <spellchecktarget
+ class="org.eclipse.wst.xml.ui.XMLSpellCheckTarget"
+ target="org.eclipse.wst.xml.core.xmlsource">
+ </spellchecktarget>
+ <sourceeditingtexttools
+ class="org.eclipse.wst.xml.ui.extensions.XMLSourceEditingTextTools"
+ target="org.eclipse.wst.xml.core.xmlsource">
+ </sourceeditingtexttools>
+ <characterpairmatcher
+ class="org.eclipse.wst.xml.ui.text.XMLDocumentRegionEdgeMatcher"
+ target="org.eclipse.wst.xml.core.xmlsource">
+ </characterpairmatcher>
+ <preferencepages
+ preferenceids="org.eclipse.wst.sse.ui.preferences/org.eclipse.wst.sse.ui.preferences.xml"
+ target="org.eclipse.wst.xml.core.xmlsource">
+ </preferencepages>
+ </extension>
+ <extension
+ point="org.eclipse.core.filebuffers.annotationModelCreation">
+ <factory
+ contentTypeId="org.eclipse.wst.xml.core.xmlsource"
+ class="org.eclipse.wst.sse.ui.StructuredResourceMarkerAnnotationModelFactory"/>
+ </extension>
+ <extension
+ point="org.eclipse.wst.sse.ui.adapterFactoryDescription">
+ <adapterFactoryDescription
+ class="org.eclipse.wst.xml.ui.registry.AdapterFactoryProviderForXML">
+ <contentType id="org.eclipse.wst.xml.core.xmlsource"/>
+ </adapterFactoryDescription>
+ </extension>
+ <extension
+ point="org.eclipse.wst.sse.ui.embeddedAdapterFactoryProvider">
+ <embeddedAdapterFactoryProvider
+ class="org.eclipse.wst.xml.ui.registry.AdapterFactoryProviderForEmbeddedXML">
+ </embeddedAdapterFactoryProvider>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+<!-- XML PREFERENCE PAGES -->
+ <page
+ name="%XML_Files.name"
+ category="org.eclipse.wst.sse.ui.preferences"
+ class="org.eclipse.wst.xml.ui.preferences.XMLFilesPreferencePage"
+ id="org.eclipse.wst.sse.ui.preferences.xml">
+ </page>
+ <page
+ name="%XML_Source.name"
+ category="org.eclipse.wst.sse.ui.preferences.xml"
+ class="org.eclipse.wst.xml.ui.preferences.XMLSourcePreferencePage"
+ id="org.eclipse.wst.sse.ui.preferences.xml.source">
+ </page>
+ <page
+ name="%XML_Templates.name"
+ category="org.eclipse.wst.sse.ui.preferences.xml"
+ class="org.eclipse.wst.xml.ui.preferences.XMLTemplatePreferencePage"
+ id="org.eclipse.wst.sse.ui.preferences.xml.templates">
+ </page>
+ <page
+ name="%XML_Styles.name"
+ category="org.eclipse.wst.sse.ui.preferences.xml"
+ class="org.eclipse.wst.xml.ui.preferences.XMLColorPage"
+ id="org.eclipse.wst.sse.ui.preferences.xml.colors">
+ </page>
+ </extension>
+<!-- Editor actionsets -->
+ <extension
+ point="org.eclipse.ui.actionSetPartAssociations">
+ <actionSetPartAssociation
+ targetID="org.eclipse.ui.edit.text.actionSet.annotationNavigation">
+ <part
+ id="org.eclipse.wst.xml.ui.StructuredTextEditorXML">
+ </part>
+ <part
+ id="org.eclipse.wst.xml.ui.StructuredTextEditorXML2">
+ </part>
+ </actionSetPartAssociation>
+ <actionSetPartAssociation
+ targetID="org.eclipse.ui.NavigateActionSet">
+ <part
+ id="org.eclipse.wst.xml.ui.StructuredTextEditorXML">
+ </part>
+ <part
+ id="org.eclipse.wst.xml.ui.StructuredTextEditorXML2">
+ </part>
+ </actionSetPartAssociation>
+ </extension>
+ <extension
+ point="org.eclipse.ui.perspectiveExtensions">
+<!-- added to enable "Navigator > Show In" for various views... -->
+ <perspectiveExtension
+ targetID="com.ibm.etools.xml.tools.XMLPerspective">
+ <showInPart
+ id="org.eclipse.ui.views.ResourceNavigator">
+ </showInPart>
+<!-- add the "navigate" action set (Navigate > Open Resource...) -->
+ <actionSet
+ id="org.eclipse.ui.NavigateActionSet">
+ </actionSet>
+ </perspectiveExtension>
+ </extension>
+<!-- add a default open on action for xml content type -->
+ <extension
+ point="org.eclipse.wst.sse.ui.openon">
+ <openon
+ class="org.eclipse.wst.xml.ui.openon.DefaultOpenOnXML"
+ id="org.eclipse.wst.xml.ui.openon.DefaultOpenOnXML">
+ <contenttypeidentifier
+ id="org.eclipse.wst.xml.core.xmlsource">
+ </contenttypeidentifier>
+ </openon>
+ </extension>
+<!-- Templates -->
+ <extension
+ point="org.eclipse.ui.editors.templates">
+ <contextType
+ name="All XML context type"
+ class="org.eclipse.wst.xml.ui.templates.TemplateContextTypeXML"
+ id="xml_all">
+ </contextType>
+ <contextType
+ name="XML Tag context type"
+ class="org.eclipse.wst.xml.ui.templates.TemplateContextTypeXMLTag"
+ id="xml_tag">
+ </contextType>
+ <contextType
+ name="XML Attribute context type"
+ class="org.eclipse.wst.xml.ui.templates.TemplateContextTypeXMLAttribute"
+ id="xml_attribute">
+ </contextType>
+ <contextType
+ name="XML Attribute value context type"
+ class="org.eclipse.wst.xml.ui.templates.TemplateContextTypeXMLAttributeValue"
+ id="xml_attribute_value">
+ </contextType>
+ <include
+ file="templates/xmldefault-templates.xml"
+ translations="templates/xmldefault-templates.properties">
+ </include>
+ </extension>
+
+
+
+
+
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ name="%XML_Editor.name"
+ icon="icons/xmldoc.gif"
+ extensions="xml, tld, nst, xmi"
+ contributorClass="org.eclipse.wst.xml.internal.ui.XMLMultiPageEditorActionBarContributor"
+ class="org.eclipse.wst.xml.internal.ui.XMLMultiPageEditorPart"
+ id="org.eclipse.wst.xml.internal.ui.XMLMultiPageEditorPart">
+ </editor>
+ </extension>
+<!-- Editor actionsets -->
+ <extension
+ point="org.eclipse.ui.actionSetPartAssociations">
+ <actionSetPartAssociation
+ targetID="org.eclipse.ui.edit.text.actionSet.annotationNavigation">
+ <part
+ id="org.eclipse.wst.xml.internal.ui.XMLMultiPageEditorPart">
+ </part>
+ </actionSetPartAssociation>
+ <actionSetPartAssociation
+ targetID="org.eclipse.ui.NavigateActionSet">
+ <part
+ id="org.eclipse.wst.xml.internal.ui.XMLMultiPageEditorPart">
+ </part>
+ </actionSetPartAssociation>
+ </extension>
+
+
+</plugin>
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/IDesignViewer.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/IDesignViewer.java
new file mode 100644
index 0000000000..493b8fddcf
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/IDesignViewer.java
@@ -0,0 +1,26 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.ui.ViewerSelectionManager;
+
+
+public interface IDesignViewer {
+ public Control getControl();
+
+ String getTitle();
+
+ void setModel(IStructuredModel model);
+
+ void setViewerSelectionManager(ViewerSelectionManager viewerSelectionManager);
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/IDesignViewerActionBarContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/IDesignViewerActionBarContributor.java
new file mode 100644
index 0000000000..ac191b354b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/IDesignViewerActionBarContributor.java
@@ -0,0 +1,19 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+
+
+import org.eclipse.ui.IActionBars;
+import org.eclipse.wst.sse.ui.ISourceViewerActionBarContributor;
+
+
+public interface IDesignViewerActionBarContributor extends ISourceViewerActionBarContributor {
+ public void initViewerSpecificContributions(IActionBars bars);
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/SourceEditorActionBarContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/SourceEditorActionBarContributor.java
new file mode 100644
index 0000000000..bfd080a657
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/SourceEditorActionBarContributor.java
@@ -0,0 +1,211 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorActionBarContributor;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.part.EditorActionBarContributor;
+import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
+import org.eclipse.wst.sse.ui.ISourceViewerActionBarContributor;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.sse.ui.extension.ExtendedEditorActionBuilder;
+import org.eclipse.wst.sse.ui.extension.IExtendedContributor;
+
+
+public class SourceEditorActionBarContributor extends MultiPageEditorActionBarContributor implements IExtendedContributor {
+
+ protected IEditorActionBarContributor designViewerActionBarContributor = null;
+ protected IEditorActionBarContributor sourceViewerActionContributor = null;
+ protected XMLMultiPageEditorPart multiPageEditor = null;
+
+ // EditorExtension
+ private static final String EDITOR_ID = "org.eclipse.wst.xml.ui.XMLMultiPageEditorPart"; //$NON-NLS-1$
+ private IExtendedContributor extendedContributor;
+
+ public SourceEditorActionBarContributor() {
+ super();
+
+ sourceViewerActionContributor = new SourcePageActionContributor();
+
+ // Read action extensions.
+ ExtendedEditorActionBuilder builder = new ExtendedEditorActionBuilder();
+ extendedContributor = builder.readActionExtensions(EDITOR_ID);
+ }
+
+ public void init(IActionBars actionBars) {
+ super.init(actionBars);
+
+ if (actionBars != null) {
+ initDesignViewerActionBarContributor(actionBars);
+ initSourceViewerActionContributor(actionBars);
+ }
+ }
+
+ protected void initDesignViewerActionBarContributor(IActionBars actionBars) {
+ if (designViewerActionBarContributor != null)
+ designViewerActionBarContributor.init(actionBars, getPage());
+ }
+
+ protected void initSourceViewerActionContributor(IActionBars actionBars) {
+ if (sourceViewerActionContributor != null)
+ sourceViewerActionContributor.init(actionBars, getPage());
+ }
+
+ public void dispose() {
+ super.dispose();
+
+ if (designViewerActionBarContributor != null)
+ designViewerActionBarContributor.dispose();
+
+ if (sourceViewerActionContributor != null)
+ sourceViewerActionContributor.dispose();
+
+ if (extendedContributor != null)
+ extendedContributor.dispose();
+ }
+
+ /**
+ * @see EditorActionBarContributor#contributeToMenu(IMenuManager)
+ */
+ public final void contributeToMenu(IMenuManager menu) {
+ super.contributeToMenu(menu);
+
+ addToMenu(menu);
+
+ if (extendedContributor != null)
+ extendedContributor.contributeToMenu(menu);
+ }
+
+ protected void addToMenu(IMenuManager menu) {
+ }
+
+ /**
+ * @see IExtendedContributor#contributeToPopupMenu(IMenuManager)
+ */
+ public final void contributeToPopupMenu(IMenuManager menu) {
+
+ addToPopupMenu(menu);
+
+ if (extendedContributor != null)
+ extendedContributor.contributeToPopupMenu(menu);
+ }
+
+ protected void addToPopupMenu(IMenuManager menu) {
+ }
+
+ /**
+ * @see EditorActionBarContributor#contributeToToolBar(IToolBarManager)
+ */
+ public final void contributeToToolBar(IToolBarManager toolBarManager) {
+ super.contributeToToolBar(toolBarManager);
+
+ addToToolBar(toolBarManager);
+
+ if (extendedContributor != null)
+ extendedContributor.contributeToToolBar(toolBarManager);
+ }
+
+ protected void addToToolBar(IToolBarManager toolBarManager) {
+ }
+
+ /**
+ * @see EditorActionBarContributor#contributeToStatusLine(IStatusLineManager)
+ */
+ public final void contributeToStatusLine(IStatusLineManager manager) {
+ super.contributeToStatusLine(manager);
+
+ addToStatusLine(manager);
+
+ if (extendedContributor != null)
+ extendedContributor.contributeToStatusLine(manager);
+ }
+
+ protected void addToStatusLine(IStatusLineManager manager) {
+ }
+
+ /**
+ * @see IExtendedContributor#updateToolbarActions()
+ */
+ public void updateToolbarActions() {
+ if (extendedContributor != null)
+ extendedContributor.updateToolbarActions();
+ }
+
+ public void setActiveEditor(IEditorPart targetEditor) {
+ // save multiPageEditor before calling
+ // super.setActiveEditor(targetEditor)
+ // super.setActiveEditor will call setActivePage(IEditorPart
+ // activeEditor)
+ // multiPageEditor is needed in setActivePage(IEditorPart
+ // activeEditor)
+ if (targetEditor instanceof XMLMultiPageEditorPart)
+ multiPageEditor = (XMLMultiPageEditorPart) targetEditor;
+
+ super.setActiveEditor(targetEditor);
+
+ updateToolbarActions();
+
+ if (extendedContributor != null)
+ extendedContributor.setActiveEditor(targetEditor);
+ }
+
+ public void setActivePage(IEditorPart activeEditor) {
+ // This contributor is designed for StructuredTextMultiPageEditorPart.
+ // To safe-guard this from problems caused by unexpected usage by
+ // other editors, the following
+ // check is added.
+ if (multiPageEditor != null) {
+ if (activeEditor != null && activeEditor instanceof StructuredTextEditor)
+ activateSourcePage(activeEditor);
+ else
+ activateDesignPage(activeEditor);
+ }
+
+ updateToolbarActions();
+
+ IActionBars actionBars = getActionBars();
+ if (actionBars != null) {
+ // update menu bar and tool bar
+ actionBars.updateActionBars();
+ }
+ }
+
+ protected void activateDesignPage(IEditorPart activeEditor) {
+ if (designViewerActionBarContributor != null && designViewerActionBarContributor instanceof IDesignViewerActionBarContributor) {
+ designViewerActionBarContributor.setActiveEditor(multiPageEditor);
+ }
+
+ if (sourceViewerActionContributor != null && sourceViewerActionContributor instanceof ISourceViewerActionBarContributor) {
+ // if design page is not really an IEditorPart, activeEditor ==
+ // null, so pass in multiPageEditor instead (d282414)
+ if (activeEditor == null) {
+ sourceViewerActionContributor.setActiveEditor(multiPageEditor);
+ } else {
+ sourceViewerActionContributor.setActiveEditor(activeEditor);
+ }
+ ((ISourceViewerActionBarContributor) sourceViewerActionContributor).setViewerSpecificContributionsEnabled(false);
+ }
+ }
+
+ protected void activateSourcePage(IEditorPart activeEditor) {
+ if (designViewerActionBarContributor != null && designViewerActionBarContributor instanceof IDesignViewerActionBarContributor) {
+ designViewerActionBarContributor.setActiveEditor(multiPageEditor);
+ }
+
+ if (sourceViewerActionContributor != null && sourceViewerActionContributor instanceof ISourceViewerActionBarContributor) {
+ sourceViewerActionContributor.setActiveEditor(activeEditor);
+ ((ISourceViewerActionBarContributor) sourceViewerActionContributor).setViewerSpecificContributionsEnabled(true);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/SourcePageActionContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/SourcePageActionContributor.java
new file mode 100644
index 0000000000..949a1557e0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/SourcePageActionContributor.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+
+
+import org.eclipse.ui.IActionBars;
+import org.eclipse.wst.xml.ui.actions.ActionContributorXML;
+
+
+/**
+ * SourcePageActionContributor
+ *
+ * This class is for multi page editor's source page contributor.
+ *
+ * Use XMLEditorActionContributor for single page editor.
+ */
+public class SourcePageActionContributor extends ActionContributorXML {
+
+ private IActionBars fBars;
+
+ /**
+ * This method calls:
+ * <ul>
+ * <li><code>contributeToMenu</code> with <code>bars</code>' menu
+ * manager</li>
+ * <li><code>contributeToToolBar</code> with <code>bars</code>' tool
+ * bar manager</li>
+ * <li><code>contributeToStatusLine</code> with <code>bars</code>'
+ * status line manager</li>
+ * </ul>
+ * The given action bars are also remembered and made accessible via
+ * <code>getActionBars</code>.
+ *
+ * @param bars
+ * the action bars
+ *
+ */
+ public void init(IActionBars bars) {
+ fBars = bars;
+ contributeToMenu(bars.getMenuManager());
+ contributeToToolBar(bars.getToolBarManager());
+ contributeToStatusLine(bars.getStatusLineManager());
+ }
+
+ /**
+ * Returns this contributor's action bars.
+ *
+ * @return the action bars
+ */
+ public IActionBars getActionBars() {
+ return fBars;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorActionDefinitionIds.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorActionDefinitionIds.java
new file mode 100644
index 0000000000..391183654b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorActionDefinitionIds.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+
+
+/**
+ * Defines the definitions ids for the XML editor actions.
+ */
+public interface XMLEditorActionDefinitionIds {
+ public final static String CLEANUP_DOCUMENT = "org.eclipse.wst.sse.ui.edit.ui.cleanup.document";//$NON-NLS-1$
+ public final static String FORMAT_DOCUMENT = "org.eclipse.wst.sse.ui.edit.ui.format.document";//$NON-NLS-1$
+ public final static String FORMAT_ACTIVE_ELEMENTS = "org.eclipse.wst.sse.ui.edit.ui.format.active.elements";//$NON-NLS-1$
+ public final static String OPEN_FILE = "org.eclipse.wst.sse.ui.edit.ui.open.file.from.source";//$NON-NLS-1$
+ // public final static String INFORMATION =
+ // "org.eclipse.wst.sse.ui.edit.ui.show.tooltip.information";//$NON-NLS-1$
+ public final static String INFORMATION = "org.eclipse.jdt.ui.edit.text.java.show.javadoc";//$NON-NLS-1$
+ public final static String ADD_BREAKPOINTS = "org.eclipse.wst.sse.ui.edit.ui.add.breakpoints";//$NON-NLS-1$
+ public final static String MANAGE_BREAKPOINTS = "org.eclipse.wst.sse.ui.edit.ui.manage.breakpoints";//$NON-NLS-1$
+ public final static String ENABLE_BREAKPOINTS = "org.eclipse.wst.sse.ui.edit.ui.enable.breakpoints";//$NON-NLS-1$
+ public final static String DISABLE_BREAKPOINTS = "org.eclipse.wst.sse.ui.edit.ui.disable.breakpoints";//$NON-NLS-1$
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginHOLD_OLD.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginHOLD_OLD.java
new file mode 100644
index 0000000000..18a781ce31
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginHOLD_OLD.java
@@ -0,0 +1,127 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+
+
+import org.eclipse.core.runtime.IPluginDescriptor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+import org.eclipse.wst.sse.ui.preferences.CommonEditorPreferenceNames;
+import org.eclipse.wst.sse.ui.registry.AdapterFactoryRegistry;
+import org.eclipse.wst.sse.ui.registry.AdapterFactoryRegistryImpl;
+import org.eclipse.wst.sse.ui.registry.embedded.EmbeddedAdapterFactoryRegistryImpl;
+import org.eclipse.wst.xml.core.XMLPreferenceNames;
+
+
+public class XMLEditorPluginHOLD_OLD extends AbstractUIPlugin {
+
+ public final static String PLUGIN_ID = "org.eclipse.wst.xml.ui.internal.XMLEditorPluginHOLD_OLD"; //$NON-NLS-1$
+ protected static XMLEditorPluginHOLD_OLD instance = null;
+
+ /**
+ * XMLEditorPlugin constructor comment.
+ *
+ * @param descriptor
+ * com.ibm.itp.core.api.plugins.IPluginDescriptor
+ */
+ public XMLEditorPluginHOLD_OLD(IPluginDescriptor descriptor) {
+ super(descriptor);
+ instance = this;
+
+ // reference the preference store so
+ // initializeDefaultPreferences(IPreferenceStore preferenceStore) is
+ // called
+ getPreferenceStore();
+ }
+
+ public static XMLEditorPluginHOLD_OLD getDefault() {
+ return instance;
+ }
+
+ public synchronized static XMLEditorPluginHOLD_OLD getInstance() {
+ return instance;
+ }
+
+ public AdapterFactoryRegistry getAdapterFactoryRegistry() {
+ return AdapterFactoryRegistryImpl.getInstance();
+
+ }
+
+ public AdapterFactoryRegistry getEmbeddedAdapterFactoryRegistry() {
+ return EmbeddedAdapterFactoryRegistryImpl.getInstance();
+
+ }
+
+ /**
+ * Creates XML Preference store and initializes its default values
+ */
+ protected void initializeDefaultPreferences(IPreferenceStore preferenceStore) {
+ preferenceStore.setDefault(XMLPreferenceNames.LAST_ACTIVE_PAGE, 0);
+
+ // editor prefs
+ preferenceStore.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER, false);
+ preferenceStore.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_OVERVIEW_RULER, true);
+ preferenceStore.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE, false);
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.CONTENT_ASSIST_SUPPORTED, false);
+ preferenceStore.setDefault(CommonEditorPreferenceNames.AUTO_PROPOSE, true);
+ preferenceStore.setDefault(CommonEditorPreferenceNames.AUTO_PROPOSE_CODE, CommonEditorPreferenceNames.LT);
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.MATCHING_BRACKETS, true);
+ PreferenceConverter.setDefault(preferenceStore, CommonEditorPreferenceNames.MATCHING_BRACKETS_COLOR, new RGB(192, 192, 192));
+
+ preferenceStore.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE, true);
+ PreferenceConverter.setDefault(preferenceStore, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR, new RGB(225, 235, 224));
+
+ preferenceStore.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN, true);
+ PreferenceConverter.setDefault(preferenceStore, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLOR, new RGB(176, 180, 185));
+
+ preferenceStore.setDefault(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN, 80);
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.EDITOR_USE_INFERRED_GRAMMAR, true);
+
+ initializeDefaultAnnotationPrefs(preferenceStore);
+ }
+
+ /*
+ * Using this method for all content types initialize methods since
+ * they're all the same (for now) @param preferenceStore
+ */
+ private void initializeDefaultAnnotationPrefs(IPreferenceStore preferenceStore) {
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.ERROR_INDICATION, true);
+ PreferenceConverter.setDefault(preferenceStore, CommonEditorPreferenceNames.ERROR_INDICATION_COLOR, new RGB(255, 0, 128));
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.WARNING_INDICATION, true);
+ PreferenceConverter.setDefault(preferenceStore, CommonEditorPreferenceNames.WARNING_INDICATION_COLOR, new RGB(244, 200, 45));
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.TASK_INDICATION, false);
+ PreferenceConverter.setDefault(preferenceStore, CommonEditorPreferenceNames.TASK_INDICATION_COLOR, new RGB(0, 128, 255));
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.BOOKMARK_INDICATION, false);
+ PreferenceConverter.setDefault(preferenceStore, CommonEditorPreferenceNames.BOOKMARK_INDICATION_COLOR, new RGB(34, 164, 99));
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.SEARCH_RESULT_INDICATION, true);
+ PreferenceConverter.setDefault(preferenceStore, CommonEditorPreferenceNames.SEARCH_RESULT_INDICATION_COLOR, new RGB(192, 192, 192));
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.UNKNOWN_INDICATION, false);
+ PreferenceConverter.setDefault(preferenceStore, CommonEditorPreferenceNames.UNKNOWN_INDICATION_COLOR, new RGB(0, 0, 0));
+
+ preferenceStore.setDefault(CommonEditorPreferenceNames.ERROR_INDICATION_IN_OVERVIEW_RULER, true);
+ preferenceStore.setDefault(CommonEditorPreferenceNames.WARNING_INDICATION_IN_OVERVIEW_RULER, true);
+ preferenceStore.setDefault(CommonEditorPreferenceNames.TASK_INDICATION_IN_OVERVIEW_RULER, true);
+ preferenceStore.setDefault(CommonEditorPreferenceNames.BOOKMARK_INDICATION_IN_OVERVIEW_RULER, true);
+ preferenceStore.setDefault(CommonEditorPreferenceNames.SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER, true);
+ preferenceStore.setDefault(CommonEditorPreferenceNames.UNKNOWN_INDICATION_IN_OVERVIEW_RULER, false);
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginImageHelper.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginImageHelper.java
new file mode 100644
index 0000000000..2e813eb6b7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginImageHelper.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.xml.ui.XMLEditorPlugin;
+
+/**
+ * Helper class to handle images provided by this plug-in.
+ *
+ * NOTE: For internal use only. For images used externally, please use the
+ * Shared***ImageHelper class instead.
+ *
+ * @author amywu
+ */
+public class XMLEditorPluginImageHelper {
+ private final String PLUGINID = XMLEditorPlugin.ID;
+ private static XMLEditorPluginImageHelper instance = null;
+
+ // save a descriptor for each image
+ private HashMap fImageDescRegistry = null;
+
+ /**
+ * Gets the instance.
+ *
+ * @return Returns a XMLEditorPluginImageHelper
+ */
+ public synchronized static XMLEditorPluginImageHelper getInstance() {
+ if (instance == null)
+ instance = new XMLEditorPluginImageHelper();
+ return instance;
+ }
+
+ /**
+ * Retrieves the image associated with resource from the image registry.
+ * If the image cannot be retrieved, attempt to find and load the image at
+ * the location specified in resource.
+ *
+ * @param resource
+ * the image to retrieve
+ * @return Image the image associated with resource or null if one could
+ * not be found
+ */
+ public Image getImage(String resource) {
+ Image image = getImageRegistry().get(resource);
+ if (image == null) {
+ // create an image
+ image = createImage(resource);
+ }
+ return image;
+ }
+
+ /**
+ * Retrieves the image descriptor associated with resource from the image
+ * descriptor registry. If the image descriptor cannot be retrieved,
+ * attempt to find and load the image descriptor at the location specified
+ * in resource.
+ *
+ * @param resource
+ * the image descriptor to retrieve
+ * @return ImageDescriptor the image descriptor assocated with resource or
+ * the default "missing" image descriptor if one could not be
+ * found
+ */
+ public ImageDescriptor getImageDescriptor(String resource) {
+ ImageDescriptor imageDescriptor = null;
+ Object o = getImageDescriptorRegistry().get(resource);
+ if (o == null) {
+ //create a descriptor
+ imageDescriptor = createImageDescriptor(resource);
+ } else {
+ imageDescriptor = (ImageDescriptor) o;
+ }
+ return imageDescriptor;
+ }
+
+ /**
+ * Returns the image descriptor registry for this plugin.
+ *
+ * @return HashMap - image descriptor registry for this plugin
+ */
+ private HashMap getImageDescriptorRegistry() {
+ if (fImageDescRegistry == null)
+ fImageDescRegistry = new HashMap();
+ return fImageDescRegistry;
+ }
+
+ /**
+ * Returns the image registry for this plugin.
+ *
+ * @return ImageRegistry - image registry for this plugin
+ */
+ private ImageRegistry getImageRegistry() {
+ return JFaceResources.getImageRegistry();
+ }
+
+ /**
+ * Creates an image from the given resource and adds the image to the
+ * image registry.
+ *
+ * @param resource
+ * @return Image
+ */
+ private Image createImage(String resource) {
+ ImageDescriptor desc = getImageDescriptor(resource);
+ Image image = null;
+
+ if (desc != null) {
+ image = desc.createImage();
+ // dont add the missing image descriptor image to the image
+ // registry
+ if (!desc.equals(ImageDescriptor.getMissingImageDescriptor()))
+ getImageRegistry().put(resource, image);
+ }
+ return image;
+ }
+
+ /**
+ * Creates an image descriptor from the given imageFilePath and adds the
+ * image descriptor to the image descriptor registry. If an image
+ * descriptor could not be created, the default "missing" image descriptor
+ * is returned but not added to the image descriptor registry.
+ *
+ * @param imageFilePath
+ * @return ImageDescriptor image descriptor for imageFilePath or default
+ * "missing" image descriptor if resource could not be found
+ */
+ private ImageDescriptor createImageDescriptor(String imageFilePath) {
+ ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(PLUGINID, imageFilePath);
+ if (imageDescriptor != null) {
+ getImageDescriptorRegistry().put(imageFilePath, imageDescriptor);
+ } else {
+ imageDescriptor = ImageDescriptor.getMissingImageDescriptor();
+ }
+
+ return imageDescriptor;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginImages.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginImages.java
new file mode 100644
index 0000000000..b1ee193ec4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLEditorPluginImages.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+/**
+ * Bundle of most images used by the XML Editor plug-in.
+ */
+public class XMLEditorPluginImages {
+ public static final String IMG_DTOOL_COLLAPSE = "icons/full/dtool16/collapse.gif"; //$NON-NLS-1$
+ public static final String IMG_ETOOL_COLLAPSE = "icons/full/etool16/collapse.gif"; //$NON-NLS-1$
+ public static final String IMG_DTOOL_COLLAPSEALL = "icons/full/dtool16/collapse_all.gif"; //$NON-NLS-1$
+ public static final String IMG_ETOOL_COLLAPSEALL = "icons/full/etool16/collapse_all.gif"; //$NON-NLS-1$
+ public static final String IMG_DTOOL_EXPAND = "icons/full/dtool16/expand.gif"; //$NON-NLS-1$
+ public static final String IMG_ETOOL_EXPAND = "icons/full/etool16/expand.gif"; //$NON-NLS-1$
+ public static final String IMG_DTOOL_EXPANDALL = "icons/full/dtool16/expand_all.gif"; //$NON-NLS-1$
+ public static final String IMG_ETOOL_EXPANDALL = "icons/full/etool16/expand_all.gif"; //$NON-NLS-1$
+ public static final String IMG_DTOOL_NEW_XML = "icons/full/dtool16/new_xml.gif"; //$NON-NLS-1$
+ public static final String IMG_ETOOL_NEW_XML = "icons/full/etool16/new_xml.gif"; //$NON-NLS-1$
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLMultiPageEditorActionBarContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLMultiPageEditorActionBarContributor.java
new file mode 100644
index 0000000000..8eb0240f9c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLMultiPageEditorActionBarContributor.java
@@ -0,0 +1,89 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+
+
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.wst.sse.ui.ISourceViewerActionBarContributor;
+import org.eclipse.wst.xml.ui.internal.tabletree.XMLTableTreeActionBarContributor;
+
+
+public class XMLMultiPageEditorActionBarContributor extends SourceEditorActionBarContributor {
+
+ private boolean needsMultiInit = true;
+
+ public XMLMultiPageEditorActionBarContributor() {
+ super();
+ }
+
+ protected void initDesignViewerActionBarContributor(IActionBars actionBars) {
+ super.initDesignViewerActionBarContributor(actionBars);
+
+ if (designViewerActionBarContributor != null)
+ if (designViewerActionBarContributor instanceof IDesignViewerActionBarContributor)
+ ((IDesignViewerActionBarContributor) designViewerActionBarContributor).initViewerSpecificContributions(actionBars);
+ }
+
+ protected void activateDesignPage(IEditorPart activeEditor) {
+ if (sourceViewerActionContributor != null && sourceViewerActionContributor instanceof ISourceViewerActionBarContributor) {
+ // if design page is not really an IEditorPart, activeEditor ==
+ // null, so pass in multiPageEditor instead (d282414)
+ if (activeEditor == null) {
+ sourceViewerActionContributor.setActiveEditor(multiPageEditor);
+ } else {
+ sourceViewerActionContributor.setActiveEditor(activeEditor);
+ }
+ ((ISourceViewerActionBarContributor) sourceViewerActionContributor).setViewerSpecificContributionsEnabled(false);
+ }
+
+ if (designViewerActionBarContributor != null && designViewerActionBarContributor instanceof IDesignViewerActionBarContributor) {
+ designViewerActionBarContributor.setActiveEditor(multiPageEditor);
+ ((IDesignViewerActionBarContributor) designViewerActionBarContributor).setViewerSpecificContributionsEnabled(true);
+ }
+ }
+
+ protected void activateSourcePage(IEditorPart activeEditor) {
+ if (designViewerActionBarContributor != null && designViewerActionBarContributor instanceof IDesignViewerActionBarContributor) {
+ designViewerActionBarContributor.setActiveEditor(multiPageEditor);
+ ((IDesignViewerActionBarContributor) designViewerActionBarContributor).setViewerSpecificContributionsEnabled(false);
+ }
+
+ if (sourceViewerActionContributor != null && sourceViewerActionContributor instanceof ISourceViewerActionBarContributor) {
+ sourceViewerActionContributor.setActiveEditor(activeEditor);
+ ((ISourceViewerActionBarContributor) sourceViewerActionContributor).setViewerSpecificContributionsEnabled(true);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.part.EditorActionBarContributor#init(org.eclipse.ui.IActionBars)
+ */
+ public void init(IActionBars actionBars) {
+ super.init(actionBars);
+ needsMultiInit = true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.IEditorActionBarContributor#setActiveEditor(org.eclipse.ui.IEditorPart)
+ */
+ public void setActiveEditor(IEditorPart targetEditor) {
+ if (needsMultiInit) {
+ designViewerActionBarContributor = new XMLTableTreeActionBarContributor();
+ initDesignViewerActionBarContributor(getActionBars());
+ needsMultiInit = false;
+ }
+ super.setActiveEditor(targetEditor);
+ }
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLMultiPageEditorPart.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLMultiPageEditorPart.java
new file mode 100644
index 0000000000..c49a95b8d3
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/internal/ui/XMLMultiPageEditorPart.java
@@ -0,0 +1,773 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.internal.ui;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.swt.events.ShellAdapter;
+import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorActionBarContributor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IPropertyListener;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.ui.ide.IGotoMarker;
+import org.eclipse.ui.part.MultiPageEditorPart;
+import org.eclipse.ui.part.MultiPageEditorSite;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.core.XMLPreferenceNames;
+import org.eclipse.wst.xml.ui.Logger;
+import org.eclipse.wst.xml.ui.StructuredTextEditorXML;
+import org.eclipse.wst.xml.ui.XMLEditorPlugin;
+import org.eclipse.wst.xml.ui.internal.tabletree.XMLTableTreeHelpContextIds;
+import org.eclipse.wst.xml.ui.internal.tabletree.XMLTableTreeViewer;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+
+public class XMLMultiPageEditorPart extends MultiPageEditorPart implements IPropertyListener {
+
+ /**
+ * Internal part activation listener
+ */
+ class PartListener extends ShellAdapter implements IPartListener {
+ private IWorkbenchPart fActivePart;
+ private boolean fIsHandlingActivation = false;
+
+ private void handleActivation() {
+
+ if (fIsHandlingActivation)
+ return;
+
+ if (fActivePart == XMLMultiPageEditorPart.this) {
+ fIsHandlingActivation = true;
+ try {
+ safelySanityCheckState();
+ } finally {
+ fIsHandlingActivation = false;
+ }
+ }
+ }
+
+ /**
+ * @see IPartListener#partActivated(IWorkbenchPart)
+ */
+ public void partActivated(IWorkbenchPart part) {
+ fActivePart = part;
+ handleActivation();
+ }
+
+ /**
+ * @see IPartListener#partBroughtToTop(IWorkbenchPart)
+ */
+ public void partBroughtToTop(IWorkbenchPart part) {
+ }
+
+ /**
+ * @see IPartListener#partClosed(IWorkbenchPart)
+ */
+ public void partClosed(IWorkbenchPart part) {
+ }
+
+ /**
+ * @see IPartListener#partDeactivated(IWorkbenchPart)
+ */
+ public void partDeactivated(IWorkbenchPart part) {
+ fActivePart = null;
+ }
+
+ /**
+ * @see IPartListener#partOpened(IWorkbenchPart)
+ */
+ public void partOpened(IWorkbenchPart part) {
+ }
+
+ /*
+ * @see ShellListener#shellActivated(ShellEvent)
+ */
+ public void shellActivated(ShellEvent e) {
+ handleActivation();
+ }
+ }
+
+ class TextInputListener implements ITextInputListener {
+ public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
+ }
+
+ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+ if (fDesignViewer != null && newInput != null)
+ fDesignViewer.setModel(getModel());
+ }
+ }
+
+ /** The design page index. */
+ private int fDesignPageIndex;
+
+ /** The design viewer */
+ private IDesignViewer fDesignViewer;
+
+ /** The source page index. */
+ private int fSourcePageIndex;
+ /** The text editor. */
+ private StructuredTextEditor fTextEditor;
+
+ private PartListener partListener;
+
+ /**
+ * StructuredTextMultiPageEditorPart constructor comment.
+ */
+ public XMLMultiPageEditorPart() {
+ super();
+ }
+
+ /*
+ * This method is just to make firePropertyChanged accessbible from some
+ * (anonomous) inner classes.
+ */
+ protected void _firePropertyChange(int property) {
+ super.firePropertyChange(property);
+ }
+
+ /**
+ * Adds the source page of the multi-page editor.
+ */
+ protected void addSourcePage() throws PartInitException {
+ try {
+ fSourcePageIndex = addPage(fTextEditor, getEditorInput());
+ setPageText(fSourcePageIndex, org.eclipse.wst.xml.ui.nls2.ResourceHandler.getString("XMLMultiPageEditorPart.0")); //$NON-NLS-1$
+ // the update's critical, to get viewer selection manager and
+ // highlighting to work
+ fTextEditor.update();
+
+ firePropertyChange(PROP_TITLE);
+
+ // Changes to the Text Viewer's document instance should also
+ // force an
+ // input refresh
+ fTextEditor.getTextViewer().addTextInputListener(new TextInputListener());
+ } catch (PartInitException exception) {
+ // dispose editor
+ dispose();
+
+ throw new SourceEditingRuntimeException(ResourceHandler.getString("An_error_has_occurred_when1_ERROR_")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Connects the design viewer with the viewer selection manager. Should be
+ * done after createSourcePage() is done because we need to get the
+ * ViewerSelectionManager from the TextEditor. setModel is also done here
+ * because getModel() needs to reference the TextEditor.
+ */
+ protected void connectDesignPage() {
+ if (fDesignViewer != null) {
+ fDesignViewer.setViewerSelectionManager(fTextEditor.getViewerSelectionManager());
+ fDesignViewer.setModel(getModel());
+ }
+ }
+
+ /**
+ * Create and Add the Design Page using a registered factory
+ *
+ * @throws PartInitException
+ */
+ protected void createAndAddDesignPage() {
+ XMLTableTreeViewer tableTreeViewer = new XMLTableTreeViewer(getContainer());
+ // Set the default infopop for XML design viewer.
+ WorkbenchHelp.setHelp(tableTreeViewer.getControl(), XMLTableTreeHelpContextIds.XML_DESIGN_VIEW_HELPID);
+
+ fDesignViewer = tableTreeViewer;
+ // note: By adding the design page as a Control instead of an
+ // IEditorPart, page switches will indicate
+ // a "null" active editor when the design page is made active
+ fDesignPageIndex = addPage(tableTreeViewer.getControl());
+ setPageText(fDesignPageIndex, tableTreeViewer.getTitle());
+ }
+
+ /**
+ * Creates the pages of this multi-page editor.
+ * <p>
+ * Subclasses of <code>MultiPageEditor</code> must implement this
+ * method.
+ * </p>
+ */
+ protected void createPages() {
+ try {
+ // source page MUST be created before design page, now
+ createSourcePage();
+ createAndAddDesignPage();
+ addSourcePage();
+ connectDesignPage();
+
+ setActivePage();
+
+ // future_TODO: add a catch block here for any exception the
+ // design
+ // page throws and convert it into a more informative message.
+ } catch (PartInitException e) {
+ Logger.logException(e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.part.MultiPageEditorPart#createSite(org.eclipse.ui.IEditorPart)
+ */
+ protected IEditorSite createSite(IEditorPart editor) {
+ IEditorSite site = null;
+ if (editor == fTextEditor) {
+ site = new MultiPageEditorSite(this, editor) {
+ /**
+ * @see org.eclipse.ui.part.MultiPageEditorSite#getActionBarContributor()
+ */
+ public IEditorActionBarContributor getActionBarContributor() {
+ IEditorActionBarContributor contributor = super.getActionBarContributor();
+ IEditorActionBarContributor multiContributor = XMLMultiPageEditorPart.this.getEditorSite().getActionBarContributor();
+ if (multiContributor instanceof XMLMultiPageEditorActionBarContributor) {
+ contributor = ((XMLMultiPageEditorActionBarContributor) multiContributor).sourceViewerActionContributor;
+ }
+ return contributor;
+ }
+ };
+ } else {
+ site = super.createSite(editor);
+ }
+ return site;
+ }
+
+ /**
+ * Creates the source page of the multi-page editor.
+ */
+ protected void createSourcePage() throws PartInitException {
+ fTextEditor = createTextEditor();
+ fTextEditor.setEditorPart(this);
+
+ // Set the SourceViewerConfiguration now so the text editor won't use
+ // the default configuration first
+ // and switch to the StructuredTextViewerConfiguration later.
+ // DMW removed setSourceViewerConfiguration 3/26/2003 since added
+ // createPartControl to our text editor.
+ // fTextEditor.setSourceViewerConfiguration();
+ fTextEditor.addPropertyListener(this);
+ }
+
+ /**
+ * Method createTextEditor.
+ *
+ * @return StructuredTextEditor
+ */
+ protected StructuredTextEditor createTextEditor() {
+ return new StructuredTextEditorXML();
+ }
+
+ protected void disconnectDesignPage() {
+ if (fDesignViewer != null) {
+ fDesignViewer.setModel(null);
+ fDesignViewer.setViewerSelectionManager(null);
+ }
+ }
+
+ public void dispose() {
+ Logger.trace("Source Editor", "StructuredTextMultiPageEditorPart::dispose entry"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ disconnectDesignPage();
+
+ IWorkbenchWindow window = getSite().getWorkbenchWindow();
+ window.getPartService().removePartListener(partListener);
+ window.getShell().removeShellListener(partListener);
+
+ getSite().getPage().removePartListener(partListener);
+ if (fTextEditor != null) {
+ fTextEditor.removePropertyListener(this);
+ }
+
+ // moved to last when added window ... seems like
+ // we'd be in danger of losing some data, like site,
+ // or something.
+ super.dispose();
+
+ Logger.trace("Source Editor", "StructuredTextMultiPageEditorPart::dispose exit"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ /*
+ * (non-Javadoc) Saves the contents of this editor. <p> Subclasses must
+ * override this method to implement the open-save-close lifecycle for an
+ * editor. For greater details, see <code> IEditorPart </code></p>
+ *
+ * @see IEditorPart
+ */
+ public void doSave(IProgressMonitor monitor) {
+ fTextEditor.doSave(monitor);
+ // // this is a temporary way to force validation.
+ // // when the validator is a workbench builder, the following lines
+ // can be removed
+ // if (fDesignViewer != null)
+ // fDesignViewer.saveOccurred();
+
+ }
+
+ /*
+ * (non-Javadoc) Saves the contents of this editor to another object. <p>
+ * Subclasses must override this method to implement the open-save-close
+ * lifecycle for an editor. For greater details, see <code> IEditorPart
+ * </code></p>
+ *
+ * @see IEditorPart
+ */
+ public void doSaveAs() {
+ fTextEditor.doSaveAs();
+ // 253619
+ // following used to be executed here, but is
+ // now called "back" from text editor (since
+ // mulitiple paths to the performSaveAs in StructuredTextEditor.
+ //doSaveAsForStructuredTextMulitPagePart();
+ }
+
+ private void editorInputIsAcceptable(IEditorInput input) throws PartInitException {
+ if (input instanceof IFileEditorInput) {
+ // verify that it can be opened
+ CoreException[] coreExceptionArray = new CoreException[1];
+ if (fileDoesNotExist((IFileEditorInput) input, coreExceptionArray)) {
+ CoreException coreException = coreExceptionArray[0];
+ if (coreException.getStatus().getCode() == IResourceStatus.FAILED_READ_LOCAL) {
+ // I'm assuming this is always 'does not exist'
+ // we'll refresh local go mimic behavior of default
+ // editor, where the
+ // troublesome file is refreshed (and will cause it to
+ // 'disappear' from Navigator.
+ try {
+ ((IFileEditorInput) input).getFile().refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
+ } catch (CoreException ce) {
+ // very unlikely
+ Logger.logException(ce);
+ }
+ throw new PartInitException(ResourceHandler.getString("23concat_EXC_", (new Object[]{input.getName()}))); //$NON-NLS-1$
+ //$NON-NLS-1$ = "Resource {0} does not exist."
+ } else {
+ throw new PartInitException(ResourceHandler.getString("32concat_EXC_", (new Object[]{input.getName()}))); //$NON-NLS-1$
+ //$NON-NLS-1$ = "Editor could not be open on {0}"
+ }
+ }
+ } else if (input instanceof IStorageEditorInput) {
+ InputStream contents = null;
+ try {
+ contents = ((IStorageEditorInput) input).getStorage().getContents();
+ } catch (CoreException noStorageExc) {
+ }
+ if (contents == null) {
+ throw new PartInitException(ResourceHandler.getString("32concat_EXC_", (new Object[]{input.getName()}))); //$NON-NLS-1$
+ } else {
+ try {
+ contents.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ // void doSaveAsForStructuredTextMulitPagePart() {
+ // setPageText(getActivePage(), fTextEditor.getTitle());
+ // setInput(fTextEditor.getEditorInput());
+ // if (fDesignViewer != null) {
+ // //fDesignViewer.setEditorInput(fTextEditor.getEditorInput());
+ // fDesignViewer.setModel(getModel());
+ // fDesignViewer.saveAsOccurred();
+ // }
+ // // even though we've set title etc., several times already!
+ // // only now is all prepared for it.
+ // firePropertyChange(IWorkbenchPart.PROP_TITLE);
+ // firePropertyChange(PROP_DIRTY);
+ // }
+ /*
+ * (non-Javadoc) Initializes the editor part with a site and input. <p>
+ * Subclasses of <code> EditorPart </code> must implement this method.
+ * Within the implementation subclasses should verify that the input type
+ * is acceptable and then save the site and input. Here is sample code:
+ * </p><pre> if (!(input instanceof IFileEditorInput)) throw new
+ * PartInitException("Invalid Input: Must be IFileEditorInput");
+ * setSite(site); setInput(editorInput); </pre>
+ */
+ protected boolean fileDoesNotExist(IFileEditorInput input, Throwable[] coreException) {
+ boolean result = false;
+ InputStream inStream = null;
+ if ((!(input.exists())) || (!(input.getFile().exists()))) {
+ result = true;
+ } else {
+ try {
+ inStream = input.getFile().getContents(true);
+ } catch (CoreException e) {
+ // very likely to be file not found
+ result = true;
+ coreException[0] = e;
+ } finally {
+ if (input != null) {
+ try {
+ if (inStream != null) {
+ inStream.close();
+ }
+ } catch (IOException e) {
+ Logger.logException(e);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ public Object getAdapter(Class key) {
+ Object result = null;
+ if (key == IDesignViewer.class) {
+ result = fDesignViewer;
+ } else {
+ // DMW: I'm bullet-proofing this because
+ // its been reported (on 4.03 version) a null pointer sometimes
+ // happens here on startup, when an editor has been left
+ // open when workbench shutdown.
+ if (fTextEditor != null) {
+ result = fTextEditor.getAdapter(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * IExtendedMarkupEditor method
+ */
+ public Node getCaretNode() {
+ if (getTextEditor() == null)
+ return null;
+
+ return getTextEditor().getCaretNode();
+ }
+
+ /**
+ * IExtendedSimpleEditor method
+ */
+ public int getCaretPosition() {
+ if (getTextEditor() == null)
+ return -1;
+
+ return getTextEditor().getCaretPosition();
+ }
+
+ /**
+ * IExtendedSimpleEditor method
+ */
+ public IDocument getDocument() {
+ if (getTextEditor() == null)
+ return null;
+
+ return getTextEditor().getDocument();
+ }
+
+ /**
+ * IExtendedMarkupEditor method
+ */
+ public Document getDOMDocument() {
+ if (getTextEditor() == null)
+ return null;
+
+ return getTextEditor().getDOMDocument();
+ }
+
+ /**
+ * IExtendedSimpleEditor method
+ */
+ public IEditorPart getEditorPart() {
+ return this;
+ }
+
+ protected IStructuredModel getModel() {
+ IStructuredModel model = null;
+ if (fTextEditor != null)
+ model = fTextEditor.getModel();
+ return model;
+ }
+
+ protected IPreferenceStore getPreferenceStore() {
+ return XMLEditorPlugin.getDefault().getPreferenceStore();
+ }
+
+ /**
+ * IExtendedMarkupEditor method
+ */
+ public List getSelectedNodes() {
+ if (getTextEditor() == null)
+ return null;
+ return getTextEditor().getSelectedNodes();
+ }
+
+ /**
+ * IExtendedSimpleEditor method
+ */
+ public Point getSelectionRange() {
+ if (getTextEditor() == null)
+ return new Point(-1, -1);
+
+ return getTextEditor().getSelectionRange();
+ }
+
+ public StructuredTextEditor getTextEditor() {
+ return fTextEditor;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWorkbenchPart.
+ */
+ public String getTitle() {
+ String title = null;
+ if (getTextEditor() == null) {
+ if (getEditorInput() != null) {
+ title = getEditorInput().getName();
+ }
+ } else {
+ title = getTextEditor().getTitle();
+ }
+ if (title == null) {
+ title = getPartName();
+ }
+ return title;
+ }
+
+ /*
+ * (non-Javadoc) Sets the cursor and selection state for this editor to
+ * the passage defined by the given marker. <p> Subclasses may override.
+ * For greater details, see <code> IEditorPart </code></p>
+ *
+ * @see IEditorPart
+ */
+ public void gotoMarker(IMarker marker) {
+ // (pa) 20020217 this was null when opening an editor that was
+ // already open
+ if (fTextEditor != null) {
+ IGotoMarker markerGotoer = (IGotoMarker) fTextEditor.getAdapter(IGotoMarker.class);
+ markerGotoer.gotoMarker(marker);
+ }
+ }
+
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+ editorInputIsAcceptable(input);
+ try {
+ super.init(site, input);
+ if (partListener == null) {
+ partListener = new PartListener();
+ }
+ //getSite().getPage().addPartListener(partListner);
+ // we want to listen for our own activation
+ IWorkbenchWindow window = getSite().getWorkbenchWindow();
+ window.getPartService().addPartListener(partListener);
+ window.getShell().addShellListener(partListener);
+ } catch (Exception e) {
+ if (e instanceof SourceEditingRuntimeException) {
+ Throwable t = ((SourceEditingRuntimeException) e).getOriginalException();
+ if (t instanceof IOException) {
+ System.out.println(t);
+ // file not found
+ }
+ }
+ }
+ setPartName(input.getName());
+ }
+
+ /*
+ * (non-Javadoc) Returns whether the "save as" operation is supported by
+ * this editor. <p> Subclasses must override this method to implement the
+ * open-save-close lifecycle for an editor. For greater details, see
+ * <code> IEditorPart </code></p>
+ *
+ * @see IEditorPart
+ */
+ public boolean isSaveAsAllowed() {
+ return fTextEditor != null && fTextEditor.isSaveAsAllowed();
+ }
+
+ /*
+ * (non-Javadoc) Returns whether the contents of this editor should be
+ * saved when the editor is closed. <p> This method returns <code> true
+ * </code> if and only if the editor is dirty ( <code> isDirty </code> ).
+ * </p>
+ */
+ public boolean isSaveOnCloseNeeded() {
+ // overriding super class since it does a lowly isDirty!
+ if (fTextEditor != null)
+ return fTextEditor.isSaveOnCloseNeeded();
+ return isDirty();
+ }
+
+ /**
+ * Notifies this multi-page editor that the page with the given id has
+ * been activated. This method is called when the user selects a different
+ * tab.
+ *
+ * @param newPageIndex
+ * the index of the activated page
+ */
+ protected void pageChange(int newPageIndex) {
+ super.pageChange(newPageIndex);
+
+ saveLastActivePageIndex(newPageIndex);
+ }
+
+ /**
+ * Posts the update code "behind" the running operation.
+ */
+ protected void postOnDisplayQue(Runnable runnable) {
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
+ if (windows != null && windows.length > 0) {
+ Display display = windows[0].getShell().getDisplay();
+ display.asyncExec(runnable);
+ } else
+ runnable.run();
+ }
+
+ /**
+ * Indicates that a property has changed.
+ *
+ * @param source
+ * the object whose property has changed
+ * @param propId
+ * the id of the property which has changed; property ids are
+ * generally defined as constants on the source class
+ */
+ public void propertyChanged(Object source, int propId) {
+ switch (propId) {
+ // had to implement input changed "listener" so that
+ // strucutedText could tell it containing editor that
+ // the input has change, when a 'resource moved' event is
+ // found.
+ case IEditorPart.PROP_INPUT :
+ case IEditorPart.PROP_DIRTY : {
+ if (source == fTextEditor) {
+ if (fTextEditor.getEditorInput() != getEditorInput()) {
+ setInput(fTextEditor.getEditorInput());
+ // title should always change when input changes.
+ // create runnable for following post call
+ Runnable runnable = new Runnable() {
+ public void run() {
+ _firePropertyChange(IWorkbenchPart.PROP_TITLE);
+ }
+ };
+ // Update is just to post things on the display queue
+ // (thread). We have to do this to get the dirty
+ // property to get updated after other things on the
+ // queue are executed.
+ postOnDisplayQue(runnable);
+ }
+ }
+ break;
+ }
+ case IWorkbenchPart.PROP_TITLE : {
+ // update the input if the title is changed
+ if (source == fTextEditor) {
+ if (fTextEditor.getEditorInput() != getEditorInput()) {
+ setInput(fTextEditor.getEditorInput());
+ }
+ }
+ break;
+ }
+ default : {
+ // propagate changes. Is this needed? Answer: Yes.
+ if (source == fTextEditor) {
+ firePropertyChange(propId);
+ }
+ break;
+ }
+ }
+
+ }
+
+ protected void safelySanityCheckState() {
+ // If we're called before editor is created, simply ignore since we
+ // delegate this function to our embedded TextEditor
+ if (getTextEditor() == null)
+ return;
+
+ getTextEditor().safelySanityCheckState(getEditorInput());
+
+ }
+
+ protected void saveLastActivePageIndex(int newPageIndex) {
+ // save the last active page index to preference manager
+ getPreferenceStore().setValue(XMLPreferenceNames.LAST_ACTIVE_PAGE, newPageIndex);
+ }
+
+ /**
+ * Sets the currently active page.
+ */
+ protected void setActivePage() {
+ // retrieve the last active page index from preference manager
+ int activePageIndex = getPreferenceStore().getInt(XMLPreferenceNames.LAST_ACTIVE_PAGE);
+
+ // We check this range since someone could hand edit the XML
+ // preference file to an invalid value ... which I know from
+ // experience :( ... if they do, we'll reset to default and continue
+ // rather than throw an assertion error in the setActivePage(int)
+ // method.
+ if (activePageIndex < 0 || activePageIndex >= getPageCount()) {
+ activePageIndex = fDesignPageIndex;
+ }
+ setActivePage(activePageIndex);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.part.EditorPart#setInput(org.eclipse.ui.IEditorInput)
+ */
+ protected void setInput(IEditorInput input) {
+ // If driven from the Source page, it's "model" may not be up to date
+ // with the input just yet. We'll rely on later notification from the
+ // TextViewer to set us straight
+ super.setInput(input);
+ if (fDesignViewer != null)
+ fDesignViewer.setModel(getModel());
+ setPartName(input.getName());
+ }
+
+ /**
+ * IExtendedMarkupEditor method
+ */
+ public IStatus validateEdit(Shell context) {
+ if (getTextEditor() == null)
+ return new Status(IStatus.ERROR, XMLEditorPlugin.ID, IStatus.INFO, "", null); //$NON-NLS-1$
+
+ return getTextEditor().validateEdit(context);
+ }
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/DOMPropertyDescriptorFactory.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/DOMPropertyDescriptorFactory.java
new file mode 100644
index 0000000000..dfa592378b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/DOMPropertyDescriptorFactory.java
@@ -0,0 +1,138 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.TextPropertyDescriptor;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.ui.views.properties.EnumeratedStringPropertyDescriptor;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+public class DOMPropertyDescriptorFactory {
+
+ protected static final String HACK = "hack"; //$NON-NLS-1$
+ private ModelQuery fModelQuery = null;
+
+ public DOMPropertyDescriptorFactory(ModelQuery modelQuery) {
+ fModelQuery = modelQuery;
+ }
+
+ public IPropertyDescriptor createAttributePropertyDescriptor(Attr attr) {
+ IPropertyDescriptor result = null;
+
+ String attributeName = attr.getName();
+
+ CMAttributeDeclaration ad = fModelQuery.getCMAttributeDeclaration(attr);
+ if (ad != null) {
+ String[] valuesArray = fModelQuery.getPossibleDataTypeValues(attr.getOwnerElement(), ad);
+ if (valuesArray != null && valuesArray.length > 0) {
+ result = new EnumeratedStringPropertyDescriptor(attributeName, attributeName, valuesArray);
+ }
+ }
+
+ if (result == null) {
+ result = createDefaultPropertyDescriptor(attributeName);
+ }
+ return result;
+ }
+
+ public IPropertyDescriptor createCDATASectionPropertyDescriptor(CDATASection cdataSection) {
+ return createDefaultPropertyDescriptor(HACK);
+ }
+
+ public IPropertyDescriptor createCommentPropertyDescriptor(Comment comment) {
+ return createDefaultPropertyDescriptor(HACK);
+ }
+
+ protected IPropertyDescriptor createDefaultPropertyDescriptor(String attributeName) {
+ TextPropertyDescriptor descriptor = new TextPropertyDescriptor(attributeName, attributeName);
+ return descriptor;
+ }
+
+ public IPropertyDescriptor createDocumentTypePropertyDescriptor(DocumentType documentType) {
+ return null; //new TextPropertyDescriptor(HACK, HACK);
+ }
+
+ public IPropertyDescriptor createElementPropertyDescriptor(Element element) {
+ return createDefaultPropertyDescriptor(HACK);
+ }
+
+ public IPropertyDescriptor createEntityReferencePropertyDescriptor(EntityReference entityReference) {
+ return createDefaultPropertyDescriptor(HACK);
+ }
+
+ public IPropertyDescriptor createProcessingInstructionPropertyDescriptor(ProcessingInstruction pi) {
+ return createDefaultPropertyDescriptor(HACK);
+ }
+
+ public IPropertyDescriptor createPropertyDescriptor(Object object) {
+ IPropertyDescriptor result = null;
+ if (object instanceof Node) {
+ Node node = (Node) object;
+ int nodeType = node.getNodeType();
+ switch (nodeType) {
+ case Node.ATTRIBUTE_NODE : {
+ result = createAttributePropertyDescriptor((Attr) node);
+ break;
+ }
+ case Node.CDATA_SECTION_NODE : {
+ result = createCDATASectionPropertyDescriptor((CDATASection) node);
+ break;
+ }
+ case Node.COMMENT_NODE : {
+ result = createCommentPropertyDescriptor((Comment) node);
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE : {
+ result = createDocumentTypePropertyDescriptor((DocumentType) node);
+ break;
+ }
+ case Node.ELEMENT_NODE : {
+ result = createElementPropertyDescriptor((Element) node);
+ break;
+ }
+ case Node.ENTITY_REFERENCE_NODE : {
+ result = createEntityReferencePropertyDescriptor((EntityReference) node);
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ result = createProcessingInstructionPropertyDescriptor((ProcessingInstruction) node);
+ break;
+ }
+ case Node.TEXT_NODE : {
+ result = createTextPropertyDescriptor((Text) node);
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ public IPropertyDescriptor createTextPropertyDescriptor(Text text) {
+ return createDefaultPropertyDescriptor(HACK);
+ }
+
+ /**
+ * @return
+ */
+ public ModelQuery getModelQuery() {
+ return fModelQuery;
+ }
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java
new file mode 100644
index 0000000000..d042bc2a8c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java
@@ -0,0 +1,431 @@
+/*******************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.common.contentmodel.util.DOMWriter;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+/**
+ * This performs the work of taking a DOM tree and converting it to a
+ * displayable 'UI' tree.
+ *
+ * For example : - white space text nodes are ommited from the 'UI' tree -
+ * adjacent Text and EntityReference nodes are combined into a single 'UI'
+ * node - Elements with 'text only' children are diplayed without children
+ *
+ */
+public class TreeContentHelper {
+
+ public static final int HIDE_WHITE_SPACE_TEXT_NODES = 8;
+ public static final int COMBINE_ADJACENT_TEXT_AND_ENTITY_REFERENCES = 16;
+ public static final int HIDE_ELEMENT_CHILD_TEXT_NODES = 32;
+
+ protected int style = HIDE_WHITE_SPACE_TEXT_NODES | COMBINE_ADJACENT_TEXT_AND_ENTITY_REFERENCES | HIDE_ELEMENT_CHILD_TEXT_NODES;
+
+ /**
+ *
+ */
+ public boolean hasStyleFlag(int flag) {
+ return (style & flag) != 0;
+ }
+
+ /**
+ *
+ */
+ public Object[] getChildren(Object element) {
+ Object[] result = null;
+
+ if (element instanceof Node) {
+ Node node = (Node) element;
+ List list = new ArrayList();
+ boolean textContentOnly = true;
+
+ NamedNodeMap map = node.getAttributes();
+ if (map != null) {
+ int length = map.getLength();
+ for (int i = 0; i < length; i++) {
+ list.add(map.item(i));
+ textContentOnly = false;
+ }
+ }
+
+ Node prevIncludedNode = null;
+ for (Node childNode = node.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()) {
+ int childNodeType = childNode.getNodeType();
+ boolean includeNode = true;
+
+ if (includeNode && hasStyleFlag(HIDE_WHITE_SPACE_TEXT_NODES)) {
+ if (isIgnorableText(childNode)) {
+ // filter out the ignorable text node
+ includeNode = false;
+ }
+ }
+
+ if (includeNode && hasStyleFlag(COMBINE_ADJACENT_TEXT_AND_ENTITY_REFERENCES)) {
+ if (isTextOrEntityReferenceNode(childNode) && prevIncludedNode != null && isTextOrEntityReferenceNode(prevIncludedNode)) {
+ // we only show the first of a list of adjacent text
+ // or entity reference node in the tree
+ // so we filter out this subsequent one
+ includeNode = false;
+ }
+ }
+
+ if (hasStyleFlag(HIDE_ELEMENT_CHILD_TEXT_NODES)) {
+ if (childNodeType != Node.TEXT_NODE && childNodeType != Node.ENTITY_REFERENCE_NODE) {
+ textContentOnly = false;
+ }
+ }
+
+ if (includeNode) {
+ list.add(childNode);
+ prevIncludedNode = childNode;
+ }
+ }
+
+ if (hasStyleFlag(HIDE_ELEMENT_CHILD_TEXT_NODES) && textContentOnly) {
+ result = new Object[0];
+ } else {
+ result = list.toArray();
+ }
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ protected boolean isTextOrEntityReferenceNode(Node node) {
+ return node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.ENTITY_REFERENCE_NODE;
+ }
+
+ /**
+ *
+ */
+ public boolean isIgnorableText(Node node) {
+ boolean result = false;
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ String data = ((Text) node).getData();
+ result = (data == null || data.trim().length() == 0);
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ public boolean isCombinedTextNode(Node node) {
+ boolean result = false;
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ Node nextNode = node.getNextSibling();
+ if (nextNode != null) {
+ if (nextNode.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+ result = true;
+ }
+ }
+ } else if (node.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+ result = true;
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ public List getCombinedTextNodeList(Node theNode) {
+ List list = new Vector();
+ boolean prevIsEntity = false;
+ for (Node node = theNode; node != null; node = node.getNextSibling()) {
+ int nodeType = node.getNodeType();
+ if (nodeType == Node.ENTITY_REFERENCE_NODE) {
+ prevIsEntity = true;
+ list.add(node);
+ } else if (nodeType == Node.TEXT_NODE && (prevIsEntity || node == theNode)) {
+ prevIsEntity = false;
+ list.add(node);
+ } else {
+ break;
+ }
+ }
+ return list;
+ }
+
+ /**
+ * If the element is has 'text only' content this method will return the
+ * list of elements that compose the text only content
+ */
+ public List getElementTextContent(Element element) {
+ List result = null;
+ if (!element.hasAttributes()) {
+ for (Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
+ if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+ if (result == null) {
+ result = new Vector();
+ }
+ result.add(node);
+ } else {
+ result = null;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ public String getNodeValue(Node node) {
+ String result = null;
+ int nodeType = node.getNodeType();
+ switch (nodeType) {
+ case Node.ATTRIBUTE_NODE : {
+ result = ((Attr) node).getValue();
+ break;
+ }
+ case Node.CDATA_SECTION_NODE :
+ // drop thru
+ case Node.COMMENT_NODE : {
+ result = ((CharacterData) node).getData();
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE : {
+ result = getDocumentTypeValue((DocumentType) node);
+ break;
+ }
+ case Node.ELEMENT_NODE : {
+ result = getElementNodeValue((Element) node);
+ break;
+ }
+ case Node.ENTITY_REFERENCE_NODE :
+ // drop thru
+ case Node.TEXT_NODE : {
+ result = getTextNodeValue(node);
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ result = ((ProcessingInstruction) node).getData();
+ break;
+ }
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ public void setNodeValue(Node node, String value) {
+ int nodeType = node.getNodeType();
+ try {
+ switch (nodeType) {
+ case Node.ATTRIBUTE_NODE : {
+ ((Attr) node).setValue(value);
+ break;
+ }
+ case Node.CDATA_SECTION_NODE :
+ // drop thru
+ case Node.COMMENT_NODE : {
+ ((CharacterData) node).setData(value);
+ break;
+ }
+ case Node.ELEMENT_NODE : {
+ setElementNodeValue((Element) node, value);
+ break;
+ }
+ case Node.ENTITY_REFERENCE_NODE :
+ // drop thru
+ case Node.TEXT_NODE : {
+ setTextNodeValue(node, value);
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ ((ProcessingInstruction) node).setData(value);
+ break;
+ }
+ }
+ } catch (DOMException e) {
+ Display d = getDisplay();
+ if (d != null)
+ d.beep();
+ }
+ }
+
+ private Display getDisplay() {
+
+ return PlatformUI.getWorkbench().getDisplay();
+ }
+
+
+ /**
+ *
+ */
+ protected String getDocumentTypeValue(DocumentType documentType) {
+ return DOMWriter.getDocumentTypeData(documentType);
+ }
+
+ /**
+ *
+ */
+ protected String getElementNodeValue(Element element) {
+ String result = null;
+ List list = getElementTextContent(element);
+ if (list != null) {
+ result = getValueForTextContent(list);
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ protected void setElementNodeValue(Element element, String value) {
+ List list = getElementTextContent(element);
+ if (list != null) {
+ setValueForTextContent(list, value);
+ } else {
+ Document document = element.getOwnerDocument();
+ Text text = document.createTextNode(value);
+ element.appendChild(text);
+ }
+ }
+
+ /**
+ *
+ */
+ protected String getTextNodeValue(Node node) {
+ String result = null;
+ List list = null;
+ if (isCombinedTextNode(node)) {
+ list = getCombinedTextNodeList(node);
+ } else {
+ list = new Vector();
+ list.add(node);
+ }
+ result = getValueForTextContent(list);
+ return result;
+ }
+
+ /**
+ *
+ */
+ protected void setTextNodeValue(Node node, String value) {
+ List list = null;
+ if (isCombinedTextNode(node)) {
+ list = getCombinedTextNodeList(node);
+ } else {
+ list = new Vector();
+ list.add(node);
+ }
+ setValueForTextContent(list, value);
+ }
+
+ public Text getEffectiveTextNodeForCombinedNodeList(List list) {
+ Text result = null;
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ Node node = (Node) i.next();
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ result = (Text) node;
+ break;
+ }
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ protected String getValueForTextContent(List list) {
+ String result = null;
+ if (list.size() > 0) {
+ XMLNode first = (XMLNode) list.get(0);
+ XMLNode last = (XMLNode) list.get(list.size() - 1);
+ XMLModel model = first.getModel();
+ int start = first.getStartOffset();
+ int end = last.getEndOffset();
+ try {
+ result = model.getStructuredDocument().get(start, end - start);
+ } catch (Exception e) {
+ }
+ }
+
+ // we trim the content so that it looks nice when viewed
+ // we need to be carfull to preserve the 'trimmed' text when the value
+ // is set (see setValueForTextContent)
+ if (result != null) {
+ result = result.trim();
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ protected void setValueForTextContent(List list, String value) {
+ //String oldValue = getValueForTextContent();
+ // we worry about preserving trimmed text
+ if (list.size() > 0) {
+ XMLNode first = (XMLNode) list.get(0);
+ XMLNode last = (XMLNode) list.get(list.size() - 1);
+ int start = first.getStartOffset();
+ int end = last.getEndOffset();
+ first.getModel().getStructuredDocument().replaceText(this, start, end - start, value);
+ }
+ }
+
+ /**
+ *
+ */
+ public boolean isEditable(Node node) {
+ int nodeType = node.getNodeType();
+ boolean result = false;
+ switch (nodeType) {
+ case Node.ATTRIBUTE_NODE :
+ // drop thru
+ case Node.CDATA_SECTION_NODE :
+ // drop thru
+ case Node.COMMENT_NODE :
+ // drop thru
+ case Node.ENTITY_REFERENCE_NODE :
+ // drop thru
+ case Node.TEXT_NODE :
+ // drop thru
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ result = true;
+ break;
+ }
+ case Node.ELEMENT_NODE : {
+ result = getElementTextContent((Element) node) != null || node.getChildNodes().getLength() == 0;
+ break;
+ }
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeExtension.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeExtension.java
new file mode 100644
index 0000000000..bd3c54e938
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeExtension.java
@@ -0,0 +1,512 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellEditorListener;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.PlatformUI;
+
+
+public class TreeExtension implements PaintListener {
+
+ protected Tree tree;
+ protected EditManager editManager;
+ protected String[] columnProperties;
+ protected ICellModifier cellModifier;
+ protected int columnPosition = 300;
+ protected int columnHitWidth = 5;
+ protected Color tableLineColor;
+ protected int controlWidth;
+ protected DelayedDrawTimer delayedDrawTimer;
+
+ public TreeExtension(Tree tree) {
+ this.tree = tree;
+ InternalMouseListener listener = new InternalMouseListener();
+ tree.addMouseMoveListener(listener);
+ tree.addMouseListener(listener);
+ tree.addPaintListener(this);
+ editManager = new EditManager(tree);
+ delayedDrawTimer = new DelayedDrawTimer(tree);
+
+ tableLineColor = tree.getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+ }
+
+ public void dispose() {
+ tableLineColor.dispose();
+ }
+
+ public void setCellModifier(ICellModifier modifier) {
+ cellModifier = modifier;
+ }
+
+ public void resetCachedData() {
+ }
+
+ public ICellModifier getCellModifier() {
+ return cellModifier;
+ }
+
+ public List getItemList() {
+ List list = new Vector();
+ getItemListHelper(tree.getItems(), list);
+ return list;
+ }
+
+ protected void getItemListHelper(TreeItem[] items, List list) {
+ for (int i = 0; i < items.length; i++) {
+ TreeItem item = items[i];
+ list.add(item);
+ getItemListHelper(item.getItems(), list);
+ }
+ }
+
+ protected TreeItem getTreeItemOnRow(int px, int py) {
+ TreeItem result = null;
+ List list = getItemList();
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ TreeItem item = (TreeItem) i.next();
+ Rectangle r = item.getBounds();
+ if (r != null && px >= r.x && py >= r.y && py <= r.y + r.height) {
+ result = item;
+ }
+ }
+ return result;
+ }
+
+ protected class InternalMouseListener extends MouseAdapter implements MouseMoveListener {
+ protected int columnDragged = -1;
+ protected boolean isDown = false;
+ protected int prevX = -1;
+ protected Cursor cursor = null;
+
+ public void mouseMove(MouseEvent e) {
+ if (e.x > columnPosition - columnHitWidth && e.x < columnPosition + columnHitWidth) {
+ if (cursor == null) {
+ cursor = new Cursor(tree.getDisplay(), SWT.CURSOR_SIZEWE);
+ tree.setCursor(cursor);
+ }
+ } else {
+ if (cursor != null) {
+ tree.setCursor(null);
+ cursor.dispose();
+ cursor = null;
+ }
+ }
+
+ if (columnDragged != -1) {
+ // using the delay timer will make redraws less flickery
+ if (e.x > 20) {
+ columnPosition = e.x;
+ delayedDrawTimer.reset(20);
+ }
+ }
+ }
+
+ public void mouseDown(MouseEvent e) {
+ // here we handle the column resizing by detect if the user has
+ // click on a column separator
+ //
+ columnDragged = -1;
+ editManager.deactivateCellEditor();
+
+ if (e.x > columnPosition - columnHitWidth && e.x < columnPosition + columnHitWidth) {
+ columnDragged = 0;
+ }
+
+ // here we handle selecting tree items when any thing on the 'row'
+ // is clicked
+ //
+ TreeItem item = tree.getItem(new Point(e.x, e.y));
+ if (item == null) {
+ item = getTreeItemOnRow(e.x, e.y);
+ if (item != null) {
+ TreeItem[] items = new TreeItem[1];
+ items[0] = item;
+ tree.setSelection(items);
+ }
+ }
+ }
+
+ public void mouseUp(MouseEvent e) {
+ columnDragged = -1;
+ }
+ }
+
+ public String[] getColumnProperties() {
+ return columnProperties;
+ }
+
+ public void setColumnProperties(String[] columnProperties) {
+ this.columnProperties = columnProperties;
+ }
+
+ public void paintControl(PaintEvent event) {
+ GC gc = event.gc;
+ Rectangle treeBounds = tree.getBounds();
+
+ controlWidth = treeBounds.width;
+ Color bg = tree.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+ Color bg2 = tree.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+
+ gc.setBackground(bg2);
+
+ // // This next part causes problems on LINUX, so let's not do it
+ // there
+ // if (B2BHacks.IS_UNIX == false) {
+ // TreeItem[] selectedItems = tree.getSelection();
+ // if (selectedItems.length > 0) {
+ // for (int i = 0; i < selectedItems.length; i++) {
+ // TreeItem item = selectedItems[i];
+ // Rectangle bounds = item.getBounds();
+ // if (bounds != null) {
+ // gc.fillRectangle(bounds.x + bounds.width, bounds.y, controlWidth,
+ // bounds.height);
+ // }
+ // }
+ // }
+ // }
+ //
+ TreeItem[] items = tree.getItems();
+ if (items.length > 0) {
+ gc.setForeground(tableLineColor);
+ gc.setBackground(bg);
+
+ gc.fillRectangle(columnPosition, treeBounds.x, treeBounds.width, treeBounds.height);
+
+ Rectangle itemBounds = items[0].getBounds();
+ int height = computeTreeItemHeight();
+
+ if (itemBounds != null) {
+ int startY = itemBounds.y < treeBounds.y ? itemBounds.y : treeBounds.y + ((treeBounds.y - itemBounds.y) % height);
+
+ for (int i = startY; i < treeBounds.height; i += height) {
+ if (i >= treeBounds.y) {
+ gc.drawLine(0, i, treeBounds.width, i);
+ }
+ }
+ }
+ gc.drawLine(columnPosition, 0, columnPosition, treeBounds.height);
+ } else {
+ addEmptyTreeMessage(gc);
+ }
+
+ paintItems(gc, items, treeBounds);
+ }
+
+ protected int computeTreeItemHeight() {
+ int result = -1;
+
+ // On GTK tree.getItemHeight() seems to lie to us. It reports that the
+ // tree item occupies a few pixles less
+ // vertical space than it should. This which foils our code that draw
+ // the 'row' lines since we assume that
+ // lines should be drawn at 'itemHeight' increments. In the case of
+ // LINUX we don't trust getItemHeight()
+ // to compute the increment... instead we compute the value based on
+ // distance between two TreeItems.
+ // if (B2BHacks.IS_UNIX) {
+ // TreeItem[] items = tree.getItems();
+ // Rectangle itemBounds = items[0].getBounds();
+ //
+ // if (items[0].getExpanded()) {
+ // TreeItem[] children = items[0].getItems();
+ // if (children.length > 0) {
+ // result = children[0].getBounds().y - itemBounds.y;
+ // }
+ // }
+ // else if (items.length > 1) {
+ // result = items[1].getBounds().y - itemBounds.y;
+ // }
+ // }
+
+ result = result != -1 ? result : tree.getItemHeight();
+ return result;
+ }
+
+ protected void addEmptyTreeMessage(GC gc) {
+ }
+
+ public void paintItems(GC gc, TreeItem[] items, Rectangle treeBounds) {
+ if (items != null) {
+ for (int i = 0; i < items.length; i++) {
+ TreeItem item = items[i];
+ if (item != null) {
+ Rectangle bounds = item.getBounds();
+ if (bounds != null) {
+ if (treeBounds.intersects(bounds)) {
+ paintItem(gc, item, bounds);
+ }
+ }
+
+ // defect 241039
+ //
+ if (item.getExpanded()) {
+ paintItems(gc, item.getItems(), treeBounds);
+ }
+ }
+ }
+ }
+ }
+
+ protected void paintItem(GC gc, TreeItem item, Rectangle bounds) {
+ }
+
+ public interface ICellEditorProvider {
+ CellEditor getCellEditor(Object o, int col);
+ }
+
+ /**
+ * This class is used to improve drawing during a column resize.
+ */
+ public class DelayedDrawTimer implements Runnable {
+ protected Control control;
+
+ public DelayedDrawTimer(Control control) {
+ this.control = control;
+ }
+
+ public void reset(int milliseconds) {
+ getDisplay().timerExec(milliseconds, this);
+ }
+
+ public void run() {
+ control.redraw();
+ }
+ }
+
+ private Display getDisplay() {
+
+ return PlatformUI.getWorkbench().getDisplay();
+ }
+
+ /**
+ * EditManager
+ */
+ public class EditManager {
+ protected Tree tree;
+ protected Control cellEditorHolder;
+ protected CellEditorState cellEditorState;
+
+ public EditManager(Tree tree) {
+ this.tree = tree;
+ this.cellEditorHolder = new Composite(tree, SWT.NONE);
+
+ final Tree theTree = tree;
+
+ MouseAdapter theMouseAdapter = new MouseAdapter() {
+ public void mouseDown(MouseEvent e) {
+ deactivateCellEditor();
+
+ if (e.x > columnPosition + columnHitWidth) {
+ TreeItem[] items = theTree.getSelection();
+ // No edit if more than one row is selected.
+ if (items.length == 1) {
+ Rectangle bounds = items[0].getBounds();
+ if (bounds != null && e.y >= bounds.y && e.y <= bounds.y + bounds.height) {
+ int columnToEdit = 1;
+ activateCellEditor(items[0], columnToEdit);
+ }
+ }
+ }
+ }
+ };
+
+ SelectionListener selectionListener = new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ applyCellEditorValue();
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ applyCellEditorValue();
+ }
+ };
+
+ KeyListener keyListener = new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ if (e.character == SWT.CR) {
+ deactivateCellEditor();
+ TreeItem[] items = theTree.getSelection();
+ if (items.length == 1) {
+ activateCellEditor(items[0], 1);
+ }
+ }
+ }
+ };
+
+ tree.addMouseListener(theMouseAdapter);
+ tree.addKeyListener(keyListener);
+ ScrollBar hBar = tree.getHorizontalBar();
+ if (hBar != null)
+ hBar.addSelectionListener(selectionListener);
+ ScrollBar vBar = tree.getVerticalBar();
+ if (vBar != null)
+ vBar.addSelectionListener(selectionListener);
+ }
+
+ public boolean isCellEditorActive() {
+ return cellEditorState != null;
+ }
+
+ public void applyCellEditorValue() {
+ if (cellEditorState != null && cellModifier != null) {
+ TreeItem treeItem = cellEditorState.treeItem;
+
+ // The area below the cell editor needs to be explicity
+ // repainted on Linux
+ //
+ // Rectangle r = B2BHacks.IS_UNIX ? treeItem.getBounds() :
+ // null;
+
+ Object value = cellEditorState.cellEditor.getValue();
+ String property = cellEditorState.property;
+
+ deactivateCellEditor();
+
+ cellModifier.modify(treeItem, property, value);
+
+ // if (r != null) {
+ // tree.redraw(r.x, r.y, tree.getBounds().width, r.height,
+ // false);
+ // }
+ }
+ }
+
+ public void deactivateCellEditor() {
+ // Clean up any previous editor control
+ if (cellEditorState != null) {
+ cellEditorState.deactivate();
+ cellEditorState = null;
+ }
+ }
+
+ public void activateCellEditor(TreeItem treeItem, int column) {
+ if (cellModifier instanceof ICellEditorProvider) {
+ ICellEditorProvider cellEditorProvider = (ICellEditorProvider) cellModifier;
+ Object data = treeItem.getData();
+ if (columnProperties.length > column) {
+ String property = columnProperties[column];
+ if (cellModifier.canModify(data, property)) {
+ CellEditor newCellEditor = cellEditorProvider.getCellEditor(data, column);
+ if (newCellEditor != null) {
+ // The control that will be the editor must be a
+ // child of the columnPosition
+ Control control = newCellEditor.getControl();
+ if (control != null) {
+ cellEditorState = new CellEditorState(newCellEditor, control, treeItem, column, property);
+ cellEditorState.activate();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * this class holds the state that is need on a per cell editor
+ * invocation basis
+ */
+ public class CellEditorState implements ICellEditorListener, FocusListener {
+ public CellEditor cellEditor;
+ public Control control;
+ public TreeItem treeItem;
+ public int columnNumber;
+ public String property;
+
+ public CellEditorState(CellEditor cellEditor, Control control, TreeItem treeItem, int columnNumber, String property) {
+ this.cellEditor = cellEditor;
+ this.control = control;
+ this.treeItem = treeItem;
+ this.columnNumber = columnNumber;
+ this.property = property;
+ }
+
+ public void activate() {
+ Object element = treeItem.getData();
+ String value = cellModifier.getValue(element, property).toString();
+ if (control instanceof Text) {
+ Text text = (Text) control;
+ int requiredSize = value.length() + 100;
+ if (text.getTextLimit() < requiredSize) {
+ text.setTextLimit(requiredSize);
+ }
+ }
+ Rectangle r = treeItem.getBounds();
+ if (r != null) {
+ control.setBounds(columnPosition + 5, r.y + 1, tree.getClientArea().width - (columnPosition + 5), r.height - 1);
+ control.setVisible(true);
+ cellEditor.setValue(value);
+ cellEditor.addListener(this);
+ cellEditor.setFocus();
+ control.addFocusListener(this);
+ }
+ }
+
+ public void deactivate() {
+ cellEditor.removeListener(this);
+ control.removeFocusListener(this);
+ cellEditor.deactivate();
+ tree.forceFocus();
+ }
+
+ // ICellEditorListener methods
+ //
+ public void applyEditorValue() {
+ applyCellEditorValue();
+ }
+
+ public void cancelEditor() {
+ deactivateCellEditor();
+ }
+
+ public void editorValueChanged(boolean oldValidState, boolean newValidState) {
+ }
+
+ // FocusListener methods
+ //
+ public void focusGained(FocusEvent e) {
+ }
+
+ public void focusLost(FocusEvent e) {
+ applyCellEditorValue();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/ViewerExpandCollapseAction.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/ViewerExpandCollapseAction.java
new file mode 100644
index 0000000000..956c7dee2c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/ViewerExpandCollapseAction.java
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.wst.xml.internal.ui.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.internal.ui.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+
+
+
+public class ViewerExpandCollapseAction extends Action {
+
+ protected boolean isExpandAction;
+ protected AbstractTreeViewer viewer = null;
+
+ public ViewerExpandCollapseAction(boolean isExpandAction) {
+ this.isExpandAction = isExpandAction;
+ if (isExpandAction) {
+ ImageDescriptor e_imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_ETOOL_EXPANDALL);
+ ImageDescriptor d_imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_DTOOL_EXPANDALL);
+
+ setImageDescriptor(e_imageDescriptor);
+ setDisabledImageDescriptor(d_imageDescriptor);
+ setToolTipText(XMLCommonResources.getInstance().getString("_UI_INFO_EXPAND_ALL")); //$NON-NLS-1$
+ } else {
+ ImageDescriptor e_imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_ETOOL_COLLAPSEALL);
+ ImageDescriptor d_imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_DTOOL_COLLAPSEALL);
+
+ setImageDescriptor(e_imageDescriptor);
+ setDisabledImageDescriptor(d_imageDescriptor);
+ setToolTipText(XMLCommonResources.getInstance().getString("_UI_INFO_COLLAPSE_ALL")); //$NON-NLS-1$
+ }
+ }
+
+ public void setViewer(AbstractTreeViewer viewer) {
+ this.viewer = viewer;
+ }
+
+ public void run() {
+ if (viewer != null) {
+ // temporarily set the visibility to false
+ // this has a HUGE performance benefit
+ boolean isVisible = viewer.getControl().getVisible();
+ viewer.getControl().setVisible(false);
+
+ if (isExpandAction) {
+ viewer.expandAll();
+ } else {
+ viewer.collapseAll();
+ }
+
+ // restore the previous visibility state
+ //
+ viewer.getControl().setVisible(isVisible);
+ }
+ }
+}
+
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeActionBarContributor.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeActionBarContributor.java
new file mode 100644
index 0000000000..02675f7956
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeActionBarContributor.java
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorActionBarContributor;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.modelqueryimpl.CMDocumentLoader;
+import org.eclipse.wst.common.contentmodel.modelqueryimpl.InferredGrammarBuildingCMDocumentLoader;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.internal.ui.IDesignViewer;
+import org.eclipse.wst.xml.internal.ui.IDesignViewerActionBarContributor;
+import org.eclipse.wst.xml.internal.ui.XMLMultiPageEditorPart;
+import org.eclipse.wst.xml.ui.nls2.ResourceHandler;
+import org.eclipse.wst.xml.ui.util.SharedXMLEditorPluginImageHelper;
+import org.w3c.dom.Document;
+
+
+/**
+ *
+ */
+public class XMLTableTreeActionBarContributor implements IDesignViewerActionBarContributor {
+
+ protected IEditorPart editorPart;
+ protected final static String DESIGN_VIEWER_SEPARATOR_1_ID = "sed.tabletree.separator.1"; //$NON-NLS-1$
+ protected final static String DESIGN_VIEWER_SEPARATOR_2_ID = "sed.tabletree.separator.2"; //$NON-NLS-1$
+ protected final static String VALIDATE_XML_ID = "sed.tabletree.validateXML"; //$NON-NLS-1$
+ protected final static String RELOAD_GRAMMAR_ID = "sed.tabletree.reloadGrammar"; //$NON-NLS-1$
+ protected final static String TOGGLE_EDIT_MODE_ID = "sed.tabletree.toggleEditMode"; //$NON-NLS-1$
+ protected final static String EXPAND_ALL_ID = "sed.tabletree.expandAll"; //$NON-NLS-1$
+ protected final static String COLLAPSE_ALL_ID = "sed.tabletree.collapseAll"; //$NON-NLS-1$
+
+ protected ToggleEditModeAction toggleAction;
+ protected ReloadGrammarAction reloadGrammarAction;
+ // protected ValidateXMLAction validateXMLAction;
+ protected ViewerExpandCollapseAction expandAction;
+ protected ViewerExpandCollapseAction collapseAction;
+ protected ViewerExpandCollapseAction xmlMenuExpandAction;
+ protected ViewerExpandCollapseAction xmlMenuCollapseAction;
+
+ public XMLTableTreeActionBarContributor() {
+ }
+
+ protected void removeContributions(IContributionManager manager) {
+ try {
+ doRemove(manager, DESIGN_VIEWER_SEPARATOR_1_ID);
+ doRemove(manager, DESIGN_VIEWER_SEPARATOR_2_ID);
+ doRemove(manager, VALIDATE_XML_ID);
+ doRemove(manager, RELOAD_GRAMMAR_ID);
+ doRemove(manager, TOGGLE_EDIT_MODE_ID);
+ doRemove(manager, EXPAND_ALL_ID);
+ doRemove(manager, COLLAPSE_ALL_ID);
+ } catch (Exception e) {
+ }
+ }
+
+ protected void doRemove(IContributionManager manager, String id) {
+ try {
+ if (manager.find(id) != null) {
+ manager.remove(id);
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ public void init(IActionBars bars, IWorkbenchPage page) {
+ init(bars);
+ }
+
+ public void init(IActionBars bars) {
+ IToolBarManager tbm = bars.getToolBarManager();
+
+ IMenuManager xmlMenu = bars.getMenuManager().findMenuUsingPath("com.ibm.etools.sed.editor.xmlmenu"); //$NON-NLS-1$
+
+ if (xmlMenu == null) {
+ xmlMenu = new MenuManager(ResourceHandler.getString("XMLTableTreeActionBarContributor.0"), "com.ibm.etools.sed.editor.xmlmenu"); //$NON-NLS-1$ //$NON-NLS-2$
+ bars.getMenuManager().insertBefore(IWorkbenchActionConstants.M_WINDOW, xmlMenu);
+ } else {
+ removeContributions(xmlMenu);
+ }
+
+ tbm.add(new Separator("DESIGN_VIEWER_SEPARATOR_1_ID")); //$NON-NLS-1$
+
+ // ValidateXMLAction
+ //
+ // ugly hack ... we don't contribute the generic XML validator if we
+ // already
+ // have a DAD validator contribution (in the case of the DAD editor).
+ // This hack will be removed when defect 212448 is fixed.
+ //
+ // if (tbm.find("validate.dad.validateDAD") == null) {
+ // validateXMLAction = new ValidateXMLAction();
+ // tbm.add(validateXMLAction);
+ // xmlMenu.add(validateXMLAction);
+ // }
+
+ // ToggleEditModeAction
+ //
+ toggleAction = new ToggleEditModeAction();
+ toggleAction.setId(TOGGLE_EDIT_MODE_ID);
+ xmlMenu.add(toggleAction);
+ tbm.add(toggleAction);
+
+ // ReloadGrammarAction
+ //
+ reloadGrammarAction = new ReloadGrammarAction();
+ reloadGrammarAction.setId(RELOAD_GRAMMAR_ID);
+ tbm.add(reloadGrammarAction);
+ xmlMenu.add(reloadGrammarAction);
+
+ xmlMenu.add(new Separator());
+
+ // ExpandCollapseAction
+ //
+ xmlMenuExpandAction = new ViewerExpandCollapseAction(true);
+ xmlMenuExpandAction.setId(EXPAND_ALL_ID);
+ xmlMenuExpandAction.setText(ResourceHandler.getString("XMLTableTreeActionBarContributor.1")); //$NON-NLS-1$
+ xmlMenu.add(xmlMenuExpandAction);
+
+ xmlMenuCollapseAction = new ViewerExpandCollapseAction(false);
+ xmlMenuCollapseAction.setId(COLLAPSE_ALL_ID);
+ xmlMenuCollapseAction.setId(EXPAND_ALL_ID);
+ xmlMenuCollapseAction.setText(ResourceHandler.getString("XMLTableTreeActionBarContributor.2")); //$NON-NLS-1$
+ xmlMenu.add(xmlMenuCollapseAction);
+ }
+
+ protected void addActionWithId(IMenuManager menuManager, Action action, String id) {
+ action.setId(id);
+ menuManager.add(action);
+ }
+
+ public void initViewerSpecificContributions(IActionBars bars) {
+ IToolBarManager tbm = bars.getToolBarManager();
+ tbm.add(new Separator(DESIGN_VIEWER_SEPARATOR_2_ID));
+
+ expandAction = new ViewerExpandCollapseAction(true);
+ expandAction.setId(EXPAND_ALL_ID);
+ tbm.add(expandAction);
+
+ collapseAction = new ViewerExpandCollapseAction(false);
+ collapseAction.setId(COLLAPSE_ALL_ID);
+ tbm.add(collapseAction);
+ }
+
+ public void setViewerSpecificContributionsEnabled(boolean enabled) {
+ if (expandAction != null) {
+ expandAction.setEnabled(enabled);
+ xmlMenuExpandAction.setEnabled(enabled);
+ }
+
+ if (collapseAction != null) {
+ collapseAction.setEnabled(enabled);
+ xmlMenuCollapseAction.setEnabled(enabled);
+ }
+ }
+
+ public void setActiveEditor(IEditorPart targetEditor) {
+ editorPart = targetEditor;
+
+ IStructuredModel model = getModelForEditorPart(targetEditor);
+ reloadGrammarAction.setModel(model);
+ toggleAction.setModelQuery(ModelQueryUtil.getModelQuery(model));
+
+ XMLTableTreeViewer tableTreeViewer = getTableTreeViewerForEditorPart(editorPart);
+ if (tableTreeViewer != null) {
+ expandAction.setViewer(tableTreeViewer);
+ collapseAction.setViewer(tableTreeViewer);
+
+ xmlMenuExpandAction.setViewer(tableTreeViewer);
+ xmlMenuCollapseAction.setViewer(tableTreeViewer);
+ }
+
+ if (editorPart instanceof XMLMultiPageEditorPart) {
+ IWorkbenchPartSite site = editorPart.getSite();
+ if (site instanceof IEditorSite) {
+ ITextEditor textEditor = ((XMLMultiPageEditorPart) editorPart).getTextEditor();
+ IActionBars actionBars = ((IEditorSite) site).getActionBars();
+ actionBars.setGlobalActionHandler(ITextEditorActionConstants.UNDO, getAction(textEditor, ITextEditorActionConstants.UNDO));
+ actionBars.setGlobalActionHandler(ITextEditorActionConstants.REDO, getAction(textEditor, ITextEditorActionConstants.REDO));
+ }
+ }
+
+ // TODO... uncomment this and investigate NPE
+ //
+ // add the cut/copy/paste for text fields
+ // ActionHandlerPlugin.connectPart(editorPart);
+ }
+
+ protected final IAction getAction(ITextEditor editor, String actionId) {
+ return (editor == null ? null : editor.getAction(actionId));
+ }
+
+ protected IStructuredModel getModelForEditorPart(IEditorPart targetEditor) {
+ IStructuredModel result = null;
+ if (editorPart instanceof XMLMultiPageEditorPart) {
+ StructuredTextEditor textEditor = ((XMLMultiPageEditorPart) targetEditor).getTextEditor();
+ result = (textEditor != null) ? textEditor.getModel() : null;
+ }
+ return result;
+ }
+
+ protected XMLTableTreeViewer getTableTreeViewerForEditorPart(IEditorPart targetEditor) {
+ XMLTableTreeViewer result = null;
+ Object object = targetEditor.getAdapter(IDesignViewer.class);
+ if (object instanceof XMLTableTreeViewer) {
+ result = (XMLTableTreeViewer) object;
+ }
+ return result;
+ }
+
+ /**
+ *
+ */
+ public class ToggleEditModeAction extends Action {
+ protected ImageDescriptor onImage = SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_ETOOL_CONSTRAINON);
+ protected ImageDescriptor offImage = SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_ETOOL_CONSTRAINOFF);
+ protected ModelQuery modelQuery;
+
+ public ToggleEditModeAction() {
+ setAppearanceForEditMode(ModelQuery.EDIT_MODE_CONSTRAINED_STRICT);
+ }
+
+ public void run() {
+ if (modelQuery != null) {
+ int newState = getNextState(modelQuery.getEditMode());
+ modelQuery.setEditMode(newState);
+ setAppearanceForEditMode(newState);
+ }
+ }
+
+ public void setModelQuery(ModelQuery newModelQuery) {
+ modelQuery = newModelQuery;
+ if (modelQuery != null) {
+ setAppearanceForEditMode(modelQuery.getEditMode());
+ }
+ }
+
+ public void setAppearanceForEditMode(int editMode) {
+ if (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) {
+ setToolTipText(ResourceHandler.getString("XMLTableTreeActionBarContributor.3")); //$NON-NLS-1$
+ setText(ResourceHandler.getString("XMLTableTreeActionBarContributor.4")); //$NON-NLS-1$
+ setImageDescriptor(onImage);
+ } else {
+ setToolTipText(ResourceHandler.getString("XMLTableTreeActionBarContributor.5")); //$NON-NLS-1$
+ setText(ResourceHandler.getString("XMLTableTreeActionBarContributor.6")); //$NON-NLS-1$
+ setImageDescriptor(offImage);
+ }
+ }
+
+ public int getNextState(int editMode) {
+ int result = -1;
+ if (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) {
+ result = ModelQuery.EDIT_MODE_UNCONSTRAINED;
+ } else {
+ result = ModelQuery.EDIT_MODE_CONSTRAINED_STRICT;
+ }
+ return result;
+ }
+ }
+
+ /**
+ *
+ */
+ public class ReloadGrammarAction extends Action {
+ protected IStructuredModel model;
+
+ public ReloadGrammarAction() {
+ setDisabledImageDescriptor(SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_DTOOL_RLDGRMR));
+ setImageDescriptor(SharedXMLEditorPluginImageHelper.getImageDescriptor(SharedXMLEditorPluginImageHelper.IMG_ETOOL_RLDGRMR));
+ setToolTipText(ResourceHandler.getString("XMLTableTreeActionBarContributor.7")); //$NON-NLS-1$
+ setText(ResourceHandler.getString("XMLTableTreeActionBarContributor.8")); //$NON-NLS-1$
+ }
+
+ public void setModel(IStructuredModel newModel) {
+ this.model = newModel;
+ }
+
+ public void run() {
+ if (model != null) {
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(model);
+ Document document = ((XMLModel) model).getDocument();
+ if (modelQuery != null && modelQuery.getCMDocumentManager() != null) {
+ modelQuery.getCMDocumentManager().getCMDocumentCache().clear();
+ // TODO... need to figure out how to access the
+ // DOMObserver via ModelQuery
+ // ...why?
+ CMDocumentLoader loader = new InferredGrammarBuildingCMDocumentLoader(document, modelQuery);
+ loader.loadCMDocuments();
+ }
+ }
+ }
+ }
+
+ /**
+ * @see IEditorActionBarContributor#dispose()
+ */
+ public void dispose() {
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeContentProvider.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeContentProvider.java
new file mode 100644
index 0000000000..7255aaa7e2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeContentProvider.java
@@ -0,0 +1,367 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.wst.common.contentmodel.CMDocument;
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManagerListener;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.sse.core.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.Logger;
+import org.eclipse.wst.xml.ui.util.SharedXMLEditorPluginImageHelper;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+
+
+public class XMLTableTreeContentProvider implements ITreeContentProvider, ITableLabelProvider, ILabelProvider, CMDocumentManagerListener {
+
+ protected ViewerNotifyingAdapterFactory viewerNotifyingAdapterFactory = new ViewerNotifyingAdapterFactory();
+ protected XMLTableTreePropertyDescriptorFactory propertyDescriptorFactory;
+ // protected ImageFactory imageFactory =
+ // XMLCommonUIPlugin.getInstance().getImageFactory();
+ protected List viewerList = new Vector();
+ protected TreeContentHelper treeContentHelper = new TreeContentHelper();
+
+ protected CMDocumentManager documentManager;
+
+ public XMLTableTreeContentProvider() {
+ }
+
+ public void getDecendantList(Object element, List list) {
+ Object[] children = getChildren(element);
+ if (children != null) {
+ for (int i = 0; i < children.length; i++) {
+ Object child = children[i];
+ list.add(child);
+ getDecendantList(child, list);
+ }
+ }
+ }
+
+ public void addViewer(Viewer viewer) {
+ viewerList.add(viewer);
+ }
+
+ public Object[] getChildren(Object element) {
+ viewerNotifyingAdapterFactory.doAdapt(element);
+ return treeContentHelper.getChildren(element);
+ }
+
+ public Object getParent(Object o) {
+ Object result = null;
+ if (o instanceof Node) {
+ Node node = (Node) o;
+ if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ result = ((Attr) node).getOwnerElement();
+ } else {
+ result = node.getParentNode();
+ }
+ }
+ return result;
+ }
+
+ public boolean hasChildren(Object element) {
+ viewerNotifyingAdapterFactory.doAdapt(element);
+ return getChildren(element).length > 0;
+ }
+
+ public Object[] getElements(Object element) {
+ viewerNotifyingAdapterFactory.doAdapt(element);
+ return getChildren(element);
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // remove our listeners to the old state
+ if (oldInput != null) {
+ propertyDescriptorFactory = null;
+ Document domDoc = (Document) oldInput;
+ ModelQuery mq = ModelQueryUtil.getModelQuery(domDoc);
+ if (mq != null) {
+ documentManager = mq.getCMDocumentManager();
+ if (documentManager != null) {
+ documentManager.removeListener(this);
+ }
+ }
+ }
+
+ if (newInput != null) {
+ Document domDoc = (Document) newInput;
+ ModelQuery mq = ModelQueryUtil.getModelQuery(domDoc);
+
+ if (mq != null) {
+ propertyDescriptorFactory = new XMLTableTreePropertyDescriptorFactory(mq);
+ documentManager = mq.getCMDocumentManager();
+ if (documentManager != null) {
+ documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, true);
+ documentManager.addListener(this);
+ }
+ }
+ }
+ }
+
+ public boolean isDeleted(Object element) {
+ return element != null;
+ }
+
+ //
+ // ILabelProvider stuff
+ //
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ public void dispose() {
+ viewerList = new Vector();
+ }
+
+ public Element getRootElement(Document document) {
+ Element rootElement = null;
+
+ for (Node childNode = document.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()) {
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+ rootElement = (Element) childNode;
+ break;
+ }
+ }
+ return rootElement;
+ }
+
+ public Image getImage(Object object) {
+ viewerNotifyingAdapterFactory.doAdapt(object);
+ Image image = null;
+ if (object instanceof Node) {
+ Node node = (Node) object;
+ switch (node.getNodeType()) {
+ case Node.ATTRIBUTE_NODE : {
+ image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_ATTRIBUTE);
+ break;
+ }
+ case Node.CDATA_SECTION_NODE : {
+ image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_CDATASECTION);
+ break;
+ }
+ case Node.COMMENT_NODE : {
+ image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_COMMENT);
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE : {
+ image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_DOCTYPE);
+ break;
+ }
+ case Node.ELEMENT_NODE : {
+ image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_ELEMENT);
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_PROCESSINGINSTRUCTION);
+ break;
+ }
+ case Node.TEXT_NODE : {
+ image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_TXTEXT);
+ break;
+ }
+ case Node.ENTITY_REFERENCE_NODE : {
+ image = image = SharedXMLEditorPluginImageHelper.getImage(SharedXMLEditorPluginImageHelper.IMG_OBJ_ENTITY_REFERENCE);
+ break;
+ }
+ }
+
+ // if (image != null) {
+ // Image markerOverlayImage =
+ // overlayIconManager.getOverlayImageForObject(node);
+ // if (markerOverlayImage != null) {
+ // image = imageFactory.createCompositeImage(image,
+ // markerOverlayImage, ImageFactory.BOTTOM_LEFT);
+ // }
+ // }
+ }
+ return image;
+ }
+
+ public String getText(Object object) {
+ viewerNotifyingAdapterFactory.doAdapt(object);
+ String result = null;
+ if (object instanceof Node) {
+ Node node = (Node) object;
+ switch (node.getNodeType()) {
+ case Node.ATTRIBUTE_NODE : {
+ result = node.getNodeName();
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE : {
+ result = "DOCTYPE"; //$NON-NLS-1$
+ break;
+ }
+ case Node.ELEMENT_NODE : {
+ result = node.getNodeName();
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ result = ((ProcessingInstruction) node).getTarget();
+ break;
+ }
+ }
+ }
+ return result != null ? result : ""; //$NON-NLS-1$
+ }
+
+ //
+ // ITableLabelProvider stuff
+ //
+ public String getColumnText(Object object, int column) {
+ viewerNotifyingAdapterFactory.doAdapt(object);
+ String result = null;
+ if (column == 0) {
+ result = getText(object);
+ } else if (column == 1 && object instanceof Node) {
+ result = treeContentHelper.getNodeValue((Node) object);
+ }
+ return result != null ? result : ""; //$NON-NLS-1$
+ }
+
+ public Image getColumnImage(Object object, int columnIndex) {
+ viewerNotifyingAdapterFactory.doAdapt(object);
+ return (columnIndex == 0) ? getImage(object) : null;
+ }
+
+ public boolean isLabelProperty(Object object, String property) {
+ return false;
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ // There is only 1 adapter associated with this factory. This single
+ // adapter gets added
+ // to the adapter lists of many nodes.
+ public class ViewerNotifyingAdapterFactory extends AbstractAdapterFactory {
+ protected ViewerNotifyingAdapter viewerNotifyingAdapter = new ViewerNotifyingAdapter();
+
+ protected INodeAdapter createAdapter(INodeNotifier target) {
+ return viewerNotifyingAdapter;
+ }
+
+ protected ViewerNotifyingAdapter doAdapt(Object object) {
+ ViewerNotifyingAdapter result = null;
+ if (object instanceof INodeNotifier) {
+ result = (ViewerNotifyingAdapter) adapt((INodeNotifier) object);
+ }
+ return result;
+ }
+ }
+
+ public class ViewerNotifyingAdapter implements INodeAdapter {
+ public boolean isAdapterForType(Object type) {
+ return type.equals(viewerNotifyingAdapterFactory);
+ }
+
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ switch (eventType) {
+ //case INodeNotifier.ADD: // ignore
+ //case INodeNotifier.REMOVE: // ignore
+ case INodeNotifier.CHANGE :
+ case INodeNotifier.STRUCTURE_CHANGED :
+ case INodeNotifier.CONTENT_CHANGED : {
+ Node node = (Node) notifier;
+ if (node.getNodeType() == Node.ELEMENT_NODE || node.getNodeType() == Node.DOCUMENT_NODE) {
+ for (Iterator i = viewerList.iterator(); i.hasNext();) {
+ Viewer viewer = (Viewer) i.next();
+
+ if (viewer instanceof StructuredViewer) {
+ ((StructuredViewer) viewer).refresh(node);
+ } else {
+ // todo... consider doing a time delayed
+ // refresh here!!
+ viewer.refresh();
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // the following methods handle filtering aspects of the viewer
+ //
+ //
+ public boolean isIgnorableText(Node node) {
+ boolean result = false;
+ try {
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ String data = ((Text) node).getData();
+ result = (data == null || data.trim().length() == 0);
+ }
+ } catch (Exception e) {
+ Logger.logException(e);
+ }
+ return result;
+ }
+
+ public static Text getHiddenChildTextNode(Node node) {
+ return null;
+ }
+
+ // CMDocumentManagerListener
+ //
+ public void cacheCleared(CMDocumentCache cache) {
+ doDelayedRefreshForViewers();
+ }
+
+ public void cacheUpdated(CMDocumentCache cache, final String uri, int oldStatus, int newStatus, CMDocument cmDocument) {
+ if (newStatus == CMDocumentCache.STATUS_LOADED || newStatus == CMDocumentCache.STATUS_ERROR) {
+ doDelayedRefreshForViewers();
+ }
+ }
+
+ public void propertyChanged(CMDocumentManager cmDocumentManager, String propertyName) {
+ if (cmDocumentManager.getPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD)) {
+ doDelayedRefreshForViewers();
+ }
+ }
+
+ protected void doDelayedRefreshForViewers() {
+ List list = new Vector();
+ list.addAll(viewerList);
+
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ final Viewer viewer = (Viewer) i.next();
+ Control control = viewer.getControl();
+ Runnable runnable = new Runnable() {
+ public void run() {
+ viewer.refresh();
+ }
+ };
+ // we need to ensure that this is run via 'asyncExec' since these
+ // notifications can come from a non-ui thread
+ control.getDisplay().asyncExec(runnable);
+ }
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeHelpContextIds.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeHelpContextIds.java
new file mode 100644
index 0000000000..7f2730e9d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeHelpContextIds.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+
+
+/**
+ * Help context ids for the TableTree view.
+ * <p>
+ * This interface contains constants only; it is not intended to be
+ * implemented or extended.
+ * </p>
+ *
+ */
+public interface XMLTableTreeHelpContextIds {
+
+ public static final String PREFIX = "com.ibm.etools.sed.tabletree."; //$NON-NLS-1$
+
+ // XML Design View
+ public static final String XML_DESIGN_VIEW_HELPID = PREFIX + "xmlm3000"; //$NON-NLS-1$
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreePropertyDescriptorFactory.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreePropertyDescriptorFactory.java
new file mode 100644
index 0000000000..65fe7554f7
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreePropertyDescriptorFactory.java
@@ -0,0 +1,97 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+import java.util.List;
+
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.TextPropertyDescriptor;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.ui.views.properties.EnumeratedStringPropertyDescriptor;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+
+public class XMLTableTreePropertyDescriptorFactory extends DOMPropertyDescriptorFactory {
+
+ protected TreeContentHelper treeContentHelper = new TreeContentHelper();
+
+ public XMLTableTreePropertyDescriptorFactory(ModelQuery modelQuery) {
+ super(modelQuery);
+ }
+
+ protected IPropertyDescriptor createPropertyDescriptorHelper(String name, Element element, CMNode cmNode) {
+ IPropertyDescriptor result = null;
+
+ String[] valuesArray = getModelQuery().getPossibleDataTypeValues(element, cmNode);
+ if (valuesArray != null && valuesArray.length > 0) {
+ result = new EnumeratedStringPropertyDescriptor(name, name, valuesArray);
+ }
+
+ return result;
+ }
+
+ public IPropertyDescriptor createTextPropertyDescriptor(Text text) {
+ IPropertyDescriptor result = null;
+ Node parentNode = text.getParentNode();
+ if (parentNode != null && parentNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element parentElement = (Element) parentNode;
+ CMElementDeclaration ed = getModelQuery().getCMElementDeclaration(parentElement);
+ if (ed != null) {
+ result = createPropertyDescriptorHelper(HACK, parentElement, ed);
+ }
+ }
+
+ if (result == null) {
+ result = new TextPropertyDescriptor(HACK, HACK);
+ }
+
+ return result;
+ }
+
+ public IPropertyDescriptor createAttributePropertyDescriptor(Attr attr) {
+ IPropertyDescriptor result = null;
+
+ String attributeName = attr.getName();
+
+ CMAttributeDeclaration ad = getModelQuery().getCMAttributeDeclaration(attr);
+ if (ad != null) {
+ result = createPropertyDescriptorHelper(attributeName, attr.getOwnerElement(), ad);
+ }
+
+ if (result == null) {
+ result = new TextPropertyDescriptor(attributeName, attributeName);
+ }
+
+ return result;
+ }
+
+ public IPropertyDescriptor createElementPropertyDescriptor(Element element) {
+ IPropertyDescriptor result = null;
+ List list = treeContentHelper.getElementTextContent(element);
+ if (list != null) {
+ Text text = treeContentHelper.getEffectiveTextNodeForCombinedNodeList(list);
+ if (text != null) {
+ result = createTextPropertyDescriptor(text);
+ }
+ }
+
+ if (result == null) {
+ result = new TextPropertyDescriptor(HACK, HACK);
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java
new file mode 100644
index 0000000000..271fb80c06
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java
@@ -0,0 +1,334 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+import java.util.List;
+
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.core.IModelStateListener;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.ui.ViewerSelectionManager;
+import org.eclipse.wst.sse.ui.view.events.INodeSelectionListener;
+import org.eclipse.wst.sse.ui.view.events.NodeSelectionChangedEvent;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.internal.ui.IDesignViewer;
+import org.eclipse.wst.xml.ui.actions.NodeAction;
+import org.eclipse.wst.xml.ui.dnd.XMLDragAndDropManager;
+import org.eclipse.wst.xml.ui.nls2.ResourceHandler;
+import org.eclipse.wst.xml.ui.views.contentoutline.XMLNodeActionManager;
+import org.w3c.dom.Document;
+
+
+public class XMLTableTreeViewer extends TreeViewer implements IDesignViewer {
+
+ /**
+ * This class is used to improve source editing performance by coalescing
+ * multiple notifications for an element change into a single refresh
+ */
+ class DelayedRefreshTimer implements Runnable {
+ private final int delta = 2000;
+ protected Object objectPendingRefresh;
+ protected ISelection pendingSelection;
+ protected Object prevObject;
+ protected XMLTableTreeViewer viewer;
+
+ public DelayedRefreshTimer(XMLTableTreeViewer viewer) {
+ this.viewer = viewer;
+ }
+
+ public boolean isRefreshPending() {
+ return objectPendingRefresh != null;
+ }
+
+ public void refresh(Object object) {
+ if (prevObject == object) {
+ objectPendingRefresh = object;
+ getDisplay().timerExec(delta, this);
+ } else {
+ if (objectPendingRefresh != null) {
+ viewer.doRefresh(objectPendingRefresh, false);
+ objectPendingRefresh = null;
+ }
+ viewer.doRefresh(object, false);
+ }
+ prevObject = object;
+ }
+
+ private Display getDisplay() {
+
+ return PlatformUI.getWorkbench().getDisplay();
+ }
+
+ public void run() {
+ // defect 239677 ensure that the viewer's control is not disposed
+ //
+ if (objectPendingRefresh != null && !viewer.getTree().isDisposed()) {
+ viewer.doRefresh(objectPendingRefresh, true);
+ if (pendingSelection != null) {
+ // see fireSelectionChanged comment about jumping cursor
+ // problem
+ //
+ viewer.setSelection(pendingSelection, true);
+ pendingSelection = null;
+ }
+ objectPendingRefresh = null;
+ prevObject = null;
+ }
+ }
+
+ public void setSelection(ISelection selection) {
+ pendingSelection = selection;
+ }
+ }
+
+ class DelayingNodeSelectionListener implements INodeSelectionListener {
+ public void nodeSelectionChanged(NodeSelectionChangedEvent event) {
+ // if (isNodeSelectionListenerEnabled &&
+ // !event.getSource().equals(this)) {
+ if (!event.getSource().equals(XMLTableTreeViewer.this)) {
+ List selectedNodes = event.getSelectedNodes();
+ ISelection selection = new StructuredSelection(selectedNodes);
+
+ // for performance purposes avoid large multi-selections
+ //
+ if (selectedNodes.size() < 100) {
+ if (timer.isRefreshPending()) {
+ timer.setSelection(selection);
+ } else {
+ setSelection(selection, true);
+ }
+ }
+ }
+ }
+ }
+
+ class InternalModelStateListener implements IModelStateListener {
+
+ public void modelAboutToBeChanged(IStructuredModel model) {
+ ignoreRefresh = true;
+ }
+
+ public void modelChanged(IStructuredModel model) {
+ ignoreRefresh = false;
+ refresh();
+ }
+
+ public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
+ }
+
+ public void modelResourceDeleted(IStructuredModel model) {
+ }
+
+ public void modelResourceMoved(IStructuredModel originalmodel, IStructuredModel movedmodel) {
+ }
+ }
+
+ class NodeActionMenuListener implements IMenuListener {
+ public void menuAboutToShow(IMenuManager menuManager) {
+ // used to disable NodeSelection listening while running
+ // NodeAction
+ XMLNodeActionManager nodeActionManager = new XMLNodeActionManager(fModel, XMLTableTreeViewer.this) {
+ public void beginNodeAction(NodeAction action) {
+ super.beginNodeAction(action);
+ }
+
+ public void endNodeAction(NodeAction action) {
+ super.endNodeAction(action);
+ }
+ };
+ nodeActionManager.fillContextMenu(menuManager, getSelection());
+ }
+ }
+
+ protected CellEditor cellEditor;
+
+ int count = 0;
+
+ protected IModelStateListener fInternalModelStateListener = new InternalModelStateListener();
+ protected IStructuredModel fModel = null;
+ protected INodeSelectionListener fNodeSelectionListener;
+
+ protected ViewerSelectionManager fViewerSelectionManager;
+
+ protected boolean ignoreRefresh;
+
+ protected DelayedRefreshTimer timer;
+ protected XMLTreeExtension treeExtension;
+
+ public XMLTableTreeViewer(Composite parent) {
+ super(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+
+ // set up providers
+ this.treeExtension = new XMLTreeExtension(getTree());
+
+ XMLTableTreeContentProvider provider = new XMLTableTreeContentProvider();
+ provider.addViewer(this);
+ setContentProvider(provider);
+ setLabelProvider(provider);
+
+ createContextMenu();
+
+ XMLDragAndDropManager.addDragAndDropSupport(this);
+ timer = new DelayedRefreshTimer(this);
+ }
+
+ /**
+ * This creates a context menu for the viewer and adds a listener as well
+ * registering the menu for extension.
+ */
+ protected void createContextMenu() {
+ MenuManager contextMenu = new MenuManager("#PopUp"); //$NON-NLS-1$
+ contextMenu.add(new Separator("additions")); //$NON-NLS-1$
+ contextMenu.setRemoveAllWhenShown(true);
+ contextMenu.addMenuListener(new NodeActionMenuListener());
+ Menu menu = contextMenu.createContextMenu(getControl());
+ getControl().setMenu(menu);
+ }
+
+ protected void doRefresh(Object o, boolean fromDelayed) {
+ treeExtension.resetCachedData();
+ super.refresh(o);
+ }
+
+ protected void fireSelectionChanged(SelectionChangedEvent event) {
+ if (!getTree().isDisposed() && !getTree().isFocusControl()) {
+ // defect 246094
+ // Various jumping cursor problems are caused when a selection
+ // 'delayed' selection occurs.
+ // These delayed selections are caused two ways:
+ //
+ // - when DelayedRefreshTimer calls doRefresh() ... the
+ // 'preserveSelection' causes selection to occur
+ // - when DelayedRefreshTimer performs a 'pending' selection
+ //
+ // Since we only want to update the selectionManager on an explict
+ // user action
+ // (and not some selection that is merely a resonse to the
+ // selection manager)
+ // we ensure that the tree has focus control before firing events
+ // to the selectionManager.
+ //
+ removeSelectionChangedListener(fViewerSelectionManager);
+ super.fireSelectionChanged(event);
+ addSelectionChangedListener(fViewerSelectionManager);
+ } else {
+ super.fireSelectionChanged(event);
+ }
+ }
+
+ /**
+ * @return
+ */
+ public INodeSelectionListener getNodeSelectionListener() {
+ if (fNodeSelectionListener == null)
+ fNodeSelectionListener = new DelayingNodeSelectionListener();
+ return fNodeSelectionListener;
+ }
+
+ public String getTitle() {
+ return ResourceHandler.getString("XMLTableTreeViewer.0"); //$NON-NLS-1$
+ }
+
+ protected void handleDispose(DisposeEvent event) {
+ super.handleDispose(event);
+ treeExtension.dispose();
+ setModel(null);
+ setViewerSelectionManager(null);
+
+ // if (fViewerSelectionManager != null) {
+ // fViewerSelectionManager.removeNodeSelectionListener(getNodeSelectionListener());
+ // }
+ //
+ // fOverlayIconManager.setResource(null);
+ // super.handleDispose(event);
+ //
+ // if (fModel != null)
+ // fModel.removeModelStateListener(fInternalModelStateListener);
+ }
+
+ public void refresh() {
+ if (!ignoreRefresh && !getControl().isDisposed()) {
+ treeExtension.resetCachedData();
+ super.refresh();
+
+ // if (B2BHacks.IS_UNIX) {
+ // this is required to fix defect 193792
+ // this fixes the problem where the 'paintHandler'drawn portions
+ // of tree weren't repainted properly
+ //
+ getTree().redraw(0, 0, getTree().getBounds().width, getTree().getBounds().height, false);
+ getTree().update();
+ // }
+ }
+ }
+
+ public void refresh(Object o) {
+ if (!ignoreRefresh && !getControl().isDisposed() && timer != null) {
+ if (getTree().isVisible()) {
+ doRefresh(o, false);
+ } else {
+ timer.refresh(o);
+ }
+ }
+ }
+
+ public void setModel(IStructuredModel model) {
+ // remove
+ if (fModel != null) {
+ fModel.removeModelStateListener(fInternalModelStateListener);
+ }
+
+ fModel = model;
+ Document domDoc = null;
+
+ if (fModel != null && fModel instanceof XMLModel) {
+ model.addModelStateListener(fInternalModelStateListener);
+ ModelQuery mq = ModelQueryUtil.getModelQuery(model);
+ treeExtension.setModelQuery(mq);
+ domDoc = ((XMLModel) fModel).getDocument();
+ setInput(domDoc);
+ }
+ }
+
+ // the following methods implement the IDesignViewer interface
+ // - getControl() is implemented via AdvancedTableTreeViewer
+ //
+ public void setViewerSelectionManager(ViewerSelectionManager viewerSelectionManager) {
+ // disconnect from old one
+ if (fViewerSelectionManager != null) {
+ fViewerSelectionManager.removeNodeSelectionListener(getNodeSelectionListener());
+ removeSelectionChangedListener(fViewerSelectionManager);
+ }
+
+ fViewerSelectionManager = viewerSelectionManager;
+
+ // connect to new one
+ if (fViewerSelectionManager != null) {
+ fViewerSelectionManager.addNodeSelectionListener(getNodeSelectionListener());
+ addSelectionChangedListener(fViewerSelectionManager);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java
new file mode 100644
index 0000000000..f1b842d0eb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java
@@ -0,0 +1,184 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.util.CMDescriptionBuilder;
+import org.eclipse.wst.xml.ui.nls2.ResourceHandler;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+public class XMLTreeExtension extends TreeExtension {
+
+ public final static String STRUCTURE_PROPERTY = ResourceHandler.getString("XMLTreeExtension.0"); //$NON-NLS-1$
+ public final static String VALUE_PROPERTY = ResourceHandler.getString("XMLTreeExtension.1"); //$NON-NLS-1$
+
+ protected Composite control;
+ protected MyCellModifier modifier;
+ protected XMLTableTreePropertyDescriptorFactory propertyDescriptorFactory;
+ protected CMDescriptionBuilder decriptionBuilder = new CMDescriptionBuilder();
+ protected TreeContentHelper treeContentHelper = new TreeContentHelper();
+
+ protected Color f1, f2, b1, b2;
+ protected boolean cachedDataIsValid = true;
+ private ModelQuery fModelQuery;
+
+ public XMLTreeExtension(Tree tree) {
+ super(tree);
+ control = tree;
+ modifier = new MyCellModifier();
+ setCellModifier(modifier);
+ String[] properties = {STRUCTURE_PROPERTY, VALUE_PROPERTY};
+ setColumnProperties(properties);
+
+ f1 = tree.getDisplay().getSystemColor(SWT.COLOR_BLACK);
+ Color background = tree.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+
+ int r = Math.abs(background.getRed() - 125);
+ int g = Math.abs(background.getGreen() - 85);
+ int b = Math.abs(background.getBlue() - 105);
+
+ f2 = new Color(tree.getDisplay(), r, g, b);
+ b1 = tree.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+ b2 = background;
+ }
+
+ public void dispose() {
+ super.dispose();
+ f2.dispose();
+ }
+
+ public void resetCachedData() {
+ cachedDataIsValid = false;
+ }
+
+ public void paintItems(GC gc, TreeItem[] items, Rectangle treeBounds) {
+ super.paintItems(gc, items, treeBounds);
+ cachedDataIsValid = true;
+ }
+
+ protected Object[] computeTreeExtensionData(Object object) {
+ Color color = f1;
+ String string = ""; //$NON-NLS-1$
+ if (string.length() == 0) {
+ string = (String) modifier.getValue(object, VALUE_PROPERTY);
+ color = f1;
+ }
+ if (string.length() == 0 && object instanceof Element) {
+ string = getElementValueHelper((Element) object);
+ color = f2;
+ }
+ Object[] data = new Object[2];
+ data[0] = string;
+ data[1] = color;
+ return data;
+ }
+
+ protected void paintItem(GC gc, TreeItem item, Rectangle bounds) {
+ super.paintItem(gc, item, bounds);
+ Object[] data = computeTreeExtensionData(item.getData());
+ if (data != null && data.length == 2) {
+ gc.setClipping(columnPosition, bounds.y + 1, controlWidth, bounds.height);
+ gc.setForeground((Color) data[1]);
+ gc.drawString((String) data[0], columnPosition + 5, bounds.y + 1);
+ gc.setClipping((Rectangle) null);
+ }
+ }
+
+ protected void addEmptyTreeMessage(GC gc) {
+ // here we print a message when the document is empty just to give the
+ // user a visual cue
+ // so that they know how to proceed to edit the blank view
+ gc.setForeground(tree.getDisplay().getSystemColor(SWT.COLOR_BLACK));
+ gc.setBackground(tree.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+ gc.drawString(ResourceHandler.getString("XMLTreeExtension.3"), 10, 10); //$NON-NLS-1$
+ gc.drawString(ResourceHandler.getString("XMLTreeExtension.4"), 10, 10 + gc.getFontMetrics().getHeight()); //$NON-NLS-1$
+ }
+
+ public String getElementValueHelper(Element element) {
+ String result = null;
+
+ if (result == null && getModelQuery() != null) {
+ CMElementDeclaration ed = getModelQuery().getCMElementDeclaration(element);
+ if (ed != null && !Boolean.TRUE.equals(ed.getProperty("isInferred"))) { //$NON-NLS-1$
+ result = decriptionBuilder.buildDescription(ed);
+ }
+ }
+ return result != null ? result : ""; //$NON-NLS-1$
+ }
+
+ /**
+ *
+ */
+ public class MyCellModifier implements ICellModifier, TreeExtension.ICellEditorProvider {
+ public boolean canModify(Object element, String property) {
+ boolean result = false;
+ if (element instanceof Node) {
+ Node node = (Node) element;
+ result = property == VALUE_PROPERTY && treeContentHelper.isEditable(node);
+ }
+ return result;
+ }
+
+ public Object getValue(Object object, String property) {
+ String result = null;
+ if (object instanceof Node) {
+ result = treeContentHelper.getNodeValue((Node) object);
+ }
+ return (result != null) ? result : ""; //$NON-NLS-1$
+ }
+
+ public void modify(Object element, String property, Object value) {
+ //enableNodeSelectionListener(false);
+ Item item = (Item) element;
+ String oldValue = treeContentHelper.getNodeValue((Node) item.getData());
+ String newValue = value.toString();
+ if (newValue != null && !newValue.equals(oldValue)) {
+ treeContentHelper.setNodeValue((Node) item.getData(), value.toString());
+ }
+ //enableNodeSelectionListener(true);
+ }
+
+ public CellEditor getCellEditor(Object o, int col) {
+ IPropertyDescriptor pd = propertyDescriptorFactory.createPropertyDescriptor(o);
+ return pd != null ? pd.createPropertyEditor(control) : null;
+ }
+ }
+
+ /**
+ * @return
+ */
+ public ModelQuery getModelQuery() {
+ return fModelQuery;
+ }
+
+ /**
+ * @param query
+ */
+ public void setModelQuery(ModelQuery query) {
+ fModelQuery = query;
+ propertyDescriptorFactory = new XMLTableTreePropertyDescriptorFactory(query);
+ }
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/nls2/ResourceHandler.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/nls2/ResourceHandler.java
new file mode 100644
index 0000000000..1eae6c1f6e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/nls2/ResourceHandler.java
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * Copyright (c) 2004 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.wst.xml.ui.nls2;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class ResourceHandler {
+
+
+ private static ResourceBundle fgResourceBundle;
+
+ /**
+ * Returns the resource bundle used by all classes in this Project
+ */
+ public static ResourceBundle getResourceBundle() {
+ try {
+ return ResourceBundle.getBundle("xmleditor");//$NON-NLS-1$
+ } catch (MissingResourceException e) {
+ // does nothing - this method will return null and
+ // getString(String) will return the key
+ // it was called with
+ }
+ return null;
+ }
+
+ public static String getString(String key) {
+ if (fgResourceBundle == null) {
+ fgResourceBundle = getResourceBundle();
+ }
+
+ if (fgResourceBundle != null) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$//$NON-NLS-1$
+ }
+ } else {
+ return "!" + key + "!";//$NON-NLS-2$//$NON-NLS-1$
+ }
+ }
+
+ public static String getString(String key, Object[] args) {
+
+ try {
+ return MessageFormat.format(getString(key), args);
+ } catch (IllegalArgumentException e) {
+ return getString(key);
+ }
+
+ }
+
+ public static String getString(String key, Object[] args, int x) {
+
+ return getString(key);
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.wst.xml.ui/src/EditingXML.properties b/bundles/org.eclipse.wst.xml.ui/src/EditingXML.properties
new file mode 100644
index 0000000000..8371547a7e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/EditingXML.properties
@@ -0,0 +1,230 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+## The following line is a sample XML document. Please translate only the following parts:
+## begin color definitions
+## Normal text content.
+Sample_XML_doc=<?xml version=\"1.0\"?>\n<?customProcessingInstruction\n\tXML processor specific\n\tcontent ?>\n<!DOCTYPE colors\n\tPUBLIC \"//IBM/XML/COLORS/\" \"colors.dtd\">\n<colors>\n\t<!-- begin color definitions -->\n\t<color name=\"plaintext\" foreground=\"#000000\"\n\t\tbackground=\"#D4D0C8\" />\n\t<color name=\"bold\" foreground=\"#000000\"\n\t\tbackground=\"#B3ACA0\" />\n\t<![CDATA[<123456789>]]>\n\tNormal text content.\n\t<color name=\"inverse\" foreground=\"#F0F0F0\"\n\t\tbackground=\"#D4D0C8\" />\n\n</colors>\n
+Comment_Delimiters_UI_=Comment Delimiters
+Comment_Content_UI_=Comment Content
+Tag_Delimiters_UI_=Tag Delimiters
+Tag_Names_UI_=Tag Names
+Attribute_Names_UI_=Attribute Names
+Attribute_Values_UI_=Attribute Values
+Declaration_Delimiters_UI_=Declaration Delimiters
+Content_UI_=Content
+## on the following 2 lines, do not translate CDATA
+CDATA_Delimiters_UI_=CDATA Delimiters
+CDATA_Content_UI_=CDATA Content
+Processing_Instruction_Del_UI_=Processing Instruction Delimiters
+Processing_Instruction_Con_UI__UI_=Processing Instruction Content
+## on the following line solely translate: Name
+DOCTYPE_Name_UI_=DOCTYPE Name
+## on the following line solely translate: Keyword
+DOCTYPE_SYSTEM/PUBLIC_Keyw_UI_=DOCTYPE SYSTEM/PUBLIC Keyword
+## on the following line solely translate: Public Reference
+DOCTYPE_Public_Reference_UI_=DOCTYPE Public Reference
+## on the following line solely translate: System Reference
+DOCTYPE_System_Reference_UI_=DOCTYPE System Reference
+# XML Common UI
+# Constants for strings
+
+NEW=New
+DELETE=Remove
+ADD_TEXT=Add Text
+ADD_CDATA_SECTION=Add CDATA Section
+ADD_COMMENT=Add Commen&t
+ADD_PROCESSING_INSTRUCTION=Add Processing Instruction
+
+_UI_MENU_ADD_AFTER=Add &After
+_UI_MENU_ADD_ATTRIBUTE=Add A&ttribute
+_UI_MENU_ADD_BEFORE=Add &Before
+_UI_MENU_ADD_CHILD=Add &Child
+_UI_MENU_REMOVE=Re&move
+_UI_MENU_REPLACE_WITH=Re&place With
+_UI_MENU_ADD_DOCTYPE=Add DOCTYPE...
+_UI_MENU_EDIT_DOCTYPE=Edit DOCTYPE...
+_UI_MENU_ADD_GRAMMAR_INFORMATION=Add Grammar Information
+_UI_MENU_VALIDATE_XML=Validate XML File
+_UI_LABEL_UNDO_ADD_DESCRIPTION=Add
+_UI_LABEL_UNDO_REPLACE_DESCRIPTION=Replace
+_UI_LABEL_EDIT_DOCTYPE=Edit DOCTYPE
+_UI_INFO_EXPAND_ALL=IWAK0108I Expand All
+_UI_INFO_COLLAPSE_ALL=IWAK0109I Collapse All
+
+_UI_MENU_ADD_DTD_INFORMATION=Add DTD Information...
+_UI_MENU_ADD_SCHEMA_INFORMATION=Add Schema Information...
+_UI_MENU_EDIT_SCHEMA_INFORMATION=Edit &Schema Information...
+_UI_MENU_EDIT_PROCESSING_INSTRUCTION=Edit Process&ing Instruction...
+_UI_MENU_EDIT_NAMESPACES=Edit &Namespaces...
+
+_UI_MENU_ADD_DTD_INFORMATION_TITLE=Add DTD Information
+_UI_MENU_EDIT_PROCESSING_INSTRUCTION_TITLE=Edit Processing Instruction
+_UI_MENU_EDIT_SCHEMA_INFORMATION_TITLE=Edit Schema Information
+
+_UI_MENU_NEW_ATTRIBUTE=&New Attribute...
+_UI_MENU_NEW_ATTRIBUTE_TITLE=New Attribute
+_UI_MENU_EDIT_ATTRIBUTE=Edit Attribute...
+_UI_MENU_EDIT_ATTRIBUTE_TITLE=Edit Attribute
+_UI_MENU_NEW_ELEMENT=New &Element...
+_UI_MENU_NEW_ELEMENT_TITLE=New Element
+_UI_MENU_RENAME=R&ename
+_UI_MENU_RENAME_TITLE=Rename
+_UI_LABEL_ELEMENT_NAME=Element name:
+_UI_LABEL_LOADING_GRAMMAR=Loading grammar:
+
+_UI_MENU_ADD_COMMENT=Add Comment
+_UI_MENU_ADD_PROCESSING_INSTRUCTION=Add Processing Instruction
+_UI_MENU_ADD_CDATA_SECTION=Add CDATA Section
+_UI_MENU_ADD_PCDATA=Add #PCDATA;
+
+_UI_MENU_COMMENT=C&omment
+_UI_MENU_PROCESSING_INSTRUCTION=P&rocessing Instruction
+_UI_MENU_CDATA_SECTION=CDATA Section
+_UI_MENU_PCDATA=#PC&DATA;
+
+_UI_MENU_ADD=Add
+
+_UI_COMMENT_VALUE=comment
+_UI_PI_TARGET_VALUE=target
+_UI_PI_DATA_VALUE=data
+_UI_LABEL_ROOT_ELEMENT_VALUE=RootElement
+
+_UI_LABEL_TARGET_COLON=Target:
+_UI_LABEL_DATA_COLON=Data:
+_UI_LABEL_ROOT_ELEMENT_NAME_COLON=Root element name:
+_UI_LABEL_PUBLIC_ID_COLON=Public ID:
+_UI_LABEL_SYSTEM_ID_COLON=System ID:
+_UI_LABEL_BROWSE=Browse...
+_UI_LABEL_SELECT_XML_CATALOG_ENTRY=Select XML Catalog Entry
+_UI_LABEL_SPECIFY_SYSTEM_ID=Specify System ID
+_UI_LABEL_SELECT_FILE=Select File
+
+_UI_LABEL_KEY=Key
+_UI_LABEL_URI=URI:
+_UI_LABEL_XML_CATALOG_COLON=XML Catalog
+_UI_LABEL_NAMESPACE_NAME=Namespace Name
+_UI_LABEL_LOCATION_HINT=Location Hint
+_UI_LABEL_PREFIX=Prefix
+_UI_LABEL_NAMESPACE_NAME_COLON=Namespace Name:
+_UI_LABEL_LOCATION_HINT_COLON=Location Hint:
+_UI_LABEL_PREFIX_COLON=Prefix:
+_UI_NO_NAMESPACE_NAME=<no namespace name>
+_UI_NO_PREFIX=<no prefix>
+
+_UI_LABEL_XML_SCHEMA_INFORMATION=XML Schema Information
+_UI_LABEL_NAMESPACE_INFORMATION=Namespace Information
+
+_UI_LABEL_NAME_COLON=Name:
+_UI_LABEL_VALUE_COLON=Value:
+
+_UI_BUTTON_DELETE=Delete
+_UI_BUTTON_NEW=New...
+_UI_BUTTON_EDIT=Edit...
+
+_UI_LABEL_NEW_NAMESPACE_INFORMATION=New Namespace Information
+_UI_LABEL_EDIT_NAMESPACE_INFORMATION=Edit Namespace Information
+
+#
+# Assign links to an XML file
+#
+_UI_WORK_BENCH=Workbench Files...
+_UI_FILE_SYSTEM=Import Files...
+_UI_ASSIGN_XSL=Assign An XSL Stylesheet To The XML File
+_UI_ASSIGN_DTD=Assign A DTD file To The XML File
+_UI_ASSIGN_XSD=Assign An XML schema To The XML File
+_UI_SELECT_XSL_TITLE=Select an XSL File
+_UI_SELECT_XSL_DESC=Select an XSL file from the workbench.
+
+_UI_ASSIGN=Assign
+_UI_XSD=XML Schema...
+_UI_DTD=DTD...
+_UI_XSL=XSL Stylesheet...
+
+# XMLValidator.java
+_UI_XML_VALIDATOR=XML Validator
+# SelectFileOrXMLCatalogIdPanel.java
+
+_UI_RADIO_BUTTON_SELECT_FROM_WORKSPACE=Select file from workbench
+_UI_RADIO_BUTTON_SELECT_FROM_CATALOG=Select XML Catalog entry
+
+_UI_WARNING_TITLE_ROOT_ELEMENT_REQUIRED=Root Element Required
+_UI_WARNING_DOCUMENT_REQUIRES_ROOT=The document requires a root element in order to add schema information.
+_UI_WARNING_MORE_THAN_ONE_NS_WITH_NAME=More than one namespace has been specified with the namespace name :
+_UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_NAME=More than one schema has been specified without a namespace name
+_UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_PREFIX=More than one namespace has been specificed without a prefix
+_UI_WARNING_MORE_THAN_ONE_NS_WITH_PREFIX=More than one namespace has been specified with the prefix :
+_UI_WARNING_SCHEMA_CAN_NOT_BE_LOCATED=The specified schema can not be located :
+_UI_WARNING_LOCATION_HINT_NOT_SPECIFIED=A location hint has not been specified for the namespace with name
+_UI_WARNING_NAMESPACE_NAME_NOT_SPECIFIED=A name must be specified for the namespace with prefix :
+_UI_WARNING_PREFIX_NOT_SPECIFIED=A prefix must be specified for the namespace named :
+_UI_WARNING_ROOT_ELEMENT_MUST_BE_SPECIFIED=A root element name must be specified.
+_UI_WARNING_SYSTEM_ID_MUST_BE_SPECIFIED=A system ID must be specified.
+
+_UI_INVALID_NAME=Invalid name
+
+# String used for editing namespaces (org.eclipse.wst.xml.ui.nsedit)
+_UI_ENTER_REQ_PREFIX_AND_NAMESPACE=Enter the required prefix and namespace URI for the namespace declaration.
+_UI_SELECT_REGISTERED_NAMESPACES=Select From Registered Namespaces
+_UI_SPECIFY_NEW_NAMESPACE=Specify New Namespace
+_UI_SELECT_NAMESPACE_TO_ADD=Select the namespace declarations to add.
+_UI_ADD_NAMESPACE_DECLARATIONS=Add Namespace Declarations
+_UI_NAMESPACE_DECLARATIONS=Namespace Declarations
+_UI_TARGET_NAMESPACE=Target Namespace
+
+
+#======================================================================================
+#
+# Here is the list of Error string that have message IDs - make sure they are unique
+# Range for XMLBuilder messageIDs: IWAX1601E - IWAX1800E
+# Since we'll be combing these plugins at some later point we'll use the same range
+# and be carefull not to clobber those defined in xmlbuilder's plugin.properties
+#======================================================================================
+_ERROR_XML_ATTRIBUTE_ALREADY_EXISTS=IWAK0110E The element already has an attribute with this name.
+
+#
+error_message_goes_here=error message goes here
+SurroundWithNewElementQuickAssistProposal.0=Surround with new element
+SurroundWithNewElementQuickAssistProposal.1=Surround with new element
+RenameInFileQuickAssistProposal.0=Link all references for a rename in file (does not change references in other files)
+RenameInFileQuickAssistProposal.1=Rename in file
+InsertRequiredAttrsQuickAssistProposal.0=Insert required attributes
+InsertRequiredAttrsQuickAssistProposal.1=Insert required attributes
+EncodingSettings.0=IANA:
+EncodingSettings.1=Encoding:
+TemplateContextTypeXMLTag.0=XML Tags
+TemplateContextTypeXMLAttributeValue.0=XML Attribute Values
+TemplateContextTypeXMLAttribute.0=XML Attributes
+TemplateContextTypeXML.0=All XML
+DragNodeCommand.0=Move
+CommonEditNamespacesDialog.0=Add...
+JFaceNodeAdapter.1=Refresh Property Sheet
+QuickFixProcessorXML.0=Remove empty tag
+QuickFixProcessorXML.1=Change to empty-element tag
+QuickFixProcessorXML.2=Remove this tag
+QuickFixProcessorXML.3=Insert end tag before first child element
+QuickFixProcessorXML.4=Insert end tag at end of element
+QuickFixProcessorXML.5=Remove attributes in end tag
+QuickFixProcessorXML.6=Insert default attribute value
+QuickFixProcessorXML.7=Remove this attribute
+QuickFixProcessorXML.8=Remove spaces before tag name
+QuickFixProcessorXML.9=Remove spaces before processing instruction
+QuickFixProcessorXML.10=Remove namespace in processing instruction
+QuickFixProcessorXML.11=Remove this element
+QuickFixProcessorXML.12=Remove this attribute value
+QuickFixProcessorXML.13=Insert required attribute
+QuickFixProcessorXML.14=Quote attribute value
+QuickFixProcessorXML.15=Insert closing bracket
+QuickFixProcessorXML.16=Remove this attribute and its value
+XMLPropertySourceAdapter.0=Attributes
+
+WorkbenchDefaultEncodingSettings.0=Use workbench encoding
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/DOMObserver.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/DOMObserver.java
new file mode 100644
index 0000000000..e94585515d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/DOMObserver.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui;
+
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.modelqueryimpl.CMDocumentLoader;
+import org.eclipse.wst.common.contentmodel.modelqueryimpl.InferredGrammarBuildingCMDocumentLoader;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * This class is used to observe changes in the DOM and perform
+ * occasional'scans' to deduce information. We use a delay timer mechanism to
+ * ensure scans are made every couple of seconds to avoid performance
+ * problems. Currently this class is used to keep track of referenced grammar
+ * uri's within the document ensure that they are loaded by the
+ * CMDocumentManager. We might want to generalize this class to perform other
+ * suplimental information gathering that is suitable for 'time delayed'
+ * computation (error hints etc.).
+ */
+// TODO: Where should this class go?
+public class DOMObserver {
+
+
+ // An abstract adapter that ensures that the children of a new Node are
+ // also adapted
+ //
+ abstract class DocumentAdapter implements INodeAdapter {
+ public DocumentAdapter(Document document) {
+ ((INodeNotifier) document).addAdapter(this);
+ adapt(document.getDocumentElement());
+ }
+
+ public void adapt(Element element) {
+ if (element != null) {
+ if (((INodeNotifier) element).getExistingAdapter(this) == null) {
+ ((INodeNotifier) element).addAdapter(this);
+
+ for (Node child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ adapt((Element) child);
+ }
+ }
+ }
+ }
+ }
+
+ public boolean isAdapterForType(Object type) {
+ return type == this;
+ }
+
+ abstract public void notifyChanged(INodeNotifier notifier, int eventType, Object feature, Object oldValue, Object newValue, int index);
+ }
+
+ /**
+ * This class listens to the changes in the CMDocument and triggers a
+ * CMDocument load
+ */
+ class MyDocumentAdapter extends DocumentAdapter {
+ MyDocumentAdapter(Document document) {
+ super(document);
+ }
+
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object feature, Object oldValue, Object newValue, int index) {
+ switch (eventType) {
+ case INodeNotifier.ADD : {
+ if (newValue instanceof Element) {
+ //System.out.println("ADD (to " +
+ // ((Node)notifier).getNodeName() + ") " +
+ // ((Element)newValue).getNodeName() + " old " +
+ // oldValue);
+ adapt((Element) newValue);
+ }
+ break;
+ }
+ //case INodeNotifier.REMOVE:
+ case INodeNotifier.CHANGE :
+ case INodeNotifier.STRUCTURE_CHANGED :
+ case INodeNotifier.CONTENT_CHANGED : {
+ Node node = (Node) notifier;
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ Element element = (Element) node;
+ switch (eventType) {
+ case INodeNotifier.CHANGE : {
+ invokeDelayedCMDocumentLoad();
+ break;
+ }
+ case INodeNotifier.STRUCTURE_CHANGED : {
+ // structure change
+ invokeDelayedCMDocumentLoad();
+ break;
+ }
+ case INodeNotifier.CONTENT_CHANGED : {
+ // some content changed
+ break;
+ }
+ }
+ } else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ invokeDelayedCMDocumentLoad();
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ //
+ protected class MyTimerTask extends TimerTask {
+ public MyTimerTask() {
+ super();
+ timerTaskCount++;
+ }
+
+ public void run() {
+ timerTaskCount--;
+ if (timerTaskCount == 0) {
+ invokeCMDocumentLoad();
+ }
+ }
+ }
+
+ protected static Timer timer = new Timer(true);
+ protected Document document;
+ protected boolean isGrammarInferenceEnabled;
+ protected IStructuredModel model;
+ protected int timerTaskCount = 0;
+
+ public DOMObserver(IStructuredModel model) {
+ this.document = (model instanceof XMLModel) ? ((XMLModel) model).getDocument() : null;
+
+ if (document != null) {
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+ if (modelQuery != null && modelQuery.getCMDocumentManager() != null) {
+ CMDocumentManager cmDocumentManager = modelQuery.getCMDocumentManager();
+ cmDocumentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, false);
+ }
+
+ MyDocumentAdapter myDocumentAdapter = new MyDocumentAdapter(document);
+ }
+ }
+
+ public void init() {
+ // CS: we seem to expose an XSD initialization problem when we do this
+ // immediately
+ // very nasty... I need to revist this problem with Ed Merks
+ //
+ //invokeCMDocumentLoad();
+ invokeDelayedCMDocumentLoad();
+ }
+
+ public void invokeCMDocumentLoad() {
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+ if (modelQuery != null && modelQuery.getCMDocumentManager() != null) {
+ CMDocumentLoader loader = isGrammarInferenceEnabled ? new InferredGrammarBuildingCMDocumentLoader(document, modelQuery) : new CMDocumentLoader(document, modelQuery);
+ loader.loadCMDocuments();
+ }
+ }
+
+ public void invokeDelayedCMDocumentLoad() {
+ //Display.getCurrent().timerExec(2000, new MyTimerTask());
+ timer.schedule(new MyTimerTask(), 2000);
+ }
+
+ public void setGrammarInferenceEnabled(boolean isEnabled) {
+ isGrammarInferenceEnabled = isEnabled;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/JobStatusLineHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/JobStatusLineHelper.java
new file mode 100644
index 0000000000..b0803039ad
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/JobStatusLineHelper.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
+
+
+/**
+ * Updates the status line when an appropriate Job is about to be run.
+ */
+public class JobStatusLineHelper extends JobChangeAdapter {
+ private static JobStatusLineHelper instance;
+
+ public static void init() {
+ if (instance == null) {
+ instance = new JobStatusLineHelper();
+ }
+ }
+
+ private int running = 0;
+
+ private JobStatusLineHelper() {
+ Platform.getJobManager().addJobChangeListener(this);
+ }
+
+ public void aboutToRun(IJobChangeEvent event) {
+ Job job = event.getJob();
+ if (job.belongsTo(CMDocumentManager.class)) {
+ running++;
+ setStatusLine(event.getJob().getName());
+ }
+ }
+
+ public void done(IJobChangeEvent event) {
+ Job job = event.getJob();
+ if (job.belongsTo(CMDocumentManager.class)) {
+ running--;
+ if (running == 0) {
+ setStatusLine(""); //$NON-NLS-1$
+ }
+ }
+ }
+
+ private Display getDisplay() {
+ return PlatformUI.getWorkbench().getDisplay();
+ }
+
+ private void setStatusLine(final String message) {
+ String msgString = message;
+ if (message == null) {
+ msgString = ""; //$NON-NLS-1$
+ }
+ final String finalMessageForThread = msgString;
+ if (getDisplay() != null) {
+ Runnable runnable = new Runnable() {
+ public void run() {
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ if (workbench != null) {
+ IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow();
+ if (workbenchWindow != null) {
+ IEditorPart part = workbenchWindow.getActivePage().getActiveEditor();
+ // part is sometimes null by the time this runs
+ // ... must be better way to get actionBars
+ // and/or statLineManager?
+ if (part != null) {
+ IActionBars actionBars = part.getEditorSite().getActionBars();
+ if (actionBars != null) {
+ IStatusLineManager statusLineManager = actionBars.getStatusLineManager();
+ if (statusLineManager != null) {
+ statusLineManager.setMessage(finalMessageForThread);
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+ Display workbenchDefault = PlatformUI.getWorkbench().getDisplay();
+ workbenchDefault.asyncExec(runnable);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/Logger.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/Logger.java
new file mode 100644
index 0000000000..8d94fe57ec
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/Logger.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui;
+
+
+
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if
+ * desired, the console. This class should only be used by classes in this
+ * plugin. Other plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+ public static final int ERROR = IStatus.ERROR; // 4
+ public static final int ERROR_DEBUG = 200 + ERROR;
+ private static Plugin fPlugin = XMLEditorPlugin.getDefault();
+ private static final String fPluginId = fPlugin.getDescriptor().getUniqueIdentifier();
+ public static final int INFO = IStatus.INFO; // 1
+ public static final int INFO_DEBUG = 200 + INFO;
+
+ public static final int OK = IStatus.OK; // 0
+
+ public static final int OK_DEBUG = 200 + OK;
+
+ private static final String TRACEFILTER_LOCATION = "/debug/tracefilter"; //$NON-NLS-1$
+ public static final int WARNING = IStatus.WARNING; // 2
+ public static final int WARNING_DEBUG = 200 + WARNING;
+
+ /**
+ * Adds message to log.
+ *
+ * @param level
+ * severity level of the message (OK, INFO, WARNING, ERROR,
+ * OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG)
+ * @param message
+ * text to add to the log
+ * @param exception
+ * exception thrown
+ */
+ protected static void _log(int level, String message, Throwable exception) {
+ if (level == OK_DEBUG || level == INFO_DEBUG || level == WARNING_DEBUG || level == ERROR_DEBUG) {
+ if (!isDebugging())
+ return;
+ }
+
+ int severity = IStatus.OK;
+ switch (level) {
+ case INFO_DEBUG :
+ case INFO :
+ severity = IStatus.INFO;
+ break;
+ case WARNING_DEBUG :
+ case WARNING :
+ severity = IStatus.WARNING;
+ break;
+ case ERROR_DEBUG :
+ case ERROR :
+ severity = IStatus.ERROR;
+ }
+ message = (message != null) ? message : "null"; //$NON-NLS-1$
+ Status statusObj = new Status(severity, fPluginId, severity, message, exception);
+ fPlugin.getLog().log(statusObj);
+ }
+
+ /**
+ * Prints message to log if category matches /debug/tracefilter option.
+ *
+ * @param message
+ * text to print
+ * @param category
+ * category of the message, to be compared with
+ * /debug/tracefilter
+ */
+ protected static void _trace(String category, String message, Throwable exception) {
+ if (isTracing(category)) {
+ message = (message != null) ? message : "null"; //$NON-NLS-1$
+ Status statusObj = new Status(IStatus.OK, fPluginId, IStatus.OK, message, exception);
+ fPlugin.getLog().log(statusObj);
+ }
+ }
+
+ /**
+ * @return true if the plugin for this logger is debugging
+ */
+ public static boolean isDebugging() {
+ return fPlugin.isDebugging();
+ }
+
+ /**
+ * Determines if currently tracing a category
+ *
+ * @param category
+ * @return true if tracing category, false otherwise
+ */
+ public static boolean isTracing(String category) {
+ if (!isDebugging())
+ return false;
+
+ String traceFilter = Platform.getDebugOption(fPluginId + TRACEFILTER_LOCATION);
+ if (traceFilter != null) {
+ StringTokenizer tokenizer = new StringTokenizer(traceFilter, ","); //$NON-NLS-1$
+ while (tokenizer.hasMoreTokens()) {
+ String cat = tokenizer.nextToken().trim();
+ if (category.equals(cat)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static void log(int level, String message) {
+ _log(level, message, null);
+ }
+
+ public static void log(int level, String message, Throwable exception) {
+ _log(level, message, exception);
+ }
+
+ public static void logException(String message, Throwable exception) {
+ _log(ERROR, message, exception);
+ }
+
+ public static void logException(Throwable exception) {
+ _log(ERROR, exception.getMessage(), exception);
+ }
+
+ public static void trace(String category, String message) {
+ _trace(category, message, null);
+ }
+
+ public static void traceException(String category, String message, Throwable exception) {
+ _trace(category, message, exception);
+ }
+
+ public static void traceException(String category, Throwable exception) {
+ _trace(category, exception.getMessage(), exception);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextEditorXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextEditorXML.java
new file mode 100644
index 0000000000..76836f9152
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextEditorXML.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.wst.sse.ui.StructuredTextEditor;
+import org.eclipse.wst.sse.ui.edit.util.ActionDefinitionIds;
+import org.eclipse.wst.sse.ui.edit.util.StructuredTextEditorActionConstants;
+import org.eclipse.wst.sse.ui.internal.search.FindOccurrencesActionProvider;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.ui.actions.AddBlockCommentActionXML;
+import org.eclipse.wst.xml.ui.actions.CleanupActionXML;
+import org.eclipse.wst.xml.ui.actions.RemoveBlockCommentActionXML;
+import org.eclipse.wst.xml.ui.actions.ToggleCommentActionXML;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.xml.ui.internal.search.XMLFindOccurrencesAction;
+
+
+public class StructuredTextEditorXML extends StructuredTextEditor {
+ protected void createActions() {
+ super.createActions();
+
+ ResourceBundle resourceBundle = ResourceHandler.getResourceBundle();
+
+ Action action = new CleanupActionXML(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_CLEANUP_DOCUMENT + DOT, this);
+ action.setActionDefinitionId(ActionDefinitionIds.CLEANUP_DOCUMENT);
+ setAction(StructuredTextEditorActionConstants.ACTION_NAME_CLEANUP_DOCUMENT, action);
+
+ /*
+ * action = new CommentActionXML(resourceBundle,
+ * StructuredTextEditorActionConstants.ACTION_NAME_COMMENT + DOT,
+ * this); action.setActionDefinitionId(ActionDefinitionIds.COMMENT);
+ * setAction(StructuredTextEditorActionConstants.ACTION_NAME_COMMENT,
+ * action);
+ *
+ * action = new UncommentActionXML(resourceBundle,
+ * StructuredTextEditorActionConstants.ACTION_NAME_UNCOMMENT + DOT,
+ * this); action.setActionDefinitionId(ActionDefinitionIds.UNCOMMENT);
+ * setAction(StructuredTextEditorActionConstants.ACTION_NAME_UNCOMMENT,
+ * action);
+ */
+
+ action = new ToggleCommentActionXML(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_TOGGLE_COMMENT + DOT, this);
+ action.setActionDefinitionId(ActionDefinitionIds.TOGGLE_COMMENT);
+ setAction(StructuredTextEditorActionConstants.ACTION_NAME_TOGGLE_COMMENT, action);
+
+ action = new AddBlockCommentActionXML(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_ADD_BLOCK_COMMENT + DOT, this);
+ action.setActionDefinitionId(ActionDefinitionIds.ADD_BLOCK_COMMENT);
+ setAction(StructuredTextEditorActionConstants.ACTION_NAME_ADD_BLOCK_COMMENT, action);
+
+ action = new RemoveBlockCommentActionXML(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_REMOVE_BLOCK_COMMENT + DOT, this);
+ action.setActionDefinitionId(ActionDefinitionIds.REMOVE_BLOCK_COMMENT);
+ setAction(StructuredTextEditorActionConstants.ACTION_NAME_REMOVE_BLOCK_COMMENT, action);
+
+ FindOccurrencesActionProvider foAction = new FindOccurrencesActionProvider(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_FIND_OCCURRENCES + DOT, this);
+ foAction.addAction(new XMLFindOccurrencesAction(resourceBundle, "", this)); //$NON-NLS-1$
+ foAction.setActionDefinitionId(ActionDefinitionIds.FIND_OCCURRENCES);
+ setAction(StructuredTextEditorActionConstants.ACTION_NAME_FIND_OCCURRENCES, foAction);
+ markAsSelectionDependentAction(StructuredTextEditorActionConstants.ACTION_NAME_FIND_OCCURRENCES, true);
+ }
+
+ protected void initializeEditor() {
+ super.initializeEditor();
+ setHelpContextId(IHelpContextIds.XML_SOURCEVIEW_HELPID);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextViewerConfigurationXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextViewerConfigurationXML.java
new file mode 100644
index 0000000000..d9843d5602
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/StructuredTextViewerConfigurationXML.java
@@ -0,0 +1,295 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.formatter.IContentFormatter;
+import org.eclipse.jface.text.formatter.MultiPassContentFormatter;
+import org.eclipse.jface.text.information.IInformationPresenter;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.InformationPresenter;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.dtd.ui.style.LineStyleProviderForDTDSubSet;
+import org.eclipse.wst.sse.core.IModelManager;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.format.StructuredFormattingStrategy;
+import org.eclipse.wst.sse.core.text.rules.StructuredTextPartitioner;
+import org.eclipse.wst.sse.ui.EditorPlugin;
+import org.eclipse.wst.sse.ui.StructuredTextReconciler;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration;
+import org.eclipse.wst.sse.ui.preferences.CommonEditorPreferenceNames;
+import org.eclipse.wst.sse.ui.preferences.PreferenceKeyGenerator;
+import org.eclipse.wst.sse.ui.style.IHighlighter;
+import org.eclipse.wst.sse.ui.style.LineStyleProvider;
+import org.eclipse.wst.sse.ui.taginfo.AnnotationHoverProcessor;
+import org.eclipse.wst.sse.ui.taginfo.ProblemAnnotationHoverProcessor;
+import org.eclipse.wst.sse.ui.taginfo.TextHoverManager;
+import org.eclipse.wst.sse.ui.util.EditorUtility;
+import org.eclipse.wst.xml.core.format.FormatProcessorXML;
+import org.eclipse.wst.xml.core.text.rules.StructuredTextPartitionerForXML;
+import org.eclipse.wst.xml.ui.contentassist.NoRegionContentAssistProcessor;
+import org.eclipse.wst.xml.ui.contentassist.XMLContentAssistProcessor;
+import org.eclipse.wst.xml.ui.doubleclick.XMLDoubleClickStrategy;
+import org.eclipse.wst.xml.ui.internal.autoedit.StructuredAutoEditStrategyXML;
+import org.eclipse.wst.xml.ui.internal.correction.CorrectionProcessorXML;
+import org.eclipse.wst.xml.ui.reconcile.StructuredTextReconcilingStrategyForContentModel;
+import org.eclipse.wst.xml.ui.reconcile.StructuredTextReconcilingStrategyForMarkup;
+import org.eclipse.wst.xml.ui.style.LineStyleProviderForXML;
+import org.eclipse.wst.xml.ui.taginfo.XMLBestMatchHoverProcessor;
+import org.eclipse.wst.xml.ui.taginfo.XMLInformationProvider;
+import org.eclipse.wst.xml.ui.taginfo.XMLTagInfoHoverProcessor;
+
+
+public class StructuredTextViewerConfigurationXML extends StructuredTextViewerConfiguration {
+ InformationPresenter fInformationPresenter = null;
+ private boolean reconcilerStrategiesAreSet;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration#getAutoEditStrategies(org.eclipse.jface.text.source.ISourceViewer)
+ */
+ public Map getAutoEditStrategies(ISourceViewer sourceViewer) {
+ Map result = super.getAutoEditStrategies(sourceViewer);
+
+ if (result.get(StructuredTextPartitionerForXML.ST_DEFAULT_XML) == null)
+ result.put(StructuredTextPartitionerForXML.ST_DEFAULT_XML, new ArrayList(1));
+ List strategies = (List) result.get(StructuredTextPartitionerForXML.ST_DEFAULT_XML);
+ strategies.add(new StructuredAutoEditStrategyXML());
+ return result;
+ }
+
+ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+
+ if (configuredContentTypes == null) {
+ String[] xmlTypes = StructuredTextPartitionerForXML.getConfiguredContentTypes();
+ configuredContentTypes = new String[xmlTypes.length + 2];
+ configuredContentTypes[0] = StructuredTextPartitioner.ST_DEFAULT_PARTITION;
+ configuredContentTypes[1] = StructuredTextPartitioner.ST_UNKNOWN_PARTITION;
+ int index = 0;
+ System.arraycopy(xmlTypes, 0, configuredContentTypes, index += 2, xmlTypes.length);
+ }
+ return configuredContentTypes;
+ }
+
+ public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+
+ IContentAssistant ca = super.getContentAssistant(sourceViewer);
+ if (ca != null && ca instanceof ContentAssistant) {
+ ContentAssistant contentAssistant = (ContentAssistant) ca;
+ IContentAssistProcessor xmlContentAssistProcessor = new XMLContentAssistProcessor();
+ IContentAssistProcessor noRegionProcessor = new NoRegionContentAssistProcessor();
+ addContentAssistProcessor(contentAssistant, xmlContentAssistProcessor, StructuredTextPartitioner.ST_DEFAULT_PARTITION);
+ addContentAssistProcessor(contentAssistant, xmlContentAssistProcessor, StructuredTextPartitionerForXML.ST_DEFAULT_XML);
+ addContentAssistProcessor(contentAssistant, noRegionProcessor, StructuredTextPartitioner.ST_UNKNOWN_PARTITION);
+ //contentAssistant.setContentAssistProcessor(xmlContentAssistProcessor,
+ // StructuredTextPartitioner.ST_DEFAULT_PARTITION);
+ //contentAssistant.setContentAssistProcessor(xmlContentAssistProcessor,
+ // StructuredTextPartitionerForXML.ST_DEFAULT_XML);
+ //contentAssistant.setContentAssistProcessor(noRegionProcessor,
+ // StructuredTextPartitioner.ST_UNKNOWN_PARTITION);
+ }
+ return ca;
+ }
+
+ public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
+ final MultiPassContentFormatter formatter = new MultiPassContentFormatter(getConfiguredDocumentPartitioning(sourceViewer), StructuredTextPartitionerForXML.ST_DEFAULT_XML);
+
+ formatter.setMasterStrategy(new StructuredFormattingStrategy(new FormatProcessorXML()));
+
+ return formatter;
+ }
+
+ public IContentAssistant getCorrectionAssistant(ISourceViewer sourceViewer) {
+ IContentAssistant ca = super.getCorrectionAssistant(sourceViewer);
+
+ if (ca != null && ca instanceof ContentAssistant) {
+ ContentAssistant correctionAssistant = (ContentAssistant) ca;
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ IContentAssistProcessor correctionProcessor = new CorrectionProcessorXML(editor);
+ correctionAssistant.setContentAssistProcessor(correctionProcessor, StructuredTextPartitionerForXML.ST_DEFAULT_XML);
+ correctionAssistant.setContentAssistProcessor(correctionProcessor, StructuredTextPartitionerForXML.ST_XML_CDATA);
+ correctionAssistant.setContentAssistProcessor(correctionProcessor, StructuredTextPartitionerForXML.ST_XML_COMMENT);
+ correctionAssistant.setContentAssistProcessor(correctionProcessor, StructuredTextPartitionerForXML.ST_XML_DECLARATION);
+ correctionAssistant.setContentAssistProcessor(correctionProcessor, StructuredTextPartitionerForXML.ST_XML_PI);
+ correctionAssistant.setContentAssistProcessor(correctionProcessor, StructuredTextPartitionerForXML.ST_DTD_SUBSET);
+ }
+ }
+ return ca;
+ }
+
+ public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) {
+
+ if (contentType.compareTo(StructuredTextPartitionerForXML.ST_DEFAULT_XML) == 0)
+ return new XMLDoubleClickStrategy();
+ else
+ return super.getDoubleClickStrategy(sourceViewer, contentType);
+ }
+
+ public IHighlighter getHighlighter(ISourceViewer sourceViewer) {
+
+ IHighlighter highlighter = super.getHighlighter(sourceViewer);
+ if (highlighter != null) {
+ LineStyleProvider xmlProvider = new LineStyleProviderForXML();
+ highlighter.addProvider(StructuredTextPartitionerForXML.ST_DEFAULT_XML, xmlProvider);
+ highlighter.addProvider(StructuredTextPartitionerForXML.ST_XML_CDATA, xmlProvider);
+ highlighter.addProvider(StructuredTextPartitionerForXML.ST_XML_COMMENT, xmlProvider);
+ highlighter.addProvider(StructuredTextPartitionerForXML.ST_XML_DECLARATION, xmlProvider);
+ highlighter.addProvider(StructuredTextPartitionerForXML.ST_XML_PI, xmlProvider);
+ highlighter.addProvider(StructuredTextPartitionerForXML.ST_DTD_SUBSET, new LineStyleProviderForDTDSubSet());
+ }
+ return highlighter;
+ }
+
+ public IInformationPresenter getInformationPresenter(ISourceViewer sourceViewer) {
+
+ if (fInformationPresenter == null) {
+ fInformationPresenter = new InformationPresenter(getInformationPresenterControlCreator(sourceViewer));
+ IInformationProvider xmlInformationProvider = new XMLInformationProvider();
+ fInformationPresenter.setInformationProvider(xmlInformationProvider, StructuredTextPartitioner.ST_DEFAULT_PARTITION);
+ fInformationPresenter.setInformationProvider(xmlInformationProvider, StructuredTextPartitionerForXML.ST_DEFAULT_XML);
+ fInformationPresenter.setSizeConstraints(60, 10, true, true);
+ }
+ return fInformationPresenter;
+ }
+
+ private IModelManager getModelManager() {
+
+ IModelManagerPlugin plugin = (IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID);
+ return plugin.getModelManager();
+ }
+
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+
+ if (fReconciler != null) {
+ // a reconciler should always be installed or disposed of
+ if (!fReconciler.isInstalled()) {
+ fReconciler = null;
+ reconcilerStrategiesAreSet = false;
+ }
+ }
+
+ // the first time running through, there's no model (so no pref store)
+ // but the reconciler still needs to be created so that its document
+ // gets set
+ if (fReconciler == null) {
+ // create one
+ fReconciler = new StructuredTextReconciler();
+ // a null editorPart is valid
+ //fReconciler.setEditor(editorPart);
+ }
+
+ IPreferenceStore store = ((AbstractUIPlugin) Platform.getPlugin(SSE_EDITOR_ID)).getPreferenceStore();
+ boolean reconcilingEnabled = store.getBoolean(CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS);
+
+ // the second time through, the strategies are set
+ if (fReconciler != null && !reconcilerStrategiesAreSet && reconcilingEnabled) {
+ StructuredTextViewer viewer = null;
+ if (sourceViewer instanceof StructuredTextViewer) {
+ viewer = ((StructuredTextViewer) sourceViewer);
+ }
+ IStructuredModel sModel = getModelManager().getExistingModelForRead(viewer.getDocument());
+ try {
+
+
+ if (sModel != null) {
+ // check language (ContentTypeID)....
+ String contentTypeId = sModel.getModelHandler().getAssociatedContentTypeId();
+ String generatedKey = PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.EDITOR_VALIDATION_METHOD, contentTypeId);
+ String validationMethodPref = EditorPlugin.getInstance().getPreferenceStore().getString(generatedKey);
+ IReconcilingStrategy defaultStrategy = null;
+
+ // pref set to no validation, so return
+ if (validationMethodPref.equals(CommonEditorPreferenceNames.EDITOR_VALIDATION_NONE))
+ return fReconciler;
+
+ // content model is the default for xml..
+ // "Content Model" strategies (requires propagating
+ // adapter
+ // from AdapterFactoryProviderFor*)
+
+ IReconcilingStrategy markupStrategy = new StructuredTextReconcilingStrategyForMarkup((ITextEditor) editorPart);
+ IReconcilingStrategy xmlStrategy = new StructuredTextReconcilingStrategyForContentModel((ITextEditor) editorPart);
+ defaultStrategy = xmlStrategy;
+ fReconciler.setReconcilingStrategy(markupStrategy, StructuredTextPartitioner.ST_DEFAULT_PARTITION);
+ fReconciler.setReconcilingStrategy(xmlStrategy, StructuredTextPartitionerForXML.ST_DEFAULT_XML);
+ fReconciler.setDefaultStrategy(defaultStrategy);
+
+ reconcilerStrategiesAreSet = true;
+ }
+ } finally {
+ if (sModel != null)
+ sModel.releaseFromRead();
+ }
+ }
+ return fReconciler;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getTextHover(org.eclipse.jface.text.source.ISourceViewer,
+ * java.lang.String, int)
+ */
+ public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType, int stateMask) {
+ // look for appropriate text hover processor to return based on
+ // content type and state mask
+ if ((contentType == StructuredTextPartitioner.ST_DEFAULT_PARTITION) || (contentType == StructuredTextPartitionerForXML.ST_DEFAULT_XML)) {
+ // check which of xml's text hover is handling stateMask
+ TextHoverManager.TextHoverDescriptor[] hoverDescs = EditorPlugin.getDefault().getTextHoverManager().getTextHovers();
+ int i = 0;
+ while (i < hoverDescs.length) {
+ if (hoverDescs[i].isEnabled() && EditorUtility.computeStateMask(hoverDescs[i].getModifierString()) == stateMask) {
+ String hoverType = hoverDescs[i].getId();
+ if (TextHoverManager.COMBINATION_HOVER.equalsIgnoreCase(hoverType))
+ return new XMLBestMatchHoverProcessor();
+ else if (TextHoverManager.PROBLEM_HOVER.equalsIgnoreCase(hoverType))
+ return new ProblemAnnotationHoverProcessor();
+ else if (TextHoverManager.ANNOTATION_HOVER.equalsIgnoreCase(hoverType))
+ return new AnnotationHoverProcessor();
+ else if (TextHoverManager.DOCUMENTATION_HOVER.equalsIgnoreCase(hoverType))
+ return new XMLTagInfoHoverProcessor();
+ }
+ i++;
+ }
+ }
+ return super.getTextHover(sourceViewer, contentType, stateMask);
+ }
+
+ public void unConfigure(ISourceViewer viewer) {
+
+ super.unConfigure(viewer);
+
+ // InformationPresenters
+ if (fInformationPresenter != null) {
+ fInformationPresenter.uninstall();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/XMLEditorPlugin.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/XMLEditorPlugin.java
new file mode 100644
index 0000000000..df497af771
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/XMLEditorPlugin.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.IPluginDescriptor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
+import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.ui.EditorPlugin;
+import org.eclipse.wst.sse.ui.preferences.CommonEditorPreferenceNames;
+import org.eclipse.wst.sse.ui.preferences.PreferenceKeyGenerator;
+import org.eclipse.wst.sse.ui.preferences.ui.ColorHelper;
+import org.eclipse.wst.sse.ui.registry.AdapterFactoryRegistry;
+import org.eclipse.wst.sse.ui.registry.AdapterFactoryRegistryImpl;
+import org.eclipse.wst.sse.ui.registry.embedded.EmbeddedAdapterFactoryRegistryImpl;
+import org.eclipse.wst.xml.ui.style.IStyleConstantsXML;
+import org.eclipse.wst.xml.ui.templates.TemplateContextTypeXML;
+import org.eclipse.wst.xml.ui.templates.TemplateContextTypeXMLAttribute;
+import org.eclipse.wst.xml.ui.templates.TemplateContextTypeXMLAttributeValue;
+import org.eclipse.wst.xml.ui.templates.TemplateContextTypeXMLTag;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class XMLEditorPlugin extends AbstractUIPlugin {
+ public final static String ID = "org.eclipse.wst.xml.ui"; //$NON-NLS-1$
+ protected static XMLEditorPlugin instance = null;
+
+ public static XMLEditorPlugin getDefault() {
+ return instance;
+ }
+
+ public synchronized static XMLEditorPlugin getInstance() {
+ return instance;
+ }
+
+ /**
+ * The template context type registry for the xml editor.
+ *
+ * @since 3.0
+ */
+ private ContextTypeRegistry fContextTypeRegistry;
+
+ /**
+ * The template store for the xml editor.
+ *
+ * @since 3.0
+ */
+ private TemplateStore fTemplateStore;
+
+ /**
+ * true if editor preference store has been initialized with default
+ * values false otherwise
+ */
+ private boolean preferencesInitd = false;
+
+ public XMLEditorPlugin(IPluginDescriptor descriptor) {
+ super(descriptor);
+ instance = this;
+
+ // reference the preference store so
+ // initializeDefaultPreferences(IPreferenceStore preferenceStore) is
+ // called
+ IPreferenceStore store = getPreferenceStore();
+ // for some reason initializeDefaultPreferences is not always called,
+ // so
+ // just add an extra check to see if not initialized, then call init
+ if (!preferencesInitd) {
+ initializeDefaultPreferences(store);
+ }
+ JobStatusLineHelper.init();
+ }
+
+ public AdapterFactoryRegistry getAdapterFactoryRegistry() {
+ return AdapterFactoryRegistryImpl.getInstance();
+
+ }
+
+ public AdapterFactoryRegistry getEmbeddedAdapterFactoryRegistry() {
+ return EmbeddedAdapterFactoryRegistryImpl.getInstance();
+
+ }
+
+ /**
+ * Returns the template context type registry for the xml plugin.
+ *
+ * @return the template context type registry for the xml plugin
+ */
+ public ContextTypeRegistry getTemplateContextRegistry() {
+ if (fContextTypeRegistry == null) {
+ fContextTypeRegistry = new ContributionContextTypeRegistry();
+
+ fContextTypeRegistry.addContextType(new TemplateContextTypeXML());
+ fContextTypeRegistry.addContextType(new TemplateContextTypeXMLTag());
+ fContextTypeRegistry.addContextType(new TemplateContextTypeXMLAttribute());
+ fContextTypeRegistry.addContextType(new TemplateContextTypeXMLAttributeValue());
+ }
+
+ return fContextTypeRegistry;
+ }
+
+ /**
+ * Returns the template store for the xml editor templates.
+ *
+ * @return the template store for the xml editor templates
+ */
+ public TemplateStore getTemplateStore() {
+ if (fTemplateStore == null) {
+ fTemplateStore = new ContributionTemplateStore(getTemplateContextRegistry(), getPreferenceStore(), CommonEditorPreferenceNames.TEMPLATES_KEY);
+
+ try {
+ fTemplateStore.load();
+ } catch (IOException e) {
+ Logger.logException(e);
+ }
+ }
+ return fTemplateStore;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#initializeDefaultPluginPreferences()
+ */
+ protected void initializeDefaultPreferences(IPreferenceStore store) {
+
+ // ignore this preference store
+ // use EditorPlugin preference store
+ IPreferenceStore editorStore = ((AbstractUIPlugin) Platform.getPlugin(EditorPlugin.ID)).getPreferenceStore();
+ EditorPlugin.initializeDefaultEditorPreferences(editorStore);
+ initializeDefaultXMLPreferences(editorStore);
+ preferencesInitd = true;
+ }
+
+ protected void initializeDefaultXMLPreferences(IPreferenceStore store) {
+
+ String ctId = IContentTypeIdentifier.ContentTypeID_SSEXML;
+
+ store.setDefault(PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.CONTENT_ASSIST_SUPPORTED, ctId), true);
+ store.setDefault(PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.AUTO_PROPOSE, ctId), true);
+ store.setDefault(PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.AUTO_PROPOSE_CODE, ctId), CommonEditorPreferenceNames.LT);
+
+ store.setDefault(CommonEditorPreferenceNames.EDITOR_VALIDATION_METHOD, CommonEditorPreferenceNames.EDITOR_VALIDATION_CONTENT_MODEL); //$NON-NLS-1$
+
+ store.setDefault(PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.EDITOR_VALIDATION_METHOD, ctId), CommonEditorPreferenceNames.EDITOR_VALIDATION_CONTENT_MODEL); //$NON-NLS-1$
+ store.setDefault(PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.EDITOR_USE_INFERRED_GRAMMAR, ctId), true);
+
+ // XML Style Preferences
+ String NOBACKGROUNDBOLD = " | null | false"; //$NON-NLS-1$
+ String styleValue = ColorHelper.getColorString(127, 0, 127) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.TAG_ATTRIBUTE_NAME, ctId), styleValue);
+
+ styleValue = ColorHelper.getColorString(42, 0, 255) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE, ctId), styleValue);
+
+ styleValue = "null" + NOBACKGROUNDBOLD; //$NON-NLS-1$
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS, ctId), styleValue); // specified
+ // value
+ // is
+ // black;
+ // leaving
+ // as
+ // widget
+ // default
+
+ styleValue = ColorHelper.getColorString(63, 95, 191) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.COMMENT_BORDER, ctId), styleValue);
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.COMMENT_TEXT, ctId), styleValue);
+
+ styleValue = ColorHelper.getColorString(0, 128, 128) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.DECL_BORDER, ctId), styleValue);
+
+ styleValue = ColorHelper.getColorString(0, 0, 128) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.DOCTYPE_NAME, ctId), styleValue);
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF, ctId), styleValue);
+
+ styleValue = ColorHelper.getColorString(128, 128, 128) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID, ctId), styleValue);
+
+ styleValue = ColorHelper.getColorString(63, 127, 95) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF, ctId), styleValue);
+
+ styleValue = "null" + NOBACKGROUNDBOLD; //$NON-NLS-1$
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.XML_CONTENT, ctId), styleValue); // specified
+ // value
+ // is
+ // black;
+ // leaving
+ // as
+ // widget
+ // default
+
+ styleValue = ColorHelper.getColorString(0, 128, 128) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.TAG_BORDER, ctId), styleValue);
+
+ styleValue = ColorHelper.getColorString(63, 127, 127) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.TAG_NAME, ctId), styleValue);
+
+ styleValue = ColorHelper.getColorString(0, 128, 128) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.PI_BORDER, ctId), styleValue);
+
+ styleValue = "null" + NOBACKGROUNDBOLD; //$NON-NLS-1$
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.PI_CONTENT, ctId), styleValue); // specified
+ // value
+ // is
+ // black;
+ // leaving
+ // as
+ // widget
+ // default
+
+ styleValue = ColorHelper.getColorString(0, 128, 128) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.CDATA_BORDER, ctId), styleValue);
+
+ styleValue = ColorHelper.getColorString(0, 0, 0) + NOBACKGROUNDBOLD;
+ store.setDefault(PreferenceKeyGenerator.generateKey(IStyleConstantsXML.CDATA_TEXT, ctId), styleValue);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/XMLSpellCheckTarget.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/XMLSpellCheckTarget.java
new file mode 100644
index 0000000000..150549ce70
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/XMLSpellCheckTarget.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui;
+
+import org.eclipse.wst.sse.ui.SpellCheckTargetImpl;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class XMLSpellCheckTarget extends SpellCheckTargetImpl {
+
+ /**
+ * @param editor
+ */
+ public XMLSpellCheckTarget() {
+ super();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.SpellCheckTargetImpl#isValidType(java.lang.String)
+ */
+ protected boolean isValidType(String type) {
+ boolean valid = false;
+ if (XMLRegionContext.XML_COMMENT_TEXT.equals(type) || XMLRegionContext.XML_CONTENT.equals(type)) {
+ valid = true;
+ }
+ return valid || super.isValidType(type);
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/AbstractNodeActionManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/AbstractNodeActionManager.java
new file mode 100644
index 0000000000..493b4b3437
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/AbstractNodeActionManager.java
@@ -0,0 +1,657 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMDataType;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.util.CMDescriptionBuilder;
+import org.eclipse.wst.common.contentmodel.util.DOMContentBuilder;
+import org.eclipse.wst.common.contentmodel.util.DOMContentBuilderImpl;
+import org.eclipse.wst.common.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+
+
+
+public abstract class AbstractNodeActionManager extends BaseNodeActionManager {
+
+
+ /**
+ * AddNodeAction
+ */
+ public class AddNodeAction extends NodeAction {
+ protected CMNode cmnode;
+ protected String description;
+ protected int index;
+ protected int nodeType;
+ protected Node parent;
+ protected String undoDescription;
+
+
+ public AddNodeAction(CMNode cmnode, Node parent, int index) {
+ this.cmnode = cmnode;
+ this.parent = parent;
+ this.index = index;
+
+ String text = getLabel(parent, cmnode);
+ setText(text);
+ description = text;
+ undoDescription = XMLCommonResources.getInstance().getString("_UI_MENU_ADD") + " " + text; //$NON-NLS-1$ //$NON-NLS-2$
+ setImageDescriptor(imageDescriptorCache.getImageDescriptor(cmnode));
+ }
+
+
+ public AddNodeAction(int nodeType, Node parent, int index) {
+ this.nodeType = nodeType;
+ this.index = index;
+ this.parent = parent;
+
+ switch (nodeType) {
+ case Node.COMMENT_NODE : {
+ description = XMLCommonResources.getInstance().getString("_UI_MENU_COMMENT"); //$NON-NLS-1$
+ undoDescription = XMLCommonResources.getInstance().getString("_UI_MENU_ADD_COMMENT"); //$NON-NLS-1$
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ description = XMLCommonResources.getInstance().getString("_UI_MENU_PROCESSING_INSTRUCTION"); //$NON-NLS-1$
+ undoDescription = XMLCommonResources.getInstance().getString("_UI_MENU_ADD_PROCESSING_INSTRUCTION"); //$NON-NLS-1$
+ break;
+ }
+ case Node.CDATA_SECTION_NODE : {
+ description = XMLCommonResources.getInstance().getString("_UI_MENU_CDATA_SECTION"); //$NON-NLS-1$
+ undoDescription = XMLCommonResources.getInstance().getString("_UI_MENU_ADD_CDATA_SECTION"); //$NON-NLS-1$
+ break;
+ }
+ case Node.TEXT_NODE : {
+ description = XMLCommonResources.getInstance().getString("_UI_MENU_PCDATA"); //$NON-NLS-1$
+ undoDescription = XMLCommonResources.getInstance().getString("_UI_MENU_ADD_PCDATA"); //$NON-NLS-1$
+ break;
+ }
+ }
+ setText(description);
+ setImageDescriptor(imageDescriptorCache.getImageDescriptor(new Integer(nodeType)));
+ }
+
+
+ protected void addNodeForCMNode() {
+ if (parent != null) {
+ insert(parent, cmnode, index);
+ }
+ }
+
+
+ protected void addNodeForNodeType() {
+ Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+ Node newChildNode = null;
+ boolean format = true;
+ switch (nodeType) {
+ case Node.COMMENT_NODE : {
+ newChildNode = document.createComment(XMLCommonResources.getInstance().getString("_UI_COMMENT_VALUE")); //$NON-NLS-1$
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ newChildNode = document.createProcessingInstruction(XMLCommonResources.getInstance().getString("_UI_PI_TARGET_VALUE"), XMLCommonResources.getInstance().getString("_UI_PI_DATA_VALUE")); //$NON-NLS-1$ //$NON-NLS-2$
+ break;
+ }
+ case Node.CDATA_SECTION_NODE : {
+ newChildNode = document.createCDATASection(""); //$NON-NLS-1$
+ break;
+ }
+ case Node.TEXT_NODE : {
+ format = false;
+ newChildNode = document.createTextNode(parent.getNodeName());
+ break;
+ }
+ }
+
+ if (newChildNode != null) {
+ List list = new Vector(1);
+ list.add(newChildNode);
+ insertNodesAtIndex(parent, list, index, format);
+ }
+ }
+
+
+ public String getUndoDescription() {
+ return undoDescription;
+ }
+
+
+ public void run() {
+ beginNodeAction(this);
+ if (cmnode != null) {
+ addNodeForCMNode();
+ } else {
+ addNodeForNodeType();
+ }
+ endNodeAction(this);
+ }
+ }
+
+
+ /**
+ * DeleteAction
+ */
+ public class DeleteAction extends NodeAction {
+ protected List list;
+
+ public DeleteAction(List list) {
+ setText(XMLCommonResources.getInstance().getString("_UI_MENU_REMOVE")); //$NON-NLS-1$
+ this.list = list;
+ }
+
+ public DeleteAction(Node node) {
+ setText(XMLCommonResources.getInstance().getString("_UI_MENU_REMOVE")); //$NON-NLS-1$
+ list = new Vector();
+ list.add(node);
+ }
+
+ public String getUndoDescription() {
+ return XMLCommonResources.getInstance().getString("DELETE"); //$NON-NLS-1$
+ }
+
+ public void run() {
+ beginNodeAction(this);
+
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ Node node = (Node) i.next();
+ if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ Attr attr = (Attr) node;
+ attr.getOwnerElement().removeAttributeNode(attr);
+ } else {
+ Node parent = node.getParentNode();
+ if (parent != null) {
+ Node previousSibling = node.getPreviousSibling();
+ if (previousSibling != null && isWhitespaceTextNode(previousSibling)) {
+ parent.removeChild(previousSibling);
+ }
+ parent.removeChild(node);
+ }
+ }
+ }
+
+ endNodeAction(this);
+ }
+ }
+
+
+ class ImageDescriptorCache {
+ protected ImageDescriptor attributeImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+ protected ImageDescriptor cdataSectionImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_CDATASECTION);
+ protected ImageDescriptor commentImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_COMMENT);
+ protected ImageDescriptor elementImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ELEMENT);
+ protected ImageDescriptor piImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION);
+ protected ImageDescriptor textImage = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_TXTEXT);
+
+ public ImageDescriptor getImageDescriptor(Object object) {
+ ImageDescriptor result = null;
+ if (object instanceof CMNode) {
+ CMNode cmnode = (CMNode) object;
+ switch (cmnode.getNodeType()) {
+ case CMNode.ATTRIBUTE_DECLARATION : {
+ result = attributeImage;
+ break;
+ }
+ case CMNode.DATA_TYPE : {
+ result = textImage;
+ break;
+ }
+ case CMNode.ELEMENT_DECLARATION : {
+ result = elementImage;
+ break;
+ }
+ case CMNode.GROUP : {
+ result = elementImage;
+ break;
+ }
+ }
+ } else if (object instanceof Integer) {
+ Integer integer = (Integer) object;
+ switch (integer.intValue()) {
+ case Node.COMMENT_NODE : {
+ result = commentImage;
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ result = piImage;
+ break;
+ }
+ case Node.CDATA_SECTION_NODE : {
+ result = cdataSectionImage;
+ break;
+ }
+ case Node.TEXT_NODE : {
+ result = textImage;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+ }
+
+ // TODO... remove this class. I'm pretty sure it is no longer used by
+ // anyone.
+ /**
+ * @depracated
+ */
+ public class InsertAction extends NodeAction {
+ protected String description;
+ protected int index;
+ protected int nodeType;
+ protected Node parent;
+
+ public InsertAction(int nodeType, Node parent, int index) {
+ this.nodeType = nodeType;
+ this.index = index;
+ this.parent = parent;
+ switch (nodeType) {
+ case Node.COMMENT_NODE : {
+ description = XMLCommonResources.getInstance().getString("_UI_MENU_COMMENT"); //$NON-NLS-1$
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ description = XMLCommonResources.getInstance().getString("_UI_MENU_PROCESSING_INSTRUCTION"); //$NON-NLS-1$
+ break;
+ }
+ case Node.CDATA_SECTION_NODE : {
+ description = XMLCommonResources.getInstance().getString("_UI_MENU_CDATA_SECTION"); //$NON-NLS-1$
+ break;
+ }
+ case Node.TEXT_NODE : {
+ description = XMLCommonResources.getInstance().getString("_UI_MENU_PCDATA"); //$NON-NLS-1$
+ break;
+ }
+ }
+ setText(description);
+ setImageDescriptor(imageDescriptorCache.getImageDescriptor(new Integer(nodeType)));
+ }
+
+ public InsertAction(int nodeType, Node parent, int index, String title) {
+ this.nodeType = nodeType;
+ this.index = index;
+ this.parent = parent;
+ description = title;
+ setText(description);
+ setImageDescriptor(imageDescriptorCache.getImageDescriptor(new Integer(nodeType)));
+ }
+
+ public String getUndoDescription() {
+ return XMLCommonResources.getInstance().getString("_UI_MENU_ADD") + " " + description; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void run() {
+ beginNodeAction(this);
+
+ Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+ Node newChildNode = null;
+ boolean format = true;
+ switch (nodeType) {
+ case Node.COMMENT_NODE : {
+ newChildNode = document.createComment(XMLCommonResources.getInstance().getString("_UI_COMMENT_VALUE")); //$NON-NLS-1$
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ newChildNode = document.createProcessingInstruction(XMLCommonResources.getInstance().getString("_UI_PI_TARGET_VALUE"), XMLCommonResources.getInstance().getString("_UI_PI_DATA_VALUE")); //$NON-NLS-1$ //$NON-NLS-2$
+ break;
+ }
+ case Node.CDATA_SECTION_NODE : {
+ newChildNode = document.createCDATASection(""); //$NON-NLS-1$
+ break;
+ }
+ case Node.TEXT_NODE : {
+ format = false;
+ newChildNode = document.createTextNode(parent.getNodeName());
+ break;
+ }
+ }
+
+ if (newChildNode != null) {
+ List list = new Vector(1);
+ list.add(newChildNode);
+ insertNodesAtIndex(parent, list, index, format);
+ }
+
+ endNodeAction(this);
+ }
+ }
+
+
+ /**
+ * ReplaceNodeAction
+ */
+ public class ReplaceNodeAction extends NodeAction {
+ protected CMNode cmnode;
+ protected String description;
+ protected int endIndex;
+ protected Node parent;
+ protected int startIndex;
+
+
+ public ReplaceNodeAction(Node parent, CMNode cmnode, int startIndex, int endIndex) {
+ this.parent = parent;
+ this.cmnode = cmnode;
+ this.startIndex = startIndex;
+ this.endIndex = endIndex;
+
+ setText(getLabel(parent, cmnode));
+ setImageDescriptor(imageDescriptorCache.getImageDescriptor(cmnode));
+ }
+
+ public String getUndoDescription() {
+ String result = XMLCommonResources.getInstance().getString("_UI_LABEL_UNDO_REPLACE_DESCRIPTION"); //$NON-NLS-1$
+ result += " " + getLabel(parent, cmnode); //$NON-NLS-1$
+ return result;
+ }
+
+ public void run() {
+ beginNodeAction(this);
+
+ if (parent != null && cmnode != null) {
+ remove(parent, startIndex, endIndex);
+ insert(parent, cmnode, startIndex);
+ }
+ endNodeAction(this);
+ }
+ }
+
+ protected ImageDescriptorCache imageDescriptorCache = new ImageDescriptorCache();
+ protected Viewer viewer;
+
+ public AbstractNodeActionManager(IStructuredModel model, ModelQuery modelQuery, Viewer viewer) {
+ super(model, modelQuery);
+ this.viewer = viewer;
+ }
+
+
+ public void beginNodeAction(NodeAction action) {
+ model.beginRecording(action, action.getUndoDescription());
+ }
+
+
+ protected Action createAddAttributeAction(Element parent, CMAttributeDeclaration ad) {
+ Action action = null;
+ if (ad == null) {
+ action = new EditAttributeAction(this, parent, null, XMLCommonResources.getInstance().getString("_UI_MENU_NEW_ATTRIBUTE"), XMLCommonResources.getInstance().getString("_UI_MENU_NEW_ATTRIBUTE_TITLE")); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ action = new AddNodeAction(ad, parent, -1);
+ }
+ return action;
+ }
+
+
+ protected Action createAddCDataSectionAction(Node parent, int index) {
+ return new AddNodeAction(Node.CDATA_SECTION_NODE, parent, index);
+ }
+
+
+ protected Action createAddCommentAction(Node parent, int index) {
+ return new AddNodeAction(Node.COMMENT_NODE, parent, index);
+ }
+
+
+ protected Action createAddDoctypeAction(Document document, int index) {
+ return new EditDoctypeAction(model, document, model.getBaseLocation(), XMLCommonResources.getInstance().getString("_UI_MENU_ADD_DTD_INFORMATION")); //$NON-NLS-1$
+ }
+
+
+ protected Action createAddElementAction(Node parent, CMElementDeclaration ed, int index) {
+ Action action = null;
+ if (ed == null) {
+ action = new EditElementAction(this, parent, index, XMLCommonResources.getInstance().getString("_UI_MENU_NEW_ELEMENT"), XMLCommonResources.getInstance().getString("_UI_MENU_NEW_ELEMENT_TITLE")); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ action = new AddNodeAction(ed, parent, index);
+ }
+ return action;
+ }
+
+
+ protected Action createAddPCDataAction(Node parent, CMDataType dataType, int index) {
+ Action action = null;
+ if (dataType == null) {
+ action = new AddNodeAction(Node.TEXT_NODE, parent, index);
+ } else {
+ action = new AddNodeAction(dataType, parent, index);
+ }
+ return action;
+ }
+
+
+ protected Action createAddProcessingInstructionAction(Node parent, int index) {
+ Node refChild = getRefChildNodeAtIndex(parent, index);
+ Action action = new EditProcessingInstructionAction(this, parent, refChild, XMLCommonResources.getInstance().getString("_UI_MENU_ADD_PROCESSING_INSTRUCTION"), XMLCommonResources.getInstance().getString("ADD_PROCESSING_INSTRUCTION")); //$NON-NLS-1$ //$NON-NLS-2$
+ action.setImageDescriptor(imageDescriptorCache.getImageDescriptor(new Integer(Node.PROCESSING_INSTRUCTION_NODE)));
+ return action;
+ }
+
+
+ protected Action createAddSchemaInfoAction(Element element) {
+ return new EditSchemaInfoAction(this, element.getOwnerDocument(), model.getBaseLocation(), XMLCommonResources.getInstance().getString("_UI_MENU_ADD_SCHEMA_INFORMATION")); //$NON-NLS-1$
+ }
+
+
+ protected Action createDeleteAction(List selection) {
+ DeleteAction deleteAction = new DeleteAction(selection);
+ deleteAction.setEnabled(selection.size() > 0);
+ return deleteAction;
+ }
+
+
+ public DOMContentBuilder createDOMContentBuilder(Document document) {
+ DOMContentBuilderImpl builder = new DOMContentBuilderImpl(document);
+ return builder;
+ }
+
+
+ protected Action createEditAttributeAction(Attr attr, CMAttributeDeclaration ad) {
+ return new EditAttributeAction(this, attr.getOwnerElement(), attr, XMLCommonResources.getInstance().getString("_UI_MENU_EDIT_ATTRIBUTE"), XMLCommonResources.getInstance().getString("_UI_MENU_EDIT_ATTRIBUTE_TITLE")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+
+ protected Action createEditDoctypeAction(DocumentType doctype) {
+ return new EditDoctypeAction(model, doctype, model.getBaseLocation(), XMLCommonResources.getInstance().getString("_UI_MENU_EDIT_DOCTYPE")); //$NON-NLS-1$
+ }
+
+
+ protected Action createEditProcessingInstructionAction(ProcessingInstruction pi) {
+ return new EditProcessingInstructionAction(this, pi, XMLCommonResources.getInstance().getString("_UI_MENU_EDIT_PROCESSING_INSTRUCTION"), XMLCommonResources.getInstance().getString("_UI_MENU_EDIT_PROCESSING_INSTRUCTION_TITLE")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+
+ protected Action createEditSchemaInfoAction(Element element) {
+ return new EditSchemaInfoAction(this, element.getOwnerDocument(), model.getBaseLocation(), XMLCommonResources.getInstance().getString("_UI_MENU_EDIT_NAMESPACES")); //$NON-NLS-1$
+ }
+
+
+ protected Action createRenameAction(Node node) {
+ Action result = null;
+ if (node instanceof Element) {
+ result = new EditElementAction(this, (Element) node, XMLCommonResources.getInstance().getString("_UI_MENU_RENAME"), XMLCommonResources.getInstance().getString("_UI_MENU_RENAME_TITLE")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return result;
+ }
+
+
+ protected Action createReplaceAction(Node parent, CMNode cmnode, int startIndex, int endIndex) {
+ return new ReplaceNodeAction(parent, cmnode, startIndex, endIndex);
+ }
+
+ public void endNodeAction(NodeAction action) {
+ model.endRecording(action);
+ }
+
+
+
+ public void fillContextMenu(IMenuManager menuManager, ISelection selection) {
+ try {
+ List selectionList = new ArrayList();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection es = (IStructuredSelection) selection;
+ for (Iterator i = es.iterator(); i.hasNext();) {
+ selectionList.add(i.next());
+ }
+ }
+
+ contributeActions(menuManager, selectionList);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ */
+ public String getLabel(Node parent, CMNode cmnode) {
+ String result = "?" + cmnode + "?"; //$NON-NLS-1$ //$NON-NLS-2$
+ if (cmnode != null) {
+ result = (String) cmnode.getProperty("description"); //$NON-NLS-1$
+ if (result == null) {
+ if (cmnode.getNodeType() == CMNode.GROUP) {
+ CMDescriptionBuilder descriptionBuilder = new CMDescriptionBuilder();
+ result = descriptionBuilder.buildDescription(cmnode);
+ } else {
+ result = DOMNamespaceHelper.computeName(cmnode, parent, null);
+ }
+ }
+ }
+ return result;
+ }
+
+
+ public IStructuredModel getModel() {
+ return model;
+ }
+
+
+ public Shell getWorkbenchWindowShell() {
+ return XMLCommonResources.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+ }
+
+
+ public void insert(Node parent, CMNode cmnode, int index) {
+ Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+ DOMContentBuilder builder = createDOMContentBuilder(document);
+ builder.setBuildPolicy(DOMContentBuilder.BUILD_ONLY_REQUIRED_CONTENT);
+ builder.build(parent, cmnode);
+ insertNodesAtIndex(parent, builder.getResult(), index);
+ }
+
+
+ public void insertNodesAtIndex(Node parent, List list, int index) {
+ insertNodesAtIndex(parent, list, index, true);
+ }
+
+
+ public void insertNodesAtIndex(Node parent, List list, int index, boolean format) {
+ NodeList nodeList = parent.getChildNodes();
+ if (index == -1) {
+ index = nodeList.getLength();
+ }
+ Node refChild = (index < nodeList.getLength()) ? nodeList.item(index) : null;
+
+ // here we consider the case where the previous node is a 'white
+ // space' Text node
+ // we should really do the insert before this node
+ //
+ int prevIndex = index - 1;
+ Node prevChild = (prevIndex < nodeList.getLength()) ? nodeList.item(prevIndex) : null;
+ if (isWhitespaceTextNode(prevChild)) {
+ refChild = prevChild;
+ }
+
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ Node newNode = (Node) i.next();
+
+ if (newNode.getNodeType() == Node.ATTRIBUTE_NODE) {
+ Element parentElement = (Element) parent;
+ parentElement.setAttributeNode((Attr) newNode);
+ } else {
+ parent.insertBefore(newNode, refChild);
+ }
+ }
+
+ boolean formatDeep = false;
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ Node newNode = (Node) i.next();
+ if (newNode.getNodeType() == Node.ELEMENT_NODE) {
+ formatDeep = true;
+ }
+
+ if (format) {
+ reformat(newNode, formatDeep);
+ }
+ }
+
+ setViewerSelection(list);
+ }
+
+
+ /**
+ * This method is abstract since currently, the sed editor is required to
+ * perform formating and we don't want to create a dependency on the sed
+ * editor.
+ */
+ public abstract void reformat(Node parent, boolean deep);
+
+
+ public void remove(Node parent, int startIndex, int endIndex) {
+ NodeList nodeList = parent.getChildNodes();
+ for (int i = endIndex; i >= startIndex; i--) {
+ Node node = nodeList.item(i);
+ if (node != null) {
+ parent.removeChild(node);
+ }
+ }
+ }
+
+
+ public void setViewerSelection(List list) {
+ if (viewer != null) {
+ viewer.setSelection(new StructuredSelection(list), true);
+ }
+ }
+
+
+ public void setViewerSelection(Node node) {
+ if (viewer != null) {
+ viewer.setSelection(new StructuredSelection(node), true);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ActionContributorXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ActionContributorXML.java
new file mode 100644
index 0000000000..ec8d89d533
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ActionContributorXML.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorActionBarContributor;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.RetargetTextEditorAction;
+import org.eclipse.wst.sse.ui.edit.util.ActionContributor;
+import org.eclipse.wst.sse.ui.edit.util.ActionDefinitionIds;
+import org.eclipse.wst.sse.ui.edit.util.StructuredTextEditorActionConstants;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+
+
+/**
+ * XMLEditorActionContributor
+ *
+ * This class should not be used inside multi page editor's
+ * ActionBarContributor, since cascaded init() call from the
+ * ActionBarContributor will causes exception and it leads to lose whole
+ * toolbars.
+ *
+ * Instead, use SourcePageActionContributor for source page contributor of
+ * multi page editor.
+ *
+ * Note that this class is still valid for single page editor.
+ */
+public class ActionContributorXML extends ActionContributor {
+ private static final String[] EDITOR_IDS = {"org.eclipse.wst.xml.ui.StructuredTextEditorXML", "org.eclipse.wst.sse.ui.StructuredTextEditor", "org.eclipse.wst.xml.ui.StructuredTextEditorXML2"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ protected RetargetTextEditorAction fCleanupDocument = null;
+ protected RetargetTextEditorAction fComment = null;
+ // tooltip
+ // action
+ protected RetargetTextEditorAction fContentAssist = null;
+ // action
+ protected RetargetTextEditorAction fFindOccurrences = null;
+ protected RetargetTextEditorAction fFormatActiveElements = null;
+ protected RetargetTextEditorAction fFormatDocument = null;
+ protected MenuManager fFormatMenu = null;
+ protected RetargetTextEditorAction fOpenFileAction = null; // open file
+ protected RetargetTextEditorAction fQuickFix = null;
+
+ protected RetargetTextEditorAction fShowTooltipAction = null; // show
+ protected RetargetTextEditorAction fUncomment = null;
+
+ public ActionContributorXML() {
+ super();
+
+ ResourceBundle resourceBundle = ResourceHandler.getResourceBundle();
+
+ // edit commands
+ fShowTooltipAction = new RetargetTextEditorAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_INFORMATION + StructuredTextEditorActionConstants.DOT);
+ fShowTooltipAction.setActionDefinitionId(ActionDefinitionIds.INFORMATION);
+
+ fContentAssist = new RetargetTextEditorAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_PROPOSALS + StructuredTextEditorActionConstants.DOT);
+ fContentAssist.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+
+ fQuickFix = new RetargetTextEditorAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_QUICK_FIX + StructuredTextEditorActionConstants.DOT);
+ fQuickFix.setActionDefinitionId(ActionDefinitionIds.QUICK_FIX);
+
+ // source commands
+ fCleanupDocument = new RetargetTextEditorAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_CLEANUP_DOCUMENT + StructuredTextEditorActionConstants.DOT);
+ fCleanupDocument.setActionDefinitionId(ActionDefinitionIds.CLEANUP_DOCUMENT);
+
+ fFormatDocument = new RetargetTextEditorAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_DOCUMENT + StructuredTextEditorActionConstants.DOT);
+ fFormatDocument.setActionDefinitionId(ActionDefinitionIds.FORMAT_DOCUMENT);
+
+ fFormatActiveElements = new RetargetTextEditorAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_ACTIVE_ELEMENTS + StructuredTextEditorActionConstants.DOT);
+ fFormatActiveElements.setActionDefinitionId(ActionDefinitionIds.FORMAT_ACTIVE_ELEMENTS);
+
+ fFormatMenu = new MenuManager(ResourceHandler.getString("FormatMenu.label")); //$NON-NLS-1$
+ fFormatMenu.add(fFormatDocument);
+ fFormatMenu.add(fFormatActiveElements);
+
+ // navigate commands
+ fOpenFileAction = new RetargetTextEditorAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_OPEN_FILE + StructuredTextEditorActionConstants.DOT);
+ fOpenFileAction.setActionDefinitionId(ActionDefinitionIds.OPEN_FILE);
+
+ fFindOccurrences = new RetargetTextEditorAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_FIND_OCCURRENCES + StructuredTextEditorActionConstants.DOT);
+ fFindOccurrences.setActionDefinitionId(ActionDefinitionIds.FIND_OCCURRENCES);
+ }
+
+ protected void addToMenu(IMenuManager menu) {
+ // edit commands
+ IMenuManager editMenu = menu.findMenuUsingPath(IWorkbenchActionConstants.M_EDIT);
+ if (editMenu != null) {
+ editMenu.add(fCommandsSeparator);
+ editMenu.add(fToggleInsertModeAction);
+ editMenu.add(fCommandsSeparator);
+ editMenu.add(fExpandSelectionToMenu);
+ editMenu.add(fCommandsSeparator);
+ editMenu.add(fShowTooltipAction);
+ editMenu.add(fContentAssist);
+ editMenu.add(fQuickFix);
+ editMenu.add(fMenuAdditionsGroupMarker);
+ }
+
+ // source commands
+ String sourceMenuLabel = ResourceHandler.getString("SourceMenu.label"); //$NON-NLS-1$
+ String sourceMenuId = "sourceMenuId"; // This is just a menu id. No
+ // need to translate.
+ // //$NON-NLS-1$
+ IMenuManager sourceMenu = new MenuManager(sourceMenuLabel, sourceMenuId);
+ menu.insertAfter(IWorkbenchActionConstants.M_EDIT, sourceMenu);
+ if (sourceMenu != null) {
+ sourceMenu.add(fCommandsSeparator);
+ sourceMenu.add(fToggleComment);
+ sourceMenu.add(fAddBlockComment);
+ sourceMenu.add(fRemoveBlockComment);
+ sourceMenu.add(fShiftRight);
+ sourceMenu.add(fShiftLeft);
+ sourceMenu.add(fCleanupDocument);
+ sourceMenu.add(fFormatMenu);
+ sourceMenu.add(fCommandsSeparator);
+ sourceMenu.add(fFindOccurrences);
+ }
+
+ // navigate commands
+ IMenuManager navigateMenu = menu.findMenuUsingPath(IWorkbenchActionConstants.M_NAVIGATE);
+ if (navigateMenu != null) {
+ navigateMenu.appendToGroup(IWorkbenchActionConstants.OPEN_EXT, fCommandsSeparator);
+ navigateMenu.appendToGroup(IWorkbenchActionConstants.OPEN_EXT, fOpenFileAction);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.edit.util.ActionContributor#getExtensionIDs()
+ */
+ protected String[] getExtensionIDs() {
+ return EDITOR_IDS;
+ }
+
+ /**
+ * @see IEditorActionBarContributor#setActiveEditor(IEditorPart)
+ */
+ public void setActiveEditor(IEditorPart activeEditor) {
+ if (getActiveEditorPart() == activeEditor)
+ return;
+ super.setActiveEditor(activeEditor);
+
+ IActionBars actionBars = getActionBars();
+ if (actionBars != null) {
+ IStatusLineManager statusLineManager = actionBars.getStatusLineManager();
+ if (statusLineManager != null) {
+ statusLineManager.setMessage(null);
+ statusLineManager.setErrorMessage(null);
+ }
+ }
+
+ ITextEditor textEditor = getTextEditor(activeEditor);
+
+ fShowTooltipAction.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_INFORMATION));
+ fContentAssist.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_PROPOSALS));
+ fQuickFix.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_QUICK_FIX));
+
+ fCleanupDocument.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_CLEANUP_DOCUMENT));
+ fFormatDocument.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_DOCUMENT));
+ fFormatActiveElements.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_ACTIVE_ELEMENTS));
+
+ fOpenFileAction.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_OPEN_FILE));
+
+ fFindOccurrences.setAction(getAction(textEditor, StructuredTextEditorActionConstants.ACTION_NAME_FIND_OCCURRENCES));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.ISourceViewerActionBarContributor#setViewerSpecificContributionsEnabled(boolean)
+ */
+ public void setViewerSpecificContributionsEnabled(boolean enabled) {
+ super.setViewerSpecificContributionsEnabled(enabled);
+
+ fShowTooltipAction.setEnabled(enabled);
+ fContentAssist.setEnabled(enabled);
+ fQuickFix.setEnabled(enabled);
+ // cleanup and format document actions do not rely on source viewer
+ // being enabled
+ // fCleanupDocument.setEnabled(enabled);
+ // fFormatDocument.setEnabled(enabled);
+
+ fFormatActiveElements.setEnabled(enabled);
+ fOpenFileAction.setEnabled(enabled);
+ fFindOccurrences.setEnabled(enabled);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/AddBlockCommentActionXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/AddBlockCommentActionXML.java
new file mode 100644
index 0000000000..5b30e11881
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/AddBlockCommentActionXML.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.ui.edit.util.StructuredTextEditorActionConstants;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.core.internal.document.CommentImpl;
+
+
+public class AddBlockCommentActionXML extends CommentActionXML {
+ protected int fCloseCommentOffset;
+ protected int fOpenCommentOffset;
+ protected IndexedRegion fSelectionEndIndexedRegion;
+ protected IndexedRegion fSelectionStartIndexedRegion;
+
+ public AddBlockCommentActionXML(ResourceBundle bundle, String prefix, ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ protected void init() {
+ super.init();
+
+ fSelectionStartIndexedRegion = fModel.getIndexedRegion(fSelectionStartOffset);
+ fSelectionEndIndexedRegion = fModel.getIndexedRegion(fSelectionEndOffset);
+
+ if (fSelectionStartIndexedRegion == null || fSelectionEndIndexedRegion == null)
+ return;
+
+ fOpenCommentOffset = fSelectionStartIndexedRegion.getStartOffset();
+ fCloseCommentOffset = fSelectionEndIndexedRegion.getEndOffset() + OPEN_COMMENT.length();
+ }
+
+ protected void processAction() {
+ if (fSelection.getLength() == 0 && fSelectionStartIndexedRegion instanceof CommentImpl)
+ return;
+
+ fModel.beginRecording(this, ResourceHandler.getString(StructuredTextEditorActionConstants.ACTION_NAME_ADD_BLOCK_COMMENT + ".tooltip")); //$NON-NLS-1$
+ fModel.aboutToChangeModel();
+
+ try {
+ fDocument.replace(fOpenCommentOffset, 0, OPEN_COMMENT);
+ fDocument.replace(fCloseCommentOffset, 0, CLOSE_COMMENT);
+ removeOpenCloseComments(fOpenCommentOffset + OPEN_COMMENT.length(), fCloseCommentOffset - fOpenCommentOffset - CLOSE_COMMENT.length());
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+
+ fModel.changedModel();
+ fModel.endRecording(this);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/BaseNodeActionManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/BaseNodeActionManager.java
new file mode 100644
index 0000000000..fc587b374e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/BaseNodeActionManager.java
@@ -0,0 +1,518 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMDataType;
+import org.eclipse.wst.common.contentmodel.CMDocument;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQueryAction;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+
+
+
+public abstract class BaseNodeActionManager {
+
+
+ /**
+ * MyMenuManager
+ */
+ public static class MyMenuManager extends MenuManager {
+ protected String title;
+
+ public MyMenuManager(String s) {
+ super(s);
+ title = s;
+ }
+
+ public boolean isEnabled() {
+ return !isEmpty();
+ }
+
+ public String toString() {
+ return title;
+ }
+ }
+
+ public static DocumentType getDoctype(Node node) {
+ Document document = (node.getNodeType() == Node.DOCUMENT_NODE) ? (Document) node : node.getOwnerDocument();
+ return document.getDoctype();
+ }
+
+ protected MenuBuilder menuBuilder = new MenuBuilder();
+ protected IStructuredModel model;
+ protected ModelQuery modelQuery;
+
+ protected BaseNodeActionManager(IStructuredModel model, ModelQuery modelQuery) {
+ this.model = model;
+ this.modelQuery = modelQuery;
+ }
+
+
+ protected void addActionHelper(IMenuManager menu, List modelQueryActionList) {
+ List actionList = new Vector();
+ for (Iterator i = modelQueryActionList.iterator(); i.hasNext();) {
+ ModelQueryAction action = (ModelQueryAction) i.next();
+ if (action.getCMNode() != null) {
+ int cmNodeType = action.getCMNode().getNodeType();
+ if (action.getKind() == ModelQueryAction.INSERT) {
+ switch (cmNodeType) {
+ case CMNode.ATTRIBUTE_DECLARATION : {
+ actionList.add(createAddAttributeAction((Element) action.getParent(), (CMAttributeDeclaration) action.getCMNode()));
+ break;
+ }
+ case CMNode.ELEMENT_DECLARATION : {
+ actionList.add(createAddElementAction(action.getParent(), (CMElementDeclaration) action.getCMNode(), action.getStartIndex()));
+ break;
+ }
+ }
+ } else if (action.getKind() == ModelQueryAction.REPLACE) {
+ if (action.getParent() != null && action.getCMNode() != null) {
+ actionList.add(createReplaceAction(action.getParent(), action.getCMNode(), action.getStartIndex(), action.getEndIndex()));
+ }
+ }
+ }
+ }
+ menuBuilder.populateMenu(menu, actionList, false);
+ }
+
+ protected void contributeAction(IMenuManager menu, Action action) {
+ if (action != null) {
+ menu.add(action);
+ }
+ }
+
+
+ public void contributeActions(IMenuManager menu, List selection) {
+ int editMode = modelQuery.getEditMode();
+ int ic = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.INCLUDE_CHILD_NODES | ModelQuery.INCLUDE_SEQUENCE_GROUPS : ModelQuery.INCLUDE_CHILD_NODES;
+ int vc = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.VALIDITY_STRICT : ModelQuery.VALIDITY_NONE;
+
+ List implicitlySelectedNodeList = null;
+
+ if (selection.size() > 0) {
+ implicitlySelectedNodeList = getSelectedNodes(selection, true);
+
+ // contribute delete actions
+ contributeDeleteActions(menu, implicitlySelectedNodeList, ic, vc);
+ }
+
+ if (selection.size() == 1) {
+ Node node = (Node) selection.get(0);
+
+ // contribute edit actions
+ contributeEditActions(menu, node);
+
+ // contribute add child actions
+ contributeAddChildActions(menu, node, ic, vc);
+
+ // contribute add before actions
+ contributeAddSiblingActions(menu, node, ic, vc);
+ }
+
+ if (selection.size() > 0) {
+ // contribute replace actions
+ contributeReplaceActions(menu, implicitlySelectedNodeList, ic, vc);
+ }
+
+ if (selection.size() == 0) {
+ Document document = ((XMLModel) model).getDocument();
+ contributeAddDocumentChildActions(menu, document, ic, vc);
+ contributeEditGrammarInformationActions(menu, document);
+ }
+ }
+
+
+ protected void contributeAddChildActions(IMenuManager menu, Node node, int ic, int vc) {
+ int nodeType = node.getNodeType();
+
+ if (nodeType == Node.ELEMENT_NODE) {
+ // 'Add Child...' and 'Add Attribute...' actions
+ //
+ Element element = (Element) node;
+
+ IMenuManager addAttributeMenu = new MyMenuManager(XMLCommonResources.getInstance().getString("_UI_MENU_ADD_ATTRIBUTE")); //$NON-NLS-1$
+ IMenuManager addChildMenu = new MyMenuManager(XMLCommonResources.getInstance().getString("_UI_MENU_ADD_CHILD")); //$NON-NLS-1$
+ menu.add(addAttributeMenu);
+ menu.add(addChildMenu);
+
+ CMElementDeclaration ed = modelQuery.getCMElementDeclaration(element);
+ if (ed != null) {
+ // add insert attribute actions
+ //
+ List modelQueryActionList = new ArrayList();
+ modelQuery.getInsertActions(element, ed, -1, ModelQuery.INCLUDE_ATTRIBUTES, vc, modelQueryActionList);
+ addActionHelper(addAttributeMenu, modelQueryActionList);
+
+ // add insert child node actions
+ //
+ modelQueryActionList = new ArrayList();
+ modelQuery.getInsertActions(element, ed, -1, ic, vc, modelQueryActionList);
+ addActionHelper(addChildMenu, modelQueryActionList);
+ }
+
+ // add PI and COMMENT
+ contributePIAndCommentActions(addChildMenu, element, ed, -1);
+
+ // add PCDATA, CDATA_SECTION
+ contributeTextNodeActions(addChildMenu, element, ed, -1);
+
+ // add NEW ELEMENT
+ contributeUnconstrainedAddElementAction(addChildMenu, element, ed, -1);
+
+ // add ATTRIBUTE
+ contributeUnconstrainedAttributeActions(addAttributeMenu, element, ed);
+ }
+ }
+
+
+ protected void contributeAddDocumentChildActions(IMenuManager menu, Document document, int ic, int vc) {
+ IMenuManager addChildMenu = new MyMenuManager(XMLCommonResources.getInstance().getString("_UI_MENU_ADD_CHILD")); //$NON-NLS-1$
+ menu.add(addChildMenu);
+
+ // add PI and COMMENT
+ contributePIAndCommentActions(addChildMenu, document, -1);
+
+ // add NEW ELEMENT
+ contributeUnconstrainedAddElementAction(addChildMenu, document, -1);
+ }
+
+
+ protected void contributeAddSiblingActions(IMenuManager menu, Node node, int ic, int vc) {
+ IMenuManager addBeforeMenu = new MyMenuManager(XMLCommonResources.getInstance().getString("_UI_MENU_ADD_BEFORE")); //$NON-NLS-1$
+ IMenuManager addAfterMenu = new MyMenuManager(XMLCommonResources.getInstance().getString("_UI_MENU_ADD_AFTER")); //$NON-NLS-1$
+ menu.add(addBeforeMenu);
+ menu.add(addAfterMenu);
+
+ Node parentNode = node.getParentNode();
+ if (parentNode != null) {
+ int index = getIndex(parentNode, node);
+ if (parentNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element parentElement = (Element) parentNode;
+ CMElementDeclaration parentED = modelQuery.getCMElementDeclaration(parentElement);
+ if (parentED != null) {
+ // 'Add Before...' and 'Add After...' actions
+ //
+ List modelQueryActionList = new ArrayList();
+ modelQuery.getInsertActions(parentElement, parentED, index, ic, vc, modelQueryActionList);
+ addActionHelper(addBeforeMenu, modelQueryActionList);
+
+ modelQueryActionList = new ArrayList();
+ modelQuery.getInsertActions(parentElement, parentED, index + 1, ic, vc, modelQueryActionList);
+ addActionHelper(addAfterMenu, modelQueryActionList);
+ }
+
+ // add COMMENT and PI before and after
+ contributePIAndCommentActions(addBeforeMenu, parentElement, parentED, index);
+ contributePIAndCommentActions(addAfterMenu, parentElement, parentED, index + 1);
+
+ // add PCDATA, CDATA_SECTION before and after
+ contributeTextNodeActions(addBeforeMenu, parentElement, parentED, index);
+ contributeTextNodeActions(addAfterMenu, parentElement, parentED, index + 1);
+
+ // add NEW ELEMENT before and after
+ contributeUnconstrainedAddElementAction(addBeforeMenu, parentElement, parentED, index);
+ contributeUnconstrainedAddElementAction(addAfterMenu, parentElement, parentED, index + 1);
+ } else if (parentNode.getNodeType() == Node.DOCUMENT_NODE) {
+ Document document = (Document) parentNode;
+ CMDocument cmDocument = modelQuery.getCorrespondingCMDocument(parentNode);
+ if (cmDocument != null) {
+ // add possible root element insertions
+ //
+ List modelQueryActionList = new ArrayList();
+ modelQuery.getInsertActions(document, cmDocument, index, ic, vc, modelQueryActionList);
+ addActionHelper(addAfterMenu, modelQueryActionList);
+
+ modelQueryActionList = new ArrayList();
+ modelQuery.getInsertActions(document, cmDocument, index + 1, ic, vc, modelQueryActionList);
+ addActionHelper(addAfterMenu, modelQueryActionList);
+ }
+
+ // add COMMENT and PI before and after
+ contributePIAndCommentActions(addBeforeMenu, document, index);
+ contributePIAndCommentActions(addAfterMenu, document, index + 1);
+
+ // add ELEMENT before and after
+ contributeUnconstrainedAddElementAction(addBeforeMenu, document, index);
+ contributeUnconstrainedAddElementAction(addAfterMenu, document, index + 1);
+ }
+ }
+ }
+
+ protected void contributeDeleteActions(IMenuManager menu, List list, int ic, int vc) {
+ boolean canRemove = modelQuery.canRemove(list, vc);
+
+
+ // a delete action with an empty list will produce a disabled menu
+ // item
+ //
+ List resultList = canRemove ? list : Collections.EMPTY_LIST;
+ contributeAction(menu, createDeleteAction(resultList));
+ }
+
+
+ protected void contributeEditActions(IMenuManager menu, Node node) {
+ contributeEditGrammarInformationActions(menu, node);
+
+ if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+ contributeAction(menu, createEditProcessingInstructionAction((ProcessingInstruction) node));
+ } else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ contributeAction(menu, createEditAttributeAction((Attr) node, null));
+ }
+ }
+
+
+ protected void contributeEditGrammarInformationActions(IMenuManager menu, Node node) {
+ Document document = node.getNodeType() == Node.DOCUMENT_NODE ? (Document) node : node.getOwnerDocument();
+
+ DocumentType doctype = getDoctype(node);
+ if (doctype == null) {
+ contributeAction(menu, createAddDoctypeAction(document, -1));
+ }
+
+ if (node.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ contributeAction(menu, createEditDoctypeAction((DocumentType) node));
+ }
+
+ if (doctype == null && getRootElement(document) != null) {
+ contributeAction(menu, createEditSchemaInfoAction(getRootElement(document)));
+ }
+ }
+
+ protected void contributePIAndCommentActions(IMenuManager menu, Document document, int index) {
+ // test to make sure that the index isn't before the XML declaration
+ //
+ contributeAction(menu, createAddCommentAction(document, index));
+ contributeAction(menu, createAddProcessingInstructionAction(document, index));
+ }
+
+
+ protected void contributePIAndCommentActions(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd, int index) {
+ if (parentEd == null || isCommentAllowed(parentEd)) {
+ contributeAction(menu, createAddCommentAction(parentElement, index));
+ contributeAction(menu, createAddProcessingInstructionAction(parentElement, index));
+ }
+ }
+
+
+ protected void contributeReplaceActions(IMenuManager menu, List selectedNodeList, int ic, int vc) {
+ // 'Replace With...' actions
+ //
+ IMenuManager replaceWithMenu = new MyMenuManager(XMLCommonResources.getInstance().getString("_UI_MENU_REPLACE_WITH")); //$NON-NLS-1$
+ menu.add(replaceWithMenu);
+
+ if (modelQuery.getEditMode() == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT && selectedNodeList.size() > 0) {
+ Node node = (Node) selectedNodeList.get(0);
+ Node parentNode = node.getParentNode();
+ if (parentNode != null && parentNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element parentElement = (Element) parentNode;
+ CMElementDeclaration parentED = modelQuery.getCMElementDeclaration(parentElement);
+ if (parentED != null) {
+ List replaceActionList = new Vector();
+ modelQuery.getReplaceActions(parentElement, parentED, selectedNodeList, ic, vc, replaceActionList);
+ addActionHelper(replaceWithMenu, replaceActionList);
+ }
+ }
+ }
+ }
+
+ protected void contributeTextNodeActions(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd, int index) {
+ if (parentEd == null || isTextAllowed(parentEd)) {
+ CMDataType dataType = parentEd != null ? parentEd.getDataType() : null;
+ contributeAction(menu, createAddPCDataAction(parentElement, dataType, index));
+ contributeAction(menu, createAddCDataSectionAction(parentElement, index));
+ }
+ }
+
+
+ protected void contributeUnconstrainedAddElementAction(IMenuManager menu, Document document, int index) {
+ if (isUnconstrainedActionAllowed()) {
+ if (getRootElement(document) == null) {
+ int xmlDeclarationIndex = -1;
+ int doctypeIndex = -1;
+ NodeList nodeList = document.getChildNodes();
+ int nodeListLength = nodeList.getLength();
+ for (int i = 0; i < nodeListLength; i++) {
+ Node node = nodeList.item(i);
+ int nodeType = node.getNodeType();
+ if (nodeType == Node.DOCUMENT_TYPE_NODE) {
+ doctypeIndex = i;
+ break;
+ } else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
+ ProcessingInstruction pi = (ProcessingInstruction) node;
+ if (pi.getTarget().equalsIgnoreCase("xml") && xmlDeclarationIndex == -1) { //$NON-NLS-1$
+ xmlDeclarationIndex = i;
+ }
+ }
+ }
+
+ if ((xmlDeclarationIndex == -1 || index > xmlDeclarationIndex) && (doctypeIndex == -1 || index > doctypeIndex)) {
+ contributeAction(menu, createAddElementAction(document, null, index));
+ }
+ }
+ }
+ }
+
+
+ protected void contributeUnconstrainedAddElementAction(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd, int index) {
+ if (isUnconstrainedActionAllowed()) {
+ if (parentEd == null || parentEd.getProperty("isInferred") == Boolean.TRUE || (modelQuery.getEditMode() != ModelQuery.EDIT_MODE_CONSTRAINED_STRICT && isElementAllowed(parentEd))) { //$NON-NLS-1$
+ contributeAction(menu, createAddElementAction(parentElement, null, index));
+ }
+ }
+ }
+
+
+ protected void contributeUnconstrainedAttributeActions(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd) {
+ if (isUnconstrainedActionAllowed()) {
+ if (parentEd == null || parentEd.getProperty("isInferred") == Boolean.TRUE || modelQuery.getEditMode() != ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) { //$NON-NLS-1$
+ contributeAction(menu, createAddAttributeAction(parentElement, null));
+ }
+ }
+ }
+
+ abstract protected Action createAddAttributeAction(Element parent, CMAttributeDeclaration ad);
+
+ abstract protected Action createAddCDataSectionAction(Node parent, int index);
+
+ abstract protected Action createAddCommentAction(Node parent, int index);
+
+ abstract protected Action createAddDoctypeAction(Document parent, int index);
+
+ abstract protected Action createAddElementAction(Node parent, CMElementDeclaration ed, int index);
+
+ abstract protected Action createAddPCDataAction(Node parent, CMDataType dataType, int index);
+
+ abstract protected Action createAddProcessingInstructionAction(Node parent, int index);
+
+ abstract protected Action createAddSchemaInfoAction(Element element);
+
+ abstract protected Action createDeleteAction(List selection);
+
+ abstract protected Action createEditAttributeAction(Attr attribute, CMAttributeDeclaration ad);
+
+ abstract protected Action createEditDoctypeAction(DocumentType doctype);
+
+ abstract protected Action createEditProcessingInstructionAction(ProcessingInstruction pi);
+
+ abstract protected Action createEditSchemaInfoAction(Element element);
+
+ abstract protected Action createRenameAction(Node node);
+
+ abstract protected Action createReplaceAction(Node parent, CMNode cmnode, int startIndex, int endIndex);
+
+
+ public int getIndex(Node parentNode, Node child) {
+ NodeList nodeList = parentNode.getChildNodes();
+ int index = -1;
+ int size = nodeList.getLength();
+ for (int i = 0; i < size; i++) {
+ if (nodeList.item(i) == child) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+
+ public Node getRefChildNodeAtIndex(Node parent, int index) {
+ NodeList nodeList = parent.getChildNodes();
+ Node refChild = (index >= 0 && index < nodeList.getLength()) ? nodeList.item(index) : null;
+ return refChild;
+ }
+
+
+ protected Element getRootElement(Document document) {
+ Element result = null;
+ NodeList nodeList = document.getChildNodes();
+ int nodeListLength = nodeList.getLength();
+ for (int i = 0; i < nodeListLength; i++) {
+ Node node = nodeList.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ result = (Element) node;
+ break;
+ }
+ }
+ return result;
+ }
+
+
+ protected List getSelectedNodes(List list, boolean includeTextNodes) {
+ List result = new ArrayList(0);
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ Object object = i.next();
+ if (object instanceof Node) {
+ Node node = (Node) object;
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ if (includeTextNodes) {
+ result.add(object);
+ }
+ } else {
+ result.add(node);
+ }
+ }
+ }
+ return result;
+ }
+
+
+ protected boolean isCommentAllowed(CMElementDeclaration parentEd) {
+ int contentType = parentEd.getContentType();
+ return contentType == CMElementDeclaration.ELEMENT || contentType == CMElementDeclaration.MIXED || contentType == CMElementDeclaration.PCDATA || contentType == CMElementDeclaration.ANY;
+ }
+
+
+ protected boolean isElementAllowed(CMElementDeclaration parentEd) {
+ int contentType = parentEd.getContentType();
+ return contentType == CMElementDeclaration.ELEMENT || contentType == CMElementDeclaration.MIXED || contentType == CMElementDeclaration.ANY;
+ }
+
+
+ protected boolean isTextAllowed(CMElementDeclaration parentEd) {
+ int contentType = parentEd.getContentType();
+ return contentType == CMElementDeclaration.MIXED || contentType == CMElementDeclaration.PCDATA || contentType == CMElementDeclaration.ANY;
+ }
+
+
+ protected boolean isUnconstrainedActionAllowed() {
+ return true;
+ }
+
+
+ protected boolean isWhitespaceTextNode(Node node) {
+ return (node != null) && (node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().trim().length() == 0);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CleanupActionXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CleanupActionXML.java
new file mode 100644
index 0000000000..e5a3a13cce
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CleanupActionXML.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.cleanup.IStructuredCleanupProcessor;
+import org.eclipse.wst.sse.ui.edit.util.CleanupAction;
+import org.eclipse.wst.xml.core.cleanup.CleanupProcessorXML;
+
+
+public class CleanupActionXML extends CleanupAction {
+ protected IStructuredCleanupProcessor fCleanupProcessor;
+
+ public CleanupActionXML(ResourceBundle bundle, String prefix, ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ protected Dialog getCleanupDialog(Shell shell) {
+ if (fCleanupDialog == null)
+ fCleanupDialog = new CleanupDialogXML(shell);
+
+ return fCleanupDialog;
+ }
+
+ protected IStructuredCleanupProcessor getCleanupProcessor() {
+ if (fCleanupProcessor == null)
+ fCleanupProcessor = new CleanupProcessorXML();
+
+ return fCleanupProcessor;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CleanupDialogXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CleanupDialogXML.java
new file mode 100644
index 0000000000..4e059c8592
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CleanupDialogXML.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.wst.common.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.preferences.CommonModelPreferenceNames;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.core.XMLModelPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+
+
+public class CleanupDialogXML extends Dialog implements SelectionListener {
+ protected Button fCheckBoxCompressEmptyElementTags;
+ protected Button fCheckBoxConvertEOLCodes;
+ protected Button fCheckBoxFormatSource;
+ protected Button fCheckBoxInsertMissingTags;
+ protected Button fCheckBoxInsertRequiredAttrs;
+ protected Button fCheckBoxQuoteAttrValues;
+ protected IStructuredModel fModel = null;
+ protected Preferences fPreferences = null;
+ protected Button fRadioButtonAttrNameCaseAsis;
+ protected Button fRadioButtonAttrNameCaseLower;
+ protected Button fRadioButtonAttrNameCaseUpper;
+ protected Button fRadioButtonConvertEOLMac;
+ protected Button fRadioButtonConvertEOLUnix;
+ protected Button fRadioButtonConvertEOLWindows;
+
+ protected Button fRadioButtonTagNameCaseAsis;
+ protected Button fRadioButtonTagNameCaseLower;
+ protected Button fRadioButtonTagNameCaseUpper;
+
+ public CleanupDialogXML(Shell shell) {
+
+ super(shell);
+ }
+
+ public Control createDialogArea(Composite parent) {
+
+ getShell().setText(ResourceHandler.getString("Cleanup_UI_")); //$NON-NLS-1$ = "Cleanup"
+ Composite composite = new Composite(parent, SWT.NULL);
+ createDialogAreaInComposite(composite);
+ initializeOptions();
+ return composite;
+ }
+
+ protected void createDialogAreaInComposite(Composite composite) {
+
+ WorkbenchHelp.setHelp(composite, IHelpContextIds.CLEANUP_XML_HELPID); // use
+ // XML
+ // specific
+ // help
+
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ layout.makeColumnsEqualWidth = true;
+ composite.setLayout(layout);
+
+ // Compress empty element tags
+ fCheckBoxCompressEmptyElementTags = new Button(composite, SWT.CHECK);
+ fCheckBoxCompressEmptyElementTags.setText(ResourceHandler.getString("Compress_empty_element_tags_UI_")); //$NON-NLS-1$
+ fCheckBoxCompressEmptyElementTags.addSelectionListener(this);
+
+ // Insert missing required attrs
+ fCheckBoxInsertRequiredAttrs = new Button(composite, SWT.CHECK);
+ fCheckBoxInsertRequiredAttrs.setText(ResourceHandler.getString("Insert_required_attributes_UI_")); //$NON-NLS-1$
+ fCheckBoxInsertRequiredAttrs.addSelectionListener(this);
+
+ // Insert missing begin/end tags
+ fCheckBoxInsertMissingTags = new Button(composite, SWT.CHECK);
+ fCheckBoxInsertMissingTags.setText(ResourceHandler.getString("Insert_missing_tags_UI_")); //$NON-NLS-1$ = "Insert missing tags"
+ fCheckBoxInsertMissingTags.addSelectionListener(this);
+
+ // Quote attribute values
+ fCheckBoxQuoteAttrValues = new Button(composite, SWT.CHECK);
+ fCheckBoxQuoteAttrValues.setText(ResourceHandler.getString("Quote_attribute_values_UI_")); //$NON-NLS-1$ = "Quote attribute values"
+ fCheckBoxQuoteAttrValues.addSelectionListener(this);
+
+ // Format source
+ fCheckBoxFormatSource = new Button(composite, SWT.CHECK);
+ fCheckBoxFormatSource.setText(ResourceHandler.getString("Format_source_UI_")); //$NON-NLS-1$ = "Format source"
+ fCheckBoxFormatSource.addSelectionListener(this);
+
+ // Convert EOL code
+ fCheckBoxConvertEOLCodes = new Button(composite, SWT.CHECK);
+ fCheckBoxConvertEOLCodes.setText(ResourceHandler.getString("Convert_EOL_codes_UI_")); //$NON-NLS-1$ = "Convert end-of-line codes"
+ fCheckBoxConvertEOLCodes.addSelectionListener(this);
+ Composite EOLCodes = new Composite(composite, SWT.NULL);
+ GridLayout hLayout = new GridLayout();
+ hLayout.numColumns = 3;
+ EOLCodes.setLayout(hLayout);
+ fRadioButtonConvertEOLWindows = new Button(EOLCodes, SWT.RADIO);
+ fRadioButtonConvertEOLWindows.setText(ResourceHandler.getString("EOL_Windows_UI")); //$NON-NLS-1$ = "Windows"
+ fRadioButtonConvertEOLWindows.addSelectionListener(this);
+ fRadioButtonConvertEOLUnix = new Button(EOLCodes, SWT.RADIO);
+ fRadioButtonConvertEOLUnix.setText(ResourceHandler.getString("EOL_Unix_UI")); //$NON-NLS-1$ = "Unix"
+ fRadioButtonConvertEOLUnix.addSelectionListener(this);
+ fRadioButtonConvertEOLMac = new Button(EOLCodes, SWT.RADIO);
+ fRadioButtonConvertEOLMac.setText(ResourceHandler.getString("EOL_Mac_UI")); //$NON-NLS-1$ = "Mac"
+ fRadioButtonConvertEOLMac.addSelectionListener(this);
+ }
+
+ protected void enableEOLCodeRadios(boolean enable) {
+
+ if ((fRadioButtonConvertEOLWindows != null) && (fRadioButtonConvertEOLUnix != null) && (fRadioButtonConvertEOLMac != null)) {
+ fRadioButtonConvertEOLWindows.setEnabled(enable);
+ fRadioButtonConvertEOLUnix.setEnabled(enable);
+ fRadioButtonConvertEOLMac.setEnabled(enable);
+ if (!fRadioButtonConvertEOLWindows.getSelection() && !fRadioButtonConvertEOLUnix.getSelection() && !fRadioButtonConvertEOLMac.getSelection())
+ fRadioButtonConvertEOLWindows.setSelection(true);
+ }
+ }
+
+ protected Preferences getModelPreferences() {
+ return XMLModelPlugin.getDefault().getPluginPreferences();
+ }
+
+ protected void initializeOptions() {
+
+ fCheckBoxCompressEmptyElementTags.setSelection(getModelPreferences().getBoolean(CommonModelPreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS));
+ fCheckBoxInsertRequiredAttrs.setSelection(getModelPreferences().getBoolean(CommonModelPreferenceNames.INSERT_REQUIRED_ATTRS));
+ fCheckBoxInsertMissingTags.setSelection(getModelPreferences().getBoolean(CommonModelPreferenceNames.INSERT_MISSING_TAGS));
+ fCheckBoxQuoteAttrValues.setSelection(getModelPreferences().getBoolean(CommonModelPreferenceNames.QUOTE_ATTR_VALUES));
+ fCheckBoxFormatSource.setSelection(getModelPreferences().getBoolean(CommonModelPreferenceNames.FORMAT_SOURCE));
+ fCheckBoxConvertEOLCodes.setSelection(getModelPreferences().getBoolean(CommonModelPreferenceNames.CONVERT_EOL_CODES));
+ String EOLCode = getModelPreferences().getString(CommonModelPreferenceNames.CLEANUP_EOL_CODE);
+ if (EOLCode.compareTo(CommonEncodingPreferenceNames.LF) == 0)
+ fRadioButtonConvertEOLUnix.setSelection(true);
+ else if (EOLCode.compareTo(CommonEncodingPreferenceNames.CR) == 0)
+ fRadioButtonConvertEOLMac.setSelection(true);
+ else
+ fRadioButtonConvertEOLWindows.setSelection(true);
+ enableEOLCodeRadios(fCheckBoxConvertEOLCodes.getSelection());
+ }
+
+ protected void okPressed() {
+
+ storeOptions();
+ super.okPressed();
+ }
+
+ public void setModel(IStructuredModel model) {
+
+ fModel = model;
+ }
+
+ protected void storeOptions() {
+
+ getModelPreferences().setValue(CommonModelPreferenceNames.COMPRESS_EMPTY_ELEMENT_TAGS, fCheckBoxCompressEmptyElementTags.getSelection());
+ getModelPreferences().setValue(CommonModelPreferenceNames.INSERT_REQUIRED_ATTRS, fCheckBoxInsertRequiredAttrs.getSelection());
+ getModelPreferences().setValue(CommonModelPreferenceNames.INSERT_MISSING_TAGS, fCheckBoxInsertMissingTags.getSelection());
+ getModelPreferences().setValue(CommonModelPreferenceNames.QUOTE_ATTR_VALUES, fCheckBoxQuoteAttrValues.getSelection());
+ getModelPreferences().setValue(CommonModelPreferenceNames.FORMAT_SOURCE, fCheckBoxFormatSource.getSelection());
+ getModelPreferences().setValue(CommonModelPreferenceNames.CONVERT_EOL_CODES, fCheckBoxConvertEOLCodes.getSelection());
+ if (fRadioButtonConvertEOLUnix.getSelection()) {
+ getModelPreferences().setValue(CommonModelPreferenceNames.CLEANUP_EOL_CODE, CommonEncodingPreferenceNames.LF);
+ } else if (fRadioButtonConvertEOLMac.getSelection()) {
+ getModelPreferences().setValue(CommonModelPreferenceNames.CLEANUP_EOL_CODE, CommonEncodingPreferenceNames.CR);
+ } else {
+ getModelPreferences().setValue(CommonModelPreferenceNames.CLEANUP_EOL_CODE, CommonEncodingPreferenceNames.CRLF);
+ }
+ // explicitly save plugin preferences so values are stored
+ XMLModelPlugin.getDefault().savePluginPreferences();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+
+ widgetSelected(e);
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+
+ getButton(OK).setEnabled((fRadioButtonTagNameCaseLower != null && (fRadioButtonTagNameCaseLower.getSelection() || fRadioButtonTagNameCaseUpper.getSelection())) || (fRadioButtonAttrNameCaseLower != null && (fRadioButtonAttrNameCaseLower.getSelection() || fRadioButtonAttrNameCaseUpper.getSelection())) || fCheckBoxInsertMissingTags.getSelection() || fCheckBoxQuoteAttrValues.getSelection() || fCheckBoxFormatSource.getSelection() || fCheckBoxConvertEOLCodes.getSelection() || (fRadioButtonConvertEOLUnix != null && (fRadioButtonConvertEOLUnix.getSelection() || fRadioButtonConvertEOLMac.getSelection() || fRadioButtonConvertEOLWindows.getSelection())));
+ if (e.widget == fCheckBoxConvertEOLCodes)
+ enableEOLCodeRadios(fCheckBoxConvertEOLCodes.getSelection());
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CommentActionXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CommentActionXML.java
new file mode 100644
index 0000000000..f2b8c13f71
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/CommentActionXML.java
@@ -0,0 +1,207 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextEditorAction;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.ui.IModelProvider;
+import org.eclipse.wst.sse.ui.edit.util.StructuredTextEditorActionConstants;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+
+
+public class CommentActionXML extends TextEditorAction {
+ protected static final String CLOSE_COMMENT = "-->"; //$NON-NLS-1$
+ protected static final String OPEN_COMMENT = "<!--"; //$NON-NLS-1$
+ protected IDocument fDocument;
+ protected IStructuredModel fModel;
+ protected ITextSelection fSelection;
+ protected int fSelectionEndLine;
+ protected int fSelectionEndLineOffset;
+ protected int fSelectionEndOffset;
+ protected Position fSelectionPosition;
+ protected int fSelectionStartLine;
+ protected int fSelectionStartLineOffset;
+ protected int fSelectionStartOffset;
+ protected boolean fUpdateSelection;
+
+ public CommentActionXML(ResourceBundle bundle, String prefix, ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ protected void comment(int openCommentOffset, int closeCommentOffset) {
+ try {
+ fDocument.replace(openCommentOffset, 0, OPEN_COMMENT);
+ fDocument.replace(closeCommentOffset, 0, CLOSE_COMMENT);
+ removeOpenCloseComments(openCommentOffset + OPEN_COMMENT.length(), closeCommentOffset - openCommentOffset - CLOSE_COMMENT.length());
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+
+ protected ITextSelection getCurrentSelection() {
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ ISelectionProvider provider = editor.getSelectionProvider();
+ if (provider != null) {
+ ISelection selection = provider.getSelection();
+ if (selection instanceof ITextSelection)
+ return (ITextSelection) selection;
+ }
+ }
+ return null;
+ }
+
+ protected void init() {
+ ITextEditor editor = getTextEditor();
+ if (editor == null)
+ return;
+
+ IDocumentProvider docProvider = editor.getDocumentProvider();
+ if (docProvider == null || !(docProvider instanceof IModelProvider))
+ return;
+
+ IModelProvider modelProvider = (IModelProvider) docProvider;
+
+ IEditorInput input = editor.getEditorInput();
+ if (input == null)
+ return;
+
+ fDocument = modelProvider.getDocument(input);
+ fModel = modelProvider.getModel(input);
+ if (fDocument == null || fModel == null)
+ return;
+
+ fSelection = getCurrentSelection();
+ fSelectionStartOffset = fSelection.getOffset();
+ fSelectionEndOffset = fSelectionStartOffset + fSelection.getLength();
+
+ // add selection position to document
+ fSelectionPosition = new Position(fSelection.getOffset(), fSelection.getLength());
+ try {
+ fDocument.addPosition(fSelectionPosition);
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+
+ try {
+ fSelectionStartLine = fDocument.getLineOfOffset(fSelectionStartOffset);
+ fSelectionEndLine = fDocument.getLineOfOffset(fSelectionEndOffset);
+ fSelectionStartLineOffset = fDocument.getLineOffset(fSelectionStartLine);
+ fSelectionEndLineOffset = fDocument.getLineOffset(fSelectionEndLine);
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+
+ // adjust selection end line
+ if (fSelectionEndLine > fSelectionStartLine && fSelectionEndLineOffset == fSelectionEndOffset)
+ fSelectionEndLine--;
+ }
+
+ protected boolean isCommentLine(int line) {
+ try {
+ IRegion region = fDocument.getLineInformation(line);
+ String string = fDocument.get(region.getOffset(), region.getLength()).trim();
+ return string.length() >= OPEN_COMMENT.length() + CLOSE_COMMENT.length() && string.startsWith(OPEN_COMMENT) && string.endsWith(CLOSE_COMMENT);
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+
+ protected void prepareSelection() {
+ fUpdateSelection = fSelection.getLength() > 0 && fSelectionStartLineOffset == fSelectionStartOffset && !isCommentLine(fSelectionStartLine);
+ }
+
+ protected void processAction() {
+ fModel.beginRecording(this, ResourceHandler.getString(StructuredTextEditorActionConstants.ACTION_NAME_COMMENT + ".tooltip")); //$NON-NLS-1$
+ fModel.aboutToChangeModel();
+
+ for (int i = fSelectionStartLine; i <= fSelectionEndLine; i++) {
+ try {
+ if (fDocument.getLineLength(i) > 0 && !isCommentLine(i)) {
+ int openCommentOffset = fDocument.getLineOffset(i);
+ int lineDelimiterLength = fDocument.getLineDelimiter(i) == null ? 0 : fDocument.getLineDelimiter(i).length();
+ int closeCommentOffset = openCommentOffset + fDocument.getLineLength(i) - lineDelimiterLength + OPEN_COMMENT.length();
+ comment(openCommentOffset, closeCommentOffset);
+ }
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+
+ fModel.changedModel();
+ fModel.endRecording(this);
+ }
+
+ protected void removeOpenCloseComments(int offset, int length) {
+ try {
+ int adjusted_length = length;
+
+ // remove open comments
+ String string = fDocument.get(offset, length);
+ int index = string.lastIndexOf(OPEN_COMMENT);
+ while (index != -1) {
+ fDocument.replace(offset + index, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+ index = string.lastIndexOf(OPEN_COMMENT, index - 1);
+ adjusted_length -= OPEN_COMMENT.length();
+ }
+
+ // remove close comments
+ string = fDocument.get(offset, adjusted_length);
+ index = string.lastIndexOf(CLOSE_COMMENT);
+ while (index != -1) {
+ fDocument.replace(offset + index, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+ index = string.lastIndexOf(CLOSE_COMMENT, index - 1);
+ }
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+
+ public void run() {
+ init();
+ prepareSelection();
+ processAction();
+ updateSelection();
+ }
+
+ protected void setCurrentSelection(ITextSelection selection) {
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ ISelectionProvider provider = editor.getSelectionProvider();
+ if (provider != null) {
+ provider.setSelection(selection);
+ }
+ }
+ }
+
+ protected void updateSelection() {
+ if (fUpdateSelection) {
+ ITextSelection selection = new TextSelection(fDocument, fSelectionPosition.getOffset() - OPEN_COMMENT.length(), fSelectionPosition.getLength() + OPEN_COMMENT.length());
+ setCurrentSelection(selection);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditAttributeAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditAttributeAction.java
new file mode 100644
index 0000000000..63ab5c228b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditAttributeAction.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.actions;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.ui.dialogs.EditAttributeDialog;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+
+public class EditAttributeAction extends NodeAction {
+ protected static ImageDescriptor imageDescriptor;
+
+ public static ImageDescriptor createImageDescriptor() {
+ if (imageDescriptor == null) {
+ imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+ }
+ return imageDescriptor;
+ }
+
+ protected Attr attr;
+ protected AbstractNodeActionManager manager;
+ protected Element ownerElement;
+ protected String title;
+
+ public EditAttributeAction(AbstractNodeActionManager manager, Element ownerElement, Attr attr, String actionLabel, String title) {
+ this.manager = manager;
+ this.ownerElement = ownerElement;
+ this.attr = attr;
+ this.title = title;
+ setText(actionLabel);
+ // assume if attr is null then this is an 'Add' that requires action
+ // an icons... otherwise this is an edit
+ if (attr == null) {
+ setImageDescriptor(createImageDescriptor());
+ }
+ }
+
+ public String getUndoDescription() {
+ return title;
+ }
+
+ public void run() {
+ manager.beginNodeAction(this);
+ Shell shell = XMLCommonResources.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+ EditAttributeDialog dialog = new EditAttributeDialog(shell, ownerElement, attr);
+ dialog.create();
+ dialog.getShell().setText(title);
+ dialog.setBlockOnOpen(true);
+ dialog.open();
+
+ if (dialog.getReturnCode() == Window.OK) {
+ if (attr != null) {
+ ownerElement.removeAttributeNode(attr);
+ }
+ Document document = ownerElement.getOwnerDocument();
+ Attr newAttribute = document.createAttribute(dialog.getAttributeName());
+ newAttribute.setValue(dialog.getAttributeValue());
+ ownerElement.setAttributeNode(newAttribute);
+ manager.setViewerSelection(newAttribute);
+ }
+ manager.endNodeAction(this);
+ }
+}
+
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditDoctypeAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditDoctypeAction.java
new file mode 100644
index 0000000000..dabe610434
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditDoctypeAction.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.actions;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLDocumentType;
+import org.eclipse.wst.xml.core.internal.document.DocumentImpl;
+import org.eclipse.wst.xml.ui.dialogs.EditDoctypeDialog;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+
+/**
+ * EditDoctypeAction
+ */
+public class EditDoctypeAction extends Action {
+ protected DocumentType doctype;
+ protected Document document;
+ protected IStructuredModel model;
+ protected String resourceLocation;
+ protected String title;
+
+ /**
+ * This constructor is used to create a new doctype.
+ */
+ public EditDoctypeAction(IStructuredModel model, Document document, String resourceLocation, String title) {
+ setText(title);
+ this.model = model;
+ this.document = document;
+ this.resourceLocation = resourceLocation;
+ this.title = title;
+ }
+
+ /**
+ * This constructor is used to edit an exisitng doctype.
+ */
+ public EditDoctypeAction(IStructuredModel model, DocumentType doctype, String resourceLocation, String title) {
+ setText(title);
+ this.model = model;
+ this.doctype = doctype;
+ this.resourceLocation = resourceLocation;
+ this.title = title;
+ }
+
+
+ protected DocumentType createDoctype(EditDoctypeDialog dialog, Document document) {
+ DocumentType result = null;
+ if (document instanceof DocumentImpl) {
+ XMLDocument documentImpl = (XMLDocument) document;
+ XMLDocumentType doctypeImpl = (XMLDocumentType) documentImpl.createDoctype(dialog.getName());
+ doctypeImpl.setPublicId(dialog.getPublicId());
+ doctypeImpl.setSystemId(dialog.getSystemId());
+ result = doctypeImpl;
+ }
+ return result;
+ }
+
+ private Display getDisplay() {
+
+ return PlatformUI.getWorkbench().getDisplay();
+ }
+
+
+ protected String getRootElementName(Document document) {
+ Element rootElement = null;
+ NodeList nodeList = document.getChildNodes();
+ int nodeListLength = nodeList.getLength();
+ for (int i = 0; i < nodeListLength; i++) {
+ Node childNode = nodeList.item(i);
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+ rootElement = (Element) childNode;
+ break;
+ }
+ }
+ return rootElement != null ? rootElement.getNodeName() : XMLCommonResources.getInstance().getString("_UI_LABEL_ROOT_ELEMENT_VALUE"); //$NON-NLS-1$
+ }
+
+ public String getUndoDescription() {
+ return title;
+ }
+
+
+ protected void insertDoctype(DocumentType doctype, Document document) {
+ Node refChild = null;
+ NodeList nodeList = document.getChildNodes();
+ int nodeListLength = nodeList.getLength();
+ for (int i = 0; i < nodeListLength; i++) {
+ Node childNode = nodeList.item(i);
+ if (childNode.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE || childNode.getNodeType() == Node.COMMENT_NODE) {
+ // continue on to the nextNode
+ } else {
+ refChild = childNode;
+ break;
+ }
+ }
+
+ document.insertBefore(doctype, refChild);
+ //manager.reformat(doctype, false);
+ }
+
+ public void run() {
+ model.beginRecording(this, getUndoDescription());
+ //Shell shell =
+ // XMLCommonUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+ Shell shell = getDisplay().getActiveShell();
+ EditDoctypeDialog dialog = showEditDoctypeDialog(shell);
+
+ if (dialog.getReturnCode() == Window.OK) {
+ if (doctype != null) {
+ updateDoctype(dialog, doctype);
+ } else if (document != null) {
+ DocumentType doctype = createDoctype(dialog, document);
+ if (doctype != null) {
+ insertDoctype(doctype, document);
+ }
+ }
+ }
+ model.endRecording(this);
+ }
+
+ protected EditDoctypeDialog showEditDoctypeDialog(Shell shell) {
+ EditDoctypeDialog dialog = null;
+
+ if (doctype != null) {
+ dialog = new EditDoctypeDialog(shell, doctype);
+ if (title == null) {
+ title = XMLCommonResources.getInstance().getString("_UI_LABEL_EDIT_DOCTYPE"); //$NON-NLS-1$
+ }
+ } else if (document != null) {
+ String rootElementName = getRootElementName(document);
+ dialog = new EditDoctypeDialog(shell, rootElementName, "", rootElementName + ".dtd"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (title == null) {
+ title = XMLCommonResources.getInstance().getString("_UI_MENU_ADD_DTD_INFORMATION_TITLE"); //$NON-NLS-1$
+ }
+ }
+
+ dialog.setComputeSystemId(doctype == null || doctype.getSystemId() == null || doctype.getSystemId().trim().length() == 0);
+
+ dialog.setErrorChecking(false);//!model.getType().equals(IStructuredModel.HTML));
+ dialog.create();
+ dialog.getShell().setText(title);
+ dialog.setBlockOnOpen(true);
+ dialog.setResourceLocation(new Path(resourceLocation));
+ dialog.open();
+
+ return dialog;
+ }
+
+
+ protected void updateDoctype(EditDoctypeDialog dialog, DocumentType doctype) {
+ if (doctype instanceof XMLDocumentType) {
+ XMLDocumentType doctypeImpl = (XMLDocumentType) doctype;
+ if (doctypeImpl.getName().equals(dialog.getName())) {
+ doctypeImpl.setPublicId(dialog.getPublicId());
+ doctypeImpl.setSystemId(dialog.getSystemId());
+ } else {
+ // we need to create a new one and remove the old
+ //
+ Document document = doctype.getOwnerDocument();
+ DocumentType newDoctype = createDoctype(dialog, document);
+ document.insertBefore(newDoctype, doctype);
+ document.removeChild(doctype);
+ //manager.reformat(newDoctype, false);
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditElementAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditElementAction.java
new file mode 100644
index 0000000000..081be78958
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditElementAction.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.ui.dialogs.EditElementDialog;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+
+public class EditElementAction extends NodeAction {
+
+ protected static ImageDescriptor imageDescriptor;
+
+ public static ImageDescriptor createImageDescriptor() {
+ if (imageDescriptor == null) {
+ imageDescriptor = XMLEditorPluginImageHelper.getInstance().getImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ELEMENT);
+ }
+ return imageDescriptor;
+ }
+
+ protected Element element;
+ protected int insertionIndex = -1;
+ protected AbstractNodeActionManager manager;
+ protected Node parent;
+ protected String title;
+
+ public EditElementAction(AbstractNodeActionManager manager, Element element, String actionLabel, String dialogTitle) {
+ this(manager, element.getParentNode(), -1, element, actionLabel, dialogTitle);
+ }
+
+ protected EditElementAction(AbstractNodeActionManager manager, Node parent, int index, Element element, String actionLabel, String title) {
+ this.manager = manager;
+ this.parent = parent;
+ this.insertionIndex = index;
+ this.element = element;
+ this.title = title;
+ setText(actionLabel);
+ if (element == null) {
+ setImageDescriptor(createImageDescriptor());
+ }
+ }
+
+ public EditElementAction(AbstractNodeActionManager manager, Node parent, int index, String actionLabel, String title) {
+ this(manager, parent, index, null, actionLabel, title);
+ }
+
+ public String getUndoDescription() {
+ return title;
+ }
+
+ public void run() {
+ manager.beginNodeAction(this);
+ Shell shell = XMLCommonResources.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+ EditElementDialog dialog = new EditElementDialog(shell, element);
+ dialog.create();
+ dialog.getShell().setText(title);
+ dialog.setBlockOnOpen(true);
+ dialog.open();
+
+ if (dialog.getReturnCode() == Window.OK) {
+ Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+ if (element != null) {
+ // here we need to do a rename... which seems to be quite hard
+ // to do :-(
+ if (element instanceof XMLElement) {
+ XMLElement elementImpl = (XMLElement) element;
+ XMLModel model = elementImpl.getModel();
+ String oldName = elementImpl.getNodeName();
+ String newName = dialog.getElementName();
+ setStructuredDocumentRegionElementName(model, elementImpl.getStartStructuredDocumentRegion(), oldName, newName);
+ setStructuredDocumentRegionElementName(model, elementImpl.getEndStructuredDocumentRegion(), oldName, newName);
+ }
+ } else {
+ Element newElement = document.createElement(dialog.getElementName());
+ NodeList nodeList = parent.getChildNodes();
+ int nodeListLength = nodeList.getLength();
+ Node refChild = insertionIndex < nodeListLength && insertionIndex >= 0 ? nodeList.item(insertionIndex) : null;
+ parent.insertBefore(newElement, refChild);
+ manager.reformat(newElement, false);
+ manager.setViewerSelection(newElement);
+ }
+ }
+ manager.endNodeAction(this);
+ }
+
+ protected void setStructuredDocumentRegionElementName(XMLModel model, IStructuredDocumentRegion flatNode, String oldName, String newName) {
+ if (flatNode != null) {
+ String string = flatNode.getText();
+ int index = string.indexOf(oldName);
+ if (index != -1) {
+ index += flatNode.getStart();
+ model.getStructuredDocument().replaceText(this, index, oldName.length(), newName);
+ }
+ }
+ }
+}
+
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditProcessingInstructionAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditProcessingInstructionAction.java
new file mode 100644
index 0000000000..f4b8f46bac
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditProcessingInstructionAction.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.ui.dialogs.EditProcessingInstructionDialog;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+
+
+
+/**
+ * EditProcessingInstructionAction
+ */
+public class EditProcessingInstructionAction extends NodeAction {
+ protected Node childRef;
+ protected AbstractNodeActionManager manager;
+ protected Node parent;
+ protected ProcessingInstruction pi;
+ protected String title;
+
+ /**
+ * This constructor is used to add a new ProcessingInstruction
+ */
+ public EditProcessingInstructionAction(AbstractNodeActionManager manager, Node parent, Node childRef, String actionLabel, String title) {
+ setText(actionLabel);
+ this.manager = manager;
+ this.parent = parent;
+ this.childRef = childRef;
+ this.title = title;
+ }
+
+ /**
+ * This constructor is used to edit a ProcessingInstruction
+ */
+ public EditProcessingInstructionAction(AbstractNodeActionManager manager, ProcessingInstruction pi, String actionLabel, String title) {
+ setText(actionLabel);
+ this.manager = manager;
+ this.pi = pi;
+ this.parent = pi.getParentNode();
+ this.title = title;
+ }
+
+ public String getUndoDescription() {
+ return title;
+ }
+
+ public void run() {
+ manager.beginNodeAction(this);
+ Shell shell = XMLCommonResources.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+
+ EditProcessingInstructionDialog dialog = null;
+ if (pi != null) {
+ dialog = new EditProcessingInstructionDialog(shell, pi);
+ } else {
+ dialog = new EditProcessingInstructionDialog(shell, XMLCommonResources.getInstance().getString("_UI_PI_TARGET_VALUE"), XMLCommonResources.getInstance().getString("_UI_PI_DATA_VALUE")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ dialog.create();
+ dialog.getShell().setText(title);
+ dialog.setBlockOnOpen(true);
+ dialog.open();
+
+ if (dialog.getReturnCode() == Window.OK) {
+ if (pi != null) {
+ childRef = pi;
+ }
+
+ Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+ Node newNode = document.createProcessingInstruction(dialog.getTarget(), dialog.getData());
+ parent.insertBefore(newNode, childRef);
+
+ if (pi != null) {
+ parent.removeChild(pi);
+ }
+
+ manager.reformat(newNode, false);
+ manager.setViewerSelection(newNode);
+ }
+ manager.endNodeAction(this);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditSchemaInfoAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditSchemaInfoAction.java
new file mode 100644
index 0000000000..5b2c3e2a7b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/EditSchemaInfoAction.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.common.contentmodel.util.DOMNamespaceInfoManager;
+import org.eclipse.wst.common.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.dialogs.EditSchemaInfoDialog;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+//import com.ibm.etools.xml.common.ui.dialogs.EditSchemaInfoDialog;
+
+
+/**
+ * EditDoctypeAction
+ */
+public class EditSchemaInfoAction extends NodeAction {
+ protected AbstractNodeActionManager manager;
+ protected DOMNamespaceInfoManager namespaceInfoManager = new DOMNamespaceInfoManager();
+ protected Node node;
+ protected String resourceLocation;
+ protected String title;
+
+ public EditSchemaInfoAction(AbstractNodeActionManager manager, Node node, String resourceLocation, String title) {
+ this.manager = manager;
+ this.node = node;
+ setText(title);
+ this.resourceLocation = resourceLocation;
+ this.title = title;
+ }
+
+ protected Map createPrefixMapping(List oldList, List newList) {
+ Map map = new Hashtable();
+
+ Hashtable oldURIToPrefixTable = new Hashtable();
+ for (Iterator i = oldList.iterator(); i.hasNext();) {
+ NamespaceInfo oldInfo = (NamespaceInfo) i.next();
+ oldURIToPrefixTable.put(oldInfo.uri, oldInfo);
+ }
+
+ for (Iterator i = newList.iterator(); i.hasNext();) {
+ NamespaceInfo newInfo = (NamespaceInfo) i.next();
+ NamespaceInfo oldInfo = (NamespaceInfo) oldURIToPrefixTable.get(newInfo.uri != null ? newInfo.uri : ""); //$NON-NLS-1$
+
+
+ // if oldInfo is non null ... there's a matching URI in the old
+ // set
+ // we can use its prefix to detemine out mapping
+ //
+ // if oldInfo is null ... we use the 'oldCopy' we stashed away
+ // assuming that the user changed the URI and the prefix
+ if (oldInfo == null) {
+ oldInfo = (NamespaceInfo) newInfo.getProperty("oldCopy"); //$NON-NLS-1$
+ }
+
+ if (oldInfo != null) {
+ String newPrefix = newInfo.prefix != null ? newInfo.prefix : ""; //$NON-NLS-1$
+ String oldPrefix = oldInfo.prefix != null ? oldInfo.prefix : ""; //$NON-NLS-1$
+ if (!oldPrefix.equals(newPrefix)) {
+ map.put(oldPrefix, newPrefix);
+ }
+ }
+ }
+ return map;
+ }
+
+ public Element getElement(Node node) {
+ Element result = null;
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ result = (Element) node;
+ } else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ result = getRootElement((Document) node);
+ }
+ return result;
+ }
+
+
+ public Element getRootElement(Document document) {
+ Element rootElement = null;
+ NodeList nodeList = document.getChildNodes();
+ int nodeListLength = nodeList.getLength();
+ for (int i = 0; i < nodeListLength; i++) {
+ Node childNode = nodeList.item(i);
+ if (childNode.getNodeType() == Node.ELEMENT_NODE) {
+ rootElement = (Element) childNode;
+ break;
+ }
+ }
+ return rootElement;
+ }
+
+ public String getUndoDescription() {
+ return title;
+ }
+
+ public void run() {
+ manager.beginNodeAction(this);
+
+ // todo... change constructor to take an element
+ Element element = getElement(node);
+ if (element != null) {
+ Shell shell = XMLCommonResources.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+ EditSchemaInfoDialog dialog = new EditSchemaInfoDialog(shell, new Path(resourceLocation));
+
+ List namespaceInfoList = namespaceInfoManager.getNamespaceInfoList(element);
+ List oldNamespaceInfoList = NamespaceInfo.cloneNamespaceInfoList(namespaceInfoList);
+
+ // here we store a copy of the old info for each NamespaceInfo
+ // this info will be used in createPrefixMapping() to figure out
+ // how to update the document
+ // in response to these changes
+ for (Iterator i = namespaceInfoList.iterator(); i.hasNext();) {
+ NamespaceInfo info = (NamespaceInfo) i.next();
+ NamespaceInfo oldCopy = new NamespaceInfo(info);
+ info.setProperty("oldCopy", oldCopy); //$NON-NLS-1$
+ }
+
+ dialog.setNamespaceInfoList(namespaceInfoList);
+ dialog.create();
+ //dialog.getShell().setSize(500, 300);
+ dialog.getShell().setText(XMLCommonResources.getInstance().getString("_UI_MENU_EDIT_SCHEMA_INFORMATION_TITLE")); //$NON-NLS-1$
+ dialog.setBlockOnOpen(true);
+ dialog.open();
+
+ if (dialog.getReturnCode() == Window.OK) {
+ List newInfoList = dialog.getNamespaceInfoList();
+ namespaceInfoManager.removeNamespaceInfo(element);
+ namespaceInfoManager.addNamespaceInfo(element, newInfoList, true);
+
+ // see if we need to rename any prefixes
+ Map prefixMapping = createPrefixMapping(oldNamespaceInfoList, namespaceInfoList);
+ if (prefixMapping.size() > 0) {
+ try {
+ manager.getModel().aboutToChangeModel();
+ ReplacePrefixAction replacePrefixAction = new ReplacePrefixAction(manager, element, prefixMapping);
+ replacePrefixAction.run();
+ } finally {
+ manager.getModel().changedModel();
+ }
+ }
+ }
+ }
+ manager.endNodeAction(this);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/MenuBuilder.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/MenuBuilder.java
new file mode 100644
index 0000000000..0403f88d34
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/MenuBuilder.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.actions;
+
+import java.text.Collator;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+
+
+public class MenuBuilder {
+
+
+ protected Comparator comparator = new Comparator() {
+
+ public int compare(Object o1, Object o2) {
+ return Collator.getInstance().compare(getSortKey(o1), getSortKey(o2));
+ }
+
+ protected String getSortKey(Object o) {
+ String result = ""; //$NON-NLS-1$
+ if (o instanceof IAction) {
+ IAction action = (IAction) o;
+ result = action.getText();
+ }
+ //else if (o instanceof MenuData)
+ //{
+ // result = "z" + ((MenuData)o).name;
+ //}
+ return result;
+ }
+ };
+
+
+ protected void createAlphebeticalGrouping(IMenuManager menu, List actionList) {
+ Object[] array = actionList.toArray();
+ if (array.length > 0) {
+ Arrays.sort(array, comparator);
+ }
+
+ int groupSize = 15;
+ int minGroupSize = 5;
+ int numberOfGroups = (array.length / groupSize) + ((array.length % groupSize > minGroupSize) ? 1 : 0);
+
+ for (int i = 0; i < numberOfGroups; i++) {
+ boolean isLastGroup = (i == (numberOfGroups - 1));
+ int firstIndex = i * groupSize;
+ int lastIndex = isLastGroup ? array.length - 1 : i * groupSize + groupSize - 1;
+ Action firstAction = (Action) array[firstIndex];
+ Action lastAction = (Action) array[lastIndex];
+ MenuManager submenu = new MenuManager(firstAction.getText() + " - " + lastAction.getText()); //$NON-NLS-1$
+ menu.add(submenu);
+ for (int j = firstIndex; j <= lastIndex; j++) {
+ submenu.add((Action) array[j]);
+ }
+ }
+ }
+
+
+ public void populateMenu(IMenuManager menu, List actionList, boolean createTiered) {
+ // sort the actions
+ if (actionList.size() < 25) {
+ Object[] array = actionList.toArray();
+ if (array.length > 0) {
+ Arrays.sort(array, comparator);
+ }
+ for (int i = 0; i < array.length; i++) {
+ menu.add((Action) array[i]);
+ }
+ } else {
+ createAlphebeticalGrouping(menu, actionList);
+ }
+ }
+
+ /*
+ * protected void createPropertyGrouping(IMenuManager menu, List
+ * actionList) { MenuDataTable menuDataTable = new MenuDataTable();
+ *
+ * for (Iterator i = actionList.iterator(); i.hasNext(); ) { String
+ * groupName = null; Action action = (Action)i.next(); if (action
+ * instanceof NodeAction) { groupName =
+ * ((NodeAction)action).getGroupName(); } if (groupName == null) {
+ * groupName = ""; } MenuData menuData =
+ * menuDataTable.lookupOrCreate(groupName, "");
+ * menuData.childList.add(action); } populateMenu(menu,
+ * menuDataTable.getRoot()); }
+ *
+ *
+ * protected void populateMenu(MenuManager menuManager, MenuData menuData) {
+ * for (Iterator i = menuData.childList.iterator(); i.hasNext(); ) {
+ * Object o = i.next(); if (o instanceof Action) {
+ * menuManager.add((Action)o); } else if (o instanceof MenuData) {
+ * MenuData childMenuData = (MenuData)o; MenuManager childMenuManager =
+ * new MenuManager(childMenuData.name); menuManager.add(childMenuManager);
+ * populateMenu(childMenuManager, childMenuData); } } }
+ *
+ *
+ * public MenuDataTable { protected Hashtable table = new Hashtable();
+ * protected MenuData root;
+ *
+ * public MenuDataTable() { root = lookupOrCreateMenuData(null, null); }
+ *
+ * protected MenuData lookupMenuData(String name) { String key = name !=
+ * null ? name : ""; return (MenuData)menuDataTable.get(key); }
+ *
+ * protected MenuData lookupOrCreateMenuData(String name, String
+ * parentName) { String key = name != null ? name : ""; MenuData menuData =
+ * (MenuData)menuDataTable.get(key); if (menuData == null) { menuData =
+ * new MenuData(name, parentName); menuDataTable.put(key, menuData); }
+ * return menuData; }
+ *
+ * public MenuData getRoot() { return root; } }
+ *
+ *
+ * protected class MenuData { public String name; public String
+ * parentName; public List childList = new Vector();
+ *
+ * MenuData(String name, String parentName) { this.name = name;
+ * this.parentName = parentName; }
+ *
+ * protected void sort() { Object[] array = childList.toArray(); if
+ * (array.length > 0 ) { Arrays.sort(array, comparator); } childList =
+ * Arrays.asList(array);
+ *
+ * for (Iterator i = childList.iterator(); i.hasNext(); ) { Object o =
+ * i.next(); if (o instanceof MenuData) { ((MenuData)o).sort(); } } } }
+ */
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/NodeAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/NodeAction.java
new file mode 100644
index 0000000000..ff91cdd068
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/NodeAction.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.actions;
+
+import org.eclipse.jface.action.Action;
+
+public abstract class NodeAction extends Action {
+
+ public String getSortKey() {
+ return null;
+ }
+
+ public abstract String getUndoDescription();
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/RemoveBlockCommentActionXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/RemoveBlockCommentActionXML.java
new file mode 100644
index 0000000000..a5a5acb981
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/RemoveBlockCommentActionXML.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.ui.edit.util.StructuredTextEditorActionConstants;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.core.internal.document.CommentImpl;
+
+
+public class RemoveBlockCommentActionXML extends AddBlockCommentActionXML {
+ public RemoveBlockCommentActionXML(ResourceBundle bundle, String prefix, ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ protected void init() {
+ super.init();
+
+ fCloseCommentOffset = fSelectionEndIndexedRegion.getEndOffset() - OPEN_COMMENT.length() - CLOSE_COMMENT.length();
+ }
+
+ protected void processAction() {
+ fModel.beginRecording(this, ResourceHandler.getString(StructuredTextEditorActionConstants.ACTION_NAME_REMOVE_BLOCK_COMMENT + ".tooltip")); //$NON-NLS-1$
+ fModel.aboutToChangeModel();
+
+ if (fSelection.getLength() == 0) {
+ if (fSelectionStartIndexedRegion instanceof CommentImpl) {
+ try {
+ fDocument.replace(fOpenCommentOffset, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+ fDocument.replace(fCloseCommentOffset, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+ } else {
+ if (fSelectionStartIndexedRegion instanceof CommentImpl) {
+ try {
+ fDocument.replace(fOpenCommentOffset, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+
+ if (fSelectionEndIndexedRegion instanceof CommentImpl) {
+ try {
+ fDocument.replace(fCloseCommentOffset, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+ }
+ removeOpenCloseComments(fOpenCommentOffset + OPEN_COMMENT.length(), fCloseCommentOffset - fOpenCommentOffset - CLOSE_COMMENT.length());
+
+ fModel.changedModel();
+ fModel.endRecording(this);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ReplacePrefixAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ReplacePrefixAction.java
new file mode 100644
index 0000000000..c94df41219
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ReplacePrefixAction.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.wst.common.contentmodel.util.DOMVisitor;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+
+public class ReplacePrefixAction extends NodeAction {
+
+ class NodeCollectingDOMVisitor extends DOMVisitor {
+ public List list = new Vector();
+
+ protected boolean isPrefixChangedNeeded(Node node) {
+ String key = node.getPrefix() != null ? node.getPrefix() : ""; //$NON-NLS-1$
+ return prefixMapping.get(key) != null;
+ }
+
+ public void visitAttr(Attr attr) {
+ /*
+ * if (isPrefixChangedNeeded(element)) { list.add(attr); }
+ */
+ }
+
+ protected void visitElement(Element element) {
+ super.visitElement(element);
+ if (isPrefixChangedNeeded(element)) {
+ list.add(element);
+ }
+ }
+ }
+
+ protected static ImageDescriptor imageDescriptor;
+ protected Element element;
+ protected AbstractNodeActionManager manager;
+ protected Map prefixMapping;
+
+ public ReplacePrefixAction(AbstractNodeActionManager manager, Element element, Map prefixMapping) {
+ this.manager = manager;
+ this.element = element;
+ this.prefixMapping = prefixMapping;
+ }
+
+ public String getUndoDescription() {
+ return ""; //$NON-NLS-1$
+ }
+
+ public void run() {
+ NodeCollectingDOMVisitor visitor = new NodeCollectingDOMVisitor();
+ visitor.visitNode(element);
+ for (Iterator i = visitor.list.iterator(); i.hasNext();) {
+ Node node = (Node) i.next();
+ String key = node.getPrefix() != null ? node.getPrefix() : ""; //$NON-NLS-1$
+ String newPrefix = (String) prefixMapping.get(key);
+ if (newPrefix != null) {
+ node.setPrefix(newPrefix);
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ToggleCommentActionXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ToggleCommentActionXML.java
new file mode 100644
index 0000000000..02b7d66268
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/ToggleCommentActionXML.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.ui.edit.util.StructuredTextEditorActionConstants;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+
+
+public class ToggleCommentActionXML extends UncommentActionXML {
+ public ToggleCommentActionXML(ResourceBundle bundle, String prefix, ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ protected void processAction() {
+ fModel.beginRecording(this, ResourceHandler.getString(StructuredTextEditorActionConstants.ACTION_NAME_COMMENT + ".tooltip")); //$NON-NLS-1$
+ fModel.aboutToChangeModel();
+
+ for (int i = fSelectionStartLine; i <= fSelectionEndLine; i++) {
+ try {
+ if (fDocument.getLineLength(i) > 0) {
+ if (isCommentLine(i)) {
+ int lineOffset = fDocument.getLineOffset(i);
+ IRegion region = fDocument.getLineInformation(i);
+ String string = fDocument.get(region.getOffset(), region.getLength());
+ int openCommentOffset = lineOffset + string.indexOf(OPEN_COMMENT);
+ int closeCommentOffset = lineOffset + string.indexOf(CLOSE_COMMENT) - OPEN_COMMENT.length();
+ uncomment(openCommentOffset, closeCommentOffset);
+ } else {
+ int openCommentOffset = fDocument.getLineOffset(i);
+ int lineDelimiterLength = fDocument.getLineDelimiter(i) == null ? 0 : fDocument.getLineDelimiter(i).length();
+ int closeCommentOffset = openCommentOffset + fDocument.getLineLength(i) - lineDelimiterLength + OPEN_COMMENT.length();
+ comment(openCommentOffset, closeCommentOffset);
+ }
+ }
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+
+ fModel.changedModel();
+ fModel.endRecording(this);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/UncommentActionXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/UncommentActionXML.java
new file mode 100644
index 0000000000..2dac342048
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/actions/UncommentActionXML.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.actions;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.ui.edit.util.StructuredTextEditorActionConstants;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+
+
+public class UncommentActionXML extends CommentActionXML {
+ public UncommentActionXML(ResourceBundle bundle, String prefix, ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ protected void processAction() {
+ fModel.beginRecording(this, ResourceHandler.getString(StructuredTextEditorActionConstants.ACTION_NAME_COMMENT + ".tooltip")); //$NON-NLS-1$
+ fModel.aboutToChangeModel();
+
+ for (int i = fSelectionStartLine; i <= fSelectionEndLine; i++) {
+ try {
+ if (fDocument.getLineLength(i) > 0 && isCommentLine(i)) {
+ int lineOffset = fDocument.getLineOffset(i);
+ IRegion region = fDocument.getLineInformation(i);
+ String string = fDocument.get(region.getOffset(), region.getLength());
+ int openCommentOffset = lineOffset + string.indexOf(OPEN_COMMENT);
+ int closeCommentOffset = lineOffset + string.indexOf(CLOSE_COMMENT) - OPEN_COMMENT.length();
+ uncomment(openCommentOffset, closeCommentOffset);
+ }
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+
+ fModel.changedModel();
+ fModel.endRecording(this);
+ }
+
+ protected void uncomment(int openCommentOffset, int closeCommentOffset) {
+ try {
+ fDocument.replace(openCommentOffset, OPEN_COMMENT.length(), ""); //$NON-NLS-1$
+ fDocument.replace(closeCommentOffset, CLOSE_COMMENT.length(), ""); //$NON-NLS-1$
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractContentAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractContentAssistProcessor.java
new file mode 100644
index 0000000000..375da3a347
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractContentAssistProcessor.java
@@ -0,0 +1,2209 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMContent;
+import org.eclipse.wst.common.contentmodel.CMDataType;
+import org.eclipse.wst.common.contentmodel.CMDocument;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMEntityDeclaration;
+import org.eclipse.wst.common.contentmodel.CMGroup;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.CMNodeList;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQueryAction;
+import org.eclipse.wst.common.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.common.encoding.ContentTypeEncodingPreferences;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.sse.ui.IReleasable;
+import org.eclipse.wst.sse.ui.Logger;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.internal.document.AttrImpl;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.taginfo.MarkupTagInfoProvider;
+import org.eclipse.wst.xml.ui.templates.TemplateContextTypeIds;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+abstract public class AbstractContentAssistProcessor implements IContentAssistProcessor, IReleasable {
+ protected static final String INTERNALERROR = ResourceHandler.getString("SEVERE_internal_error_occu_UI_"); //$NON-NLS-1$ = "SEVERE internal error occurred "
+ protected static final String UNKNOWN_ATTR = ResourceHandler.getString("No_known_attribute__UI_"); //$NON-NLS-1$ = "No known attribute "
+ protected static final String UNKNOWN_CONTEXT = ResourceHandler.getString("Content_Assist_not_availab_UI_"); //$NON-NLS-1$ = "Content Assist not available at the current location "
+ protected char completionProposalAutoActivationCharacters[] = null;
+ protected char contextInformationAutoActivationCharacters[] = null;
+ private AttributeContextInformationProvider fAttributeInfoProvider = null;
+ private AttributeContextInformationPresenter fContextInformationPresenter = null;
+
+ protected String fErrorMessage = null;
+ protected XMLContentModelGenerator fGenerator;
+ //protected IResource resource = null;
+ protected MarkupTagInfoProvider fInfoProvider = null;
+ protected ITextViewer fTextViewer = null;
+
+ protected List macroContexts = new ArrayList();
+
+ private final boolean showValues = true;
+
+ public AbstractContentAssistProcessor() {
+ super();
+ init();
+ }
+
+ protected void addAttributeNameProposals(ContentAssistRequest contentAssistRequest) {
+ XMLNode node = (XMLNode) contentAssistRequest.getNode();
+ IStructuredDocumentRegion sdRegion = contentAssistRequest.getDocumentRegion();
+ // retrieve the list of attributes
+ CMElementDeclaration elementDecl = getCMElementDeclaration(node);
+ if (elementDecl != null) {
+ CMNamedNodeMap attributes = elementDecl.getAttributes();
+ String matchString = contentAssistRequest.getMatchString();
+
+ //check whether an attribute really exists for the replacement
+ // offsets AND if it possesses a value
+ boolean attrAtLocationHasValue = false;
+ NamedNodeMap attrs = node.getAttributes();
+ for (int i = 0; i < attrs.getLength(); i++) {
+ AttrImpl existingAttr = (AttrImpl) attrs.item(i);
+ ITextRegion name = existingAttr.getNameRegion();
+
+ if (sdRegion.getStartOffset(name) <= contentAssistRequest.getReplacementBeginPosition() && sdRegion.getStartOffset(name) + name.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength() && existingAttr.getValueRegion() != null) {
+ attrAtLocationHasValue = true;
+ break;
+ }
+ }
+
+ // only add proposals for the attributes whose names begin with
+ // the matchstring
+ if (attributes != null) {
+ // CMVC 246618
+ int isRequired = 0;
+ Image attrImage = null;
+ for (int i = 0; i < attributes.getLength(); i++) {
+ CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attributes.item(i);
+ if (attrDecl.getUsage() == CMAttributeDeclaration.REQUIRED) {
+ isRequired = XMLRelevanceConstants.R_REQUIRED;
+ attrImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATT_REQ_OBJ);
+ } else {
+ isRequired = 0;
+ attrImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+ }
+
+
+ boolean showAttribute = true;
+ showAttribute = showAttribute && beginsWith(getRequiredName(node, attrDecl), matchString.trim());
+ AttrImpl attr = (AttrImpl) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl));
+ ITextRegion nameRegion = attr != null ? attr.getNameRegion() : null;
+ // nameRegion.getEndOffset() + 1 is required to allow for
+ // matches against the full name of an existing Attr
+ showAttribute = showAttribute && ((attr == null) || (nameRegion != null && sdRegion.getStartOffset(nameRegion) <= contentAssistRequest.getReplacementBeginPosition() && sdRegion.getStartOffset(nameRegion) + nameRegion.getLength() >= contentAssistRequest.getReplacementBeginPosition() + contentAssistRequest.getReplacementLength()));
+ if (showAttribute) {
+ String proposedText = null;
+ String proposedInfo = getAdditionalInfo(elementDecl, attrDecl);
+ CustomCompletionProposal proposal = null;
+ // attribute is at this location and already exists
+ if (attrAtLocationHasValue) {
+ // only propose the name
+ proposedText = getRequiredName(node, attrDecl);
+ proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), attrImage, proposedText, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired, true); //CMVC
+ // 269884
+ }
+ // no attribute exists or is elsewhere, generate
+ // minimally
+ else {
+ Attr existingAttrNode = (Attr) node.getAttributes().getNamedItem(getRequiredName(node, attrDecl));
+ String value = null;
+ if (existingAttrNode != null)
+ value = existingAttrNode.getNodeValue();
+ if (value != null && value.length() > 0)
+ proposedText = getRequiredName(node, attrDecl);
+ else {
+ proposedText = getRequiredText(node, attrDecl);
+ }
+ proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), attrDecl.getNodeName().length() + 2, attrImage,
+ // if the value isn't empty (no empty set of
+ // quotes), show it
+ (showValues && proposedText.indexOf("\"\"") < 0) ? proposedText : getRequiredName(node, attrDecl), //$NON-NLS-1$
+ null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_NAME + isRequired);
+ }
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ }
+ } else {
+ setErrorMessage(ResourceHandler.getString("25concat", (new Object[]{node.getNodeName()}))); //+
+ // node.getNodeName()
+ // + ">
+ // is
+ // unknown");
+ // //$NON-NLS-1$
+ // =
+ // "Element
+ // <{0}>
+ // is
+ // unknown."
+ }
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.ATTRIBUTE);
+ }
+
+ protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest) {
+ XMLNode node = (XMLNode) contentAssistRequest.getNode();
+
+ // Find the attribute region and name for which this position should
+ // have a value proposed
+ IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion();
+ ITextRegionList openRegions = open.getRegions();
+ int i = openRegions.indexOf(contentAssistRequest.getRegion());
+ if (i < 0)
+ return;
+ ITextRegion nameRegion = null;
+ while (i >= 0) {
+ nameRegion = openRegions.get(i--);
+ if (nameRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME)
+ break;
+ }
+
+ // the name region is REQUIRED to do anything useful
+ if (nameRegion != null) {
+ // Retrieve the declaration
+ CMElementDeclaration elementDecl = getCMElementDeclaration(node);
+
+ //String attributeName = nameRegion.getText();
+ String attributeName = open.getText(nameRegion);
+
+ CMAttributeDeclaration attrDecl = null;
+
+ // No CMElementDeclaration means no attribute metadata, but
+ // retrieve the
+ // declaration for the attribute otherwise
+ if (elementDecl != null) {
+ CMNamedNodeMap attributes = elementDecl.getAttributes();
+ String noprefixName = DOMNamespaceHelper.getUnprefixedName(attributeName);
+ if (attributes != null) {
+ attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(noprefixName);
+ if (attrDecl == null) {
+ attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(attributeName);
+ }
+ }
+ if (attrDecl == null) {
+ setErrorMessage(UNKNOWN_ATTR, attributeName);
+ }
+ }
+
+ String currentValue = node.getAttributes().getNamedItem(attributeName).getNodeValue();
+ String proposedInfo = null;
+ if (attrDecl != null && attrDecl.getAttrType() != null) {
+ // attribute is known, prompt with values from the declaration
+ proposedInfo = getAdditionalInfo(elementDecl, attrDecl);
+ List possibleValues = getPossibleDataTypeValues(node, attrDecl);
+ if (possibleValues.size() > 0) {
+ // ENUMERATED VALUES
+ String matchString = contentAssistRequest.getMatchString();
+ if (matchString == null)
+ matchString = ""; //$NON-NLS-1$
+ if (matchString.length() > 0 && (matchString.startsWith("\"") || matchString.startsWith("'"))) //$NON-NLS-2$//$NON-NLS-1$
+ matchString = matchString.substring(1);
+ boolean currentValid = false;
+
+ // d210858, if the region's a container, don't suggest the
+ // enumerated values as they probably won't help
+ boolean existingComplicatedValue = contentAssistRequest.getRegion() != null && contentAssistRequest.getRegion() instanceof ITextRegionContainer;
+ if (!existingComplicatedValue) {
+ for (Iterator j = possibleValues.iterator(); j.hasNext();) {
+ String possibleValue = (String) j.next();
+ currentValid = currentValid || possibleValue.equals(currentValue);
+ if (matchString.length() == 0 || possibleValue.startsWith(matchString)) {
+ CustomCompletionProposal proposal = new CustomCompletionProposal("\"" + possibleValue + "\"", //$NON-NLS-2$//$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), possibleValue.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE), possibleValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ }
+ } else if ((attrDecl.getUsage() == CMAttributeDeclaration.FIXED || attrDecl.getAttrType().getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) && attrDecl.getAttrType().getImpliedValue() != null) {
+ // FIXED values
+ String value = attrDecl.getAttrType().getImpliedValue();
+ if (value != null && value.length() > 0) {
+ CustomCompletionProposal proposal = new CustomCompletionProposal("\"" + value + "\"", //$NON-NLS-2$//$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), value.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE), value, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+ contentAssistRequest.addProposal(proposal);
+ if (currentValue.length() > 0 && !value.equals(currentValue)) {
+ proposal = new CustomCompletionProposal("\"" + currentValue + "\"", //$NON-NLS-2$//$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), currentValue.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE), currentValue, null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ }
+ } else {
+ // unknown attribute, so supply nice empty values
+ proposedInfo = getAdditionalInfo(null, elementDecl);
+ CustomCompletionProposal proposal = null;
+ if (currentValue != null && currentValue.length() > 0) {
+ proposal = new CustomCompletionProposal("\"" + currentValue + "\"", //$NON-NLS-2$//$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE), "\"" + currentValue + "\"", //$NON-NLS-2$//$NON-NLS-1$
+ null, proposedInfo, XMLRelevanceConstants.R_XML_ATTRIBUTE_VALUE);
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ } else
+ setErrorMessage(UNKNOWN_CONTEXT);
+
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.ATTRIBUTEVALUE);
+ }
+
+ protected void addCommentProposal(ContentAssistRequest contentAssistRequest) {
+ contentAssistRequest.addProposal(new CustomCompletionProposal("<!-- -->", //$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 5, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_COMMENT), ResourceHandler.getString("6concat", (new Object[]{" <!-- -->"})), //$NON-NLS-1$ = "comment {0}"//$NON-NLS-2$
+ null, null, XMLRelevanceConstants.R_COMMENT));
+ }
+
+ /**
+ * Add all of the element declarations int the CMContent object into one
+ * big list.
+ */
+ protected void addContent(List contentList, CMContent content) {
+ if (content == null)
+ return;
+ if (content instanceof CMGroup) {
+ CMNodeList children = ((CMGroup) content).getChildNodes();
+ if (children == null)
+ return;
+ for (int i = 0; i < children.getLength(); i++) {
+ CMNode child = children.item(i);
+ if (child.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+ contentList.add(child);
+ } else {
+ if (child.getNodeType() == CMNode.GROUP) {
+ addContent(contentList, (CMContent) child);
+ } else {
+ throw new IllegalArgumentException("Unknown content child: " + child); //$NON-NLS-1$
+ }
+ }
+ }
+ } else {
+ contentList.add(content);
+ }
+ }
+
+ protected void addDocTypeProposal(ContentAssistRequest contentAssistRequest) {
+ // if a DocumentElement exists, use that for the root Element name
+ String rootname = "unspecified"; //$NON-NLS-1$
+ if (contentAssistRequest.getNode().getOwnerDocument().getDocumentElement() != null)
+ rootname = contentAssistRequest.getNode().getOwnerDocument().getDocumentElement().getNodeName();
+
+ String proposedText = "<!DOCTYPE " + rootname + " PUBLIC \"//UNKNOWN/\" \"unknown.dtd\">"; //$NON-NLS-1$ //$NON-NLS-2$
+ ICompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 10, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DOCTYPE), "<!DOCTYPE ... >", //$NON-NLS-1$
+ null, null, XMLRelevanceConstants.R_DOCTYPE); // TODO
+ // provide
+ // special
+ // documentation
+ // on doc
+ // type
+ contentAssistRequest.addProposal(proposal);
+ }
+
+ /**
+ * Add the proposals for a completely empty document
+ */
+ protected void addEmptyDocumentProposals(ContentAssistRequest contentAssistRequest) {
+ addXMLProposal(contentAssistRequest);
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.TAG);
+ }
+
+ /**
+ * Add the proposals for the name in an end tag
+ */
+ protected void addEndTagNameProposals(ContentAssistRequest contentAssistRequest) {
+
+ if (contentAssistRequest.getStartOffset() + contentAssistRequest.getRegion().getTextLength() < contentAssistRequest.getReplacementBeginPosition()) {
+ CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), ResourceHandler.getString("9concat", (new Object[]{" '>'"})), //$NON-NLS-1$ = "Close with {0}"//$NON-NLS-2$
+ null, null, XMLRelevanceConstants.R_END_TAG_NAME);
+ contentAssistRequest.addProposal(proposal);
+ } else {
+ XMLNode node = (XMLNode) contentAssistRequest.getNode();
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+ Node aNode = contentAssistRequest.getNode();
+ String matchString = contentAssistRequest.getMatchString();
+ if (matchString.startsWith("</")) //$NON-NLS-1$
+ matchString = matchString.substring(2);
+ while (aNode != null) {
+ if (aNode.getNodeType() == Node.ELEMENT_NODE) {
+ if (aNode.getNodeName().startsWith(matchString)) {
+ XMLNode aXMLNode = (XMLNode) aNode;
+ CMElementDeclaration ed = modelQuery.getCMElementDeclaration((Element) aNode);
+ if ((aXMLNode.getEndStructuredDocumentRegion() == null) && (ed == null || (ed.getContentType() != CMElementDeclaration.EMPTY))) {
+ String proposedText = aNode.getNodeName();
+ String proposedInfo = (ed != null) ? getAdditionalInfo(null, ed) : null;
+ if (node.getNodeType() == Node.TEXT_NODE && !contentAssistRequest.getDocumentRegion().isEnded())
+ proposedText += ">"; //$NON-NLS-1$
+ CustomCompletionProposal proposal = null;
+ // double check to see if the region acted upon is
+ // a tag name; replace it if so
+ if (contentAssistRequest.getRegion().getType() == XMLRegionContext.XML_TAG_NAME) {
+ proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getStartOffset(), contentAssistRequest.getRegion().getTextLength(), proposedText.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), proposedText, null, proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME);
+ } else {
+ proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), ResourceHandler.getString("9concat", (new Object[]{"'" + proposedText + "'"})), //$NON-NLS-1$ = "Close with {0}"//$NON-NLS-2$ //$NON-NLS-3$
+ null, proposedInfo, XMLRelevanceConstants.R_END_TAG_NAME);
+ }
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ }
+ aNode = aNode.getParentNode();
+ }
+ }
+ }
+
+ /**
+ * Prompt for end tags to a non-empty Node that hasn't ended Handles these
+ * cases: <br>
+ * <tagOpen>| <br>
+ * <tagOpen>< |<br>
+ * <tagOpen></ |
+ *
+ * @param contentAssistRequest
+ */
+ protected void addEndTagProposals(ContentAssistRequest contentAssistRequest) {
+ XMLNode node = (XMLNode) contentAssistRequest.getParent();
+
+ // CMVC 241090 for special meta-info comment tags
+ if (isCommentNode(node)) {
+ // loop and find non comment node parent
+ while (node != null && isCommentNode(node)) {
+ node = (XMLNode) node.getParentNode();
+ }
+ }
+
+ // data to create a CustomCompletionProposal
+ String replaceText = node.getNodeName() + ">"; //$NON-NLS-1$
+ int replaceBegin = contentAssistRequest.getReplacementBeginPosition();
+ int replaceLength = contentAssistRequest.getReplacementLength();
+ int cursorOffset = node.getNodeName().length() + 1;
+ String displayString = ""; //$NON-NLS-1$
+ String proposedInfo = ""; //$NON-NLS-1$
+ Image image = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC);
+
+ setErrorMessage(null);
+ boolean addProposal = false;
+
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ // fix for CMVC 261790
+ // ////////////////////////////////////////////////////////////////////////////////////
+ IStructuredDocument sDoc = (IStructuredDocument) fTextViewer.getDocument();
+ IStructuredDocumentRegion xmlEndTagOpen = sDoc.getRegionAtCharacterOffset(contentAssistRequest.getReplacementBeginPosition());
+ // skip backward to "<", "</", or the (unclosed) start tag, null
+ // if not found
+ String type = ""; //$NON-NLS-1$
+ while (xmlEndTagOpen != null && (type = xmlEndTagOpen.getType()) != XMLRegionContext.XML_END_TAG_OPEN && type != XMLRegionContext.XML_TAG_CLOSE && !needsEndTag(xmlEndTagOpen) && type != XMLRegionContext.XML_TAG_OPEN) {
+ xmlEndTagOpen = xmlEndTagOpen.getPrevious();
+ }
+
+ if (xmlEndTagOpen == null)
+ return;
+
+ node = (XMLNode) node.getModel().getIndexedRegion(xmlEndTagOpen.getStartOffset());
+ node = (XMLNode) node.getParentNode();
+
+ if (isStartTag(xmlEndTagOpen)) {
+ // this is the case for a start tag w/out end tag
+ // eg:
+ // <p>
+ // <% String test = "test"; %>
+ // |
+ if (needsEndTag(xmlEndTagOpen)) {
+ String tagName = getTagName(xmlEndTagOpen);
+ xmlEndTagOpen.getTextEndOffset();
+ replaceLength = 0;
+ replaceText = "</" + tagName + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$
+ //replaceText = "</" + node.getNodeName() + ">";
+ // //$NON-NLS-1$ $NON-NLS-2$
+ cursorOffset = tagName.length() + 3;
+ displayString = ResourceHandler.getString("17concat", (new Object[]{tagName})); //$NON-NLS-1$
+ addProposal = true;
+ }
+ } else if (type == XMLRegionContext.XML_END_TAG_OPEN) {
+ // this is the case for: <tag> </ |
+ // possibly <tag> </ |<anotherTag>
+ // should only be replacing white space...
+ replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0;
+ replaceText = node.getNodeName() + ">"; //$NON-NLS-1$
+ cursorOffset = replaceText.length();
+ replaceBegin = xmlEndTagOpen.getTextEndOffset();
+ displayString = ResourceHandler.getString("15concat", (new Object[]{node.getNodeName()})); //$NON-NLS-1$
+ addProposal = true;
+ } else if (type == XMLRegionContext.XML_TAG_OPEN) {
+ // this is the case for: <tag> < |
+ replaceText = "/" + node.getNodeName() + ">"; //$NON-NLS-1$ //$NON-NLS-2$ $NON-NLS-2$
+ cursorOffset = replaceText.length();
+ //replaceText = "/" + node.getNodeName() + ">"; //$NON-NLS-1$
+ // $NON-NLS-2$
+ // should only be replacing white space...
+ replaceLength = (replaceBegin > xmlEndTagOpen.getTextEndOffset()) ? replaceBegin - xmlEndTagOpen.getTextEndOffset() : 0;
+ replaceBegin = xmlEndTagOpen.getTextEndOffset();
+ displayString = ResourceHandler.getString("15concat", (new Object[]{"/" + node.getNodeName()})); //$NON-NLS-1$ //$NON-NLS-2$
+ addProposal = true;
+ }
+ }
+ // fix for CMVC 261790
+ // ////////////////////////////////////////////////////////////////////////////////////
+ // fix for CMVC 263163, sometimes the node is not null, but
+ // getNodeValue() is null, put in a null check
+ else if (node.getNodeValue() != null && node.getNodeValue().indexOf("</") != -1) { //$NON-NLS-1$
+ // the case where "</" is started, but the nodes comes in as a
+ // text node (instead of element)
+ // like this: <tag> </|
+ Node parent = node.getParentNode();
+ if (parent != null && parent.getNodeType() != Node.DOCUMENT_NODE) {
+ replaceText = parent.getNodeName() + ">"; //$NON-NLS-1$
+ cursorOffset = replaceText.length();
+ displayString = ResourceHandler.getString("17concat", (new Object[]{parent.getNodeName()})); //$NON-NLS-1$
+ setErrorMessage(null);
+ addProposal = true;
+ }
+ }
+ // end fix for CMVC 261790
+ // ////////////////////////////////////////////////////////////////////////////////////
+ else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ setErrorMessage(UNKNOWN_CONTEXT);
+ }
+ if (addProposal == true) {
+ CustomCompletionProposal proposal = new CustomCompletionProposal(replaceText, replaceBegin, replaceLength, cursorOffset, image, displayString, null, proposedInfo, XMLRelevanceConstants.R_END_TAG);
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+
+ protected void addEntityProposals(ContentAssistRequest contentAssistRequest, int documentPosition, ITextRegion completionRegion, XMLNode treeNode) {
+ ICompletionProposal[] eps = computeEntityReferenceProposals(documentPosition, completionRegion, treeNode);
+ for (int i = 0; eps != null && i < eps.length; i++)
+ contentAssistRequest.addProposal(eps[i]);
+ }
+
+ protected void addEntityProposals(Vector proposals, Properties map, String key, int nodeOffset, IStructuredDocumentRegion sdRegion, ITextRegion completionRegion) {
+ if (map == null)
+ return;
+ String entityName = ""; //$NON-NLS-1$
+ String entityValue = ""; //$NON-NLS-1$
+ Image entityIcon = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENTITY_REFERENCE);
+ String replacementText = ""; //$NON-NLS-1$
+ String displayString = ""; //$NON-NLS-1$
+ Enumeration keys = map.keys();
+
+ while (keys != null && keys.hasMoreElements()) {
+ entityName = (String) keys.nextElement();
+ entityValue = map.getProperty(entityName);
+ // filter based on partial entity string...
+ if (entityName.toLowerCase().startsWith(key.toLowerCase()) || key.trim().equals("")) //$NON-NLS-1$
+ {
+ // figure out selection...if text is selected, add it to
+ // selection length
+ int selectionLength = nodeOffset;
+ if (fTextViewer != null) {
+ selectionLength += fTextViewer.getSelectedRange().y;
+ }
+ // create a new proposal for entity string...
+ replacementText = "&" + entityName + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+ displayString = "&" + entityName + "; (" + entityValue + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ICompletionProposal cp = new CustomCompletionProposal(replacementText, sdRegion.getStartOffset(completionRegion), selectionLength, replacementText.length(), entityIcon, displayString, null, null, XMLRelevanceConstants.R_ENTITY);
+ if (cp != null) {
+ proposals.add(cp);
+ }
+ }
+ }
+ }
+
+ protected void addPCDATAProposal(String nodeName, ContentAssistRequest contentAssistRequest) {
+ CustomCompletionProposal proposal = new CustomCompletionProposal("<![CDATA[]]>", //$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), 9, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_CDATASECTION), "CDATA Section", //$NON-NLS-1$
+ null, null, XMLRelevanceConstants.R_CDATA);
+ contentAssistRequest.addProposal(proposal);
+
+ proposal = new CustomCompletionProposal(nodeName, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), nodeName.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TXTEXT), "#PCDATA", //$NON-NLS-1$
+ null, null, XMLRelevanceConstants.R_CDATA);
+ contentAssistRequest.addProposal(proposal);
+ }
+
+ protected void addStartDocumentProposals(ContentAssistRequest contentAssistRequest) {
+ Node aNode = contentAssistRequest.getNode();
+ boolean xmlpiFound = false;
+ Document owningDocument = aNode.getOwnerDocument();
+ // ==> // int xmlpiNodePosition = -1;
+
+ // make sure xmlpi is root element
+ // don't want doctype proposal if XMLPI isn't first element...
+ // CMVC 242943
+ // CMVC 245532
+ Node first = owningDocument.getFirstChild();
+ boolean xmlpiIsFirstElement = (first != null && first.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE);
+ boolean insertDoctype = xmlpiIsFirstElement;
+
+ for (Node child = owningDocument.getFirstChild(); child != null; child = child.getNextSibling()) {
+ boolean xmlpi = (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && child.getNodeName().equals("xml")); //$NON-NLS-1$
+ xmlpiFound = xmlpiFound || xmlpi;
+ if (xmlpiFound) {
+ if (child instanceof XMLNode) {
+ // ==> // int xmlpiNodePosition =
+ // ((XMLNode)child).getEndOffset();
+ }
+ // skip white space and text
+ while ((child = child.getNextSibling()) != null && (child.getNodeType() == Node.TEXT_NODE)) {
+ }
+ // check if theres a node inbetween XMLPI and cursor position
+ if (child != null && child instanceof XMLNode) {
+ // CMVC 257486
+ if (contentAssistRequest.getReplacementBeginPosition() >= ((XMLNode) child).getEndOffset() || !xmlpiIsFirstElement) {
+ insertDoctype = false;
+ }
+ }
+ break;
+ }
+ }
+
+ if (!xmlpiFound) {
+ addXMLProposal(contentAssistRequest);
+ } else if (owningDocument.getDoctype() == null && isCursorAfterXMLPI(contentAssistRequest) && insertDoctype) {
+ addDocTypeProposal(contentAssistRequest);
+ }
+ }
+
+ /**
+ * Close an unclosed start tag
+ */
+ protected void addTagCloseProposals(ContentAssistRequest contentAssistRequest) {
+ XMLNode node = (XMLNode) contentAssistRequest.getParent();
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+
+ CMElementDeclaration elementDecl = getCMElementDeclaration(node);
+ String proposedInfo = (elementDecl != null) ? getAdditionalInfo(null, elementDecl) : null;
+ int contentType = (elementDecl != null) ? elementDecl.getContentType() : CMElementDeclaration.ANY;
+ // if it's XML and content doesn't HAVE to be element, add "/>"
+ // proposal.
+ boolean endWithSlashBracket = (getXML(node) && contentType != CMElementDeclaration.ELEMENT);
+
+ // is the start tag ended properly?
+ if (contentAssistRequest.getDocumentRegion() == node.getFirstStructuredDocumentRegion() && !(node.getFirstStructuredDocumentRegion()).isEnded()) {
+ setErrorMessage(null);
+ // Is this supposed to be an empty tag? Note that if we can't
+ // tell, we assume it's not.
+ if (elementDecl != null && elementDecl.getContentType() == CMElementDeclaration.EMPTY) {
+ // prompt with a self-closing end character if needed
+ CustomCompletionProposal proposal = new CustomCompletionProposal(getContentGenerator().getStartTagClose(node, elementDecl), contentAssistRequest.getReplacementBeginPosition(),
+ // this is one of the few times to ignore the length --
+ // always insert
+ // contentAssistRequest.getReplacementLength(),
+ 0, getContentGenerator().getStartTagClose(node, elementDecl).length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), ResourceHandler.getString("3concat", (new Object[]{getContentGenerator().getStartTagClose(node, elementDecl)})), //$NON-NLS-1$ = "Close with '{0}'"
+ null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+ contentAssistRequest.addProposal(proposal);
+ } else {
+ // prompt with a close for the start tag
+ CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(),
+ // this is one of the few times to ignore the
+ // length -- always insert
+ // contentAssistRequest.getReplacementLength(),
+ 0, 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), ResourceHandler.getString("9concat", (new Object[]{" '>'"})), //$NON-NLS-1$ = "Close with {0}"//$NON-NLS-2$
+ null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+ contentAssistRequest.addProposal(proposal);
+
+ // prompt with the closer for the start tag and an end tag
+ // if one is not present
+ if (node.getEndStructuredDocumentRegion() == null) {
+ // FIX FOR CMVC 247482
+ // make sure tag name is actually what it thinks it
+ // is...(eg. <%@ vs. <jsp:directive)
+ IStructuredDocumentRegion sdr = contentAssistRequest.getDocumentRegion();
+ String openingTagText = (sdr != null) ? sdr.getFullText() : ""; //$NON-NLS-1$
+ if (openingTagText != null && openingTagText.indexOf(node.getNodeName()) != -1) {
+ proposal = new CustomCompletionProposal("></" + node.getNodeName() + ">", //$NON-NLS-2$//$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(),
+ // this is one of the few times to
+ // ignore the length -- always insert
+ // contentAssistRequest.getReplacementLength(),
+ 0, 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), ResourceHandler.getString("5concat", (new Object[]{node.getNodeName()})), //$NON-NLS-1$ = "Close with '></{0}>'"
+ null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ // prompt with slash bracket "/>" incase if it's a self
+ // ending tag
+ if (endWithSlashBracket) {
+ proposal = new CustomCompletionProposal("/>", //$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(),
+ // this is one of the few times to ignore
+ // the length -- always insert
+ // contentAssistRequest.getReplacementLength(),
+ 0, 2, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), ResourceHandler.getString("9concat", (new Object[]{" \"/>\""})), //$NON-NLS-1$ = "Close with {0}"//$NON-NLS-2$
+ null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG + 1); // +1
+ // to
+ // bring
+ // to
+ // top
+ // of
+ // list
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ } else if (contentAssistRequest.getDocumentRegion() == node.getLastStructuredDocumentRegion() && !node.getLastStructuredDocumentRegion().isEnded()) {
+ setErrorMessage(null);
+ // prompt with a closing end character for the end tag
+ CustomCompletionProposal proposal = new CustomCompletionProposal(">", //$NON-NLS-1$
+ contentAssistRequest.getReplacementBeginPosition(),
+ // this is one of the few times to ignore the
+ // length -- always insert
+ // contentAssistRequest.getReplacementLength(),
+ 0, 1, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), ResourceHandler.getString("9concat", (new Object[]{" '>'"})), //$NON-NLS-1$ = "Close with {0}"//$NON-NLS-2$
+ null, proposedInfo, XMLRelevanceConstants.R_CLOSE_TAG);
+ contentAssistRequest.addProposal(proposal);
+ }
+ } else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ setErrorMessage(UNKNOWN_CONTEXT);
+ }
+ }
+
+ protected void addTagInsertionProposals(ContentAssistRequest contentAssistRequest, int childPosition) {
+ List cmnodes = null;
+ Node parent = contentAssistRequest.getParent();
+ List validActions = null;
+ String error = null;
+
+ // CMVC #242943 shouldn't have proposals before XMLPI
+ // (nsd) This is only valid at the document element level
+ // only valid if it's XML (check added 2/17/2004)
+ if (parent != null && parent.getNodeType() == Node.DOCUMENT_NODE && ((XMLDocument) parent).isXMLType() && !isCursorAfterXMLPI(contentAssistRequest)) {
+ // but we should always have macros
+ // need to be careful these are only added one time
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.TAG);
+ return;
+ }
+ // only want proposals if cursor is after doctype...
+ if (!isCursorAfterDoctype(contentAssistRequest))
+ return;
+
+ // CMVC 248081
+ // fix for meta-info comment nodes.. they currently "hide" other
+ // proposals because the don't
+ // have a content model (so can't propose any children..)
+ if (parent != null && parent instanceof XMLNode && isCommentNode((XMLNode) parent)) {
+ // loop and find non comment node?
+ while (parent != null && isCommentNode((XMLNode) parent)) {
+ parent = (XMLNode) parent.getParentNode();
+ }
+ }
+
+ if (parent.getNodeType() == Node.ELEMENT_NODE) {
+ CMElementDeclaration parentDecl = getCMElementDeclaration(parent);
+ if (parentDecl != null) {
+ // XSD-specific ability - no filtering
+ CMDataType childType = parentDecl.getDataType();
+ if (childType != null) {
+ String[] childStrings = childType.getEnumeratedValues();
+ if (childStrings != null) {
+ // the content string is the sole valid child...so
+ // replace the rest
+ int begin = contentAssistRequest.getReplacementBeginPosition();
+ int length = contentAssistRequest.getReplacementLength();
+ if (parent instanceof XMLNode) {
+ if (((XMLNode) parent).getLastStructuredDocumentRegion() != ((XMLNode) parent).getFirstStructuredDocumentRegion()) {
+ begin = ((XMLNode) parent).getFirstStructuredDocumentRegion().getEndOffset();
+ length = ((XMLNode) parent).getLastStructuredDocumentRegion().getStartOffset() - begin;
+ }
+ }
+ String proposedInfo = getAdditionalInfo(parentDecl, childType);
+ for (int i = 0; i < childStrings.length; i++) {
+ CustomCompletionProposal textProposal = new CustomCompletionProposal(childStrings[i], begin, length, childStrings[i].length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ENUM), childStrings[i], null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
+ contentAssistRequest.addProposal(textProposal);
+ }
+ }
+ }
+ }
+ if (parentDecl != null && parentDecl.getContentType() == CMElementDeclaration.PCDATA) {
+ addPCDATAProposal(parentDecl.getNodeName(), contentAssistRequest);
+ } else {
+ // retrieve the list of children
+ validActions = getAvailableChildrenAtIndex((Element) parent, childPosition);
+ cmnodes = getValidCMNodes(childPosition, ModelQueryAction.INSERT, validActions);
+ Iterator nodeIterator = cmnodes.iterator();
+ if (!nodeIterator.hasNext()) {
+ if (getCMElementDeclaration(parent) != null)
+ error = ResourceHandler.getString("1concat", (new Object[]{parent.getNodeName()})); //$NON-NLS-1$ = "{0} has no available child tags."
+ else
+ error = ResourceHandler.getString("31concat", (new Object[]{parent.getNodeName()})); //$NON-NLS-1$
+ }
+ String matchString = contentAssistRequest.getMatchString();
+ // chop off any leading <'s and whitespace from the
+ // matchstring
+ while ((matchString.length() > 0) && (Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) //$NON-NLS-1$
+ //$NON-NLS-1$
+ matchString = matchString.substring(1);
+ while (nodeIterator.hasNext()) {
+ Object o = nodeIterator.next();
+ if (o instanceof CMElementDeclaration) {
+ CMElementDeclaration elementDecl = (CMElementDeclaration) o;
+ // only add proposals for the child element's that
+ // begin with the matchstring
+ String tagname = getRequiredName(parent, elementDecl);
+ // Account for the &lt; and &gt;. If attributes were
+ // added, the cursor will be placed
+ // at the offset before of the first character of the
+ // first attribute name.
+ int markupAdjustment = getContentGenerator().getMinimalStartTagLength(parent, elementDecl);
+ if (beginsWith(tagname, matchString)) {
+ String proposedText = getRequiredText(parent, elementDecl);
+ String proposedInfo = getAdditionalInfo(parentDecl, elementDecl);
+ CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), markupAdjustment, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), tagname, null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ }
+ if (contentAssistRequest.getProposals().size() == 0) {
+ if (error != null)
+ setErrorMessage(error);
+ else if (contentAssistRequest.getMatchString() != null && contentAssistRequest.getMatchString().length() > 0)
+ setErrorMessage(ResourceHandler.getString("11concat", (new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()}))); //$NON-NLS-1$
+ //$NON-NLS-1$ = "No known child tag names of <{0}> begin with \"{1}\"."
+ else
+ setErrorMessage(ResourceHandler.getString("14concat", (new Object[]{parent.getNodeName()}))); //$NON-NLS-1$
+ }
+ }
+ } else if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+ // Can only prompt with elements if the cursor position is past
+ // the XML processing
+ // instruction and DOCTYPE declaration
+ boolean xmlpiFound = false;
+ boolean doctypeFound = false;
+ int minimumOffset = -1;
+
+ for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+
+ boolean xmlpi = (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && child.getNodeName().equals("xml")); //$NON-NLS-1$
+ boolean doctype = child.getNodeType() == Node.DOCUMENT_TYPE_NODE;
+ if (xmlpi || doctype && minimumOffset < 0)
+ minimumOffset = ((XMLNode) child).getFirstStructuredDocumentRegion().getStartOffset() + ((XMLNode) child).getFirstStructuredDocumentRegion().getTextLength();
+ xmlpiFound = xmlpiFound || xmlpi;
+ doctypeFound = doctypeFound || doctype;
+ }
+ if (!xmlpiFound && contentAssistRequest.getReplacementBeginPosition() < minimumOffset) {
+ addXMLProposal(contentAssistRequest);
+ }
+
+ if (contentAssistRequest.getReplacementBeginPosition() >= minimumOffset) {
+ List childDecls = getAvailableRootChildren((Document) parent, childPosition);
+ for (int i = 0; i < childDecls.size(); i++) {
+ CMElementDeclaration ed = (CMElementDeclaration) childDecls.get(i);
+ if (ed != null) {
+ String proposedText = getRequiredText(parent, ed);
+ String tagname = getRequiredName(parent, ed);
+ // account for the &lt; and &gt;
+ int markupAdjustment = getContentGenerator().getMinimalStartTagLength(parent, ed);
+ String proposedInfo = getAdditionalInfo(null, ed);
+ CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), markupAdjustment, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), tagname, null, proposedInfo, XMLRelevanceConstants.R_TAG_INSERTION);
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ }
+ }
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.TAG);
+ }
+
+ protected void addTagNameProposals(ContentAssistRequest contentAssistRequest, int childPosition) {
+ List cmnodes = null;
+ Node parent = contentAssistRequest.getParent();
+ XMLNode node = (XMLNode) contentAssistRequest.getNode();
+ List validActions = null;
+ String error = null;
+ String matchString = contentAssistRequest.getMatchString();
+ if (parent.getNodeType() == Node.ELEMENT_NODE) {
+ // retrieve the list of children
+ validActions = getAvailableChildrenAtIndex((Element) parent, childPosition);
+ cmnodes = getValidCMNodes(childPosition, ModelQueryAction.INSERT, validActions);
+ Iterator nodeIterator = cmnodes.iterator();
+ // chop off any leading <'s and whitespace from the matchstring
+ while ((matchString.length() > 0) && (Character.isWhitespace(matchString.charAt(0)) || beginsWith(matchString, "<"))) //$NON-NLS-1$
+ //$NON-NLS-1$
+ matchString = matchString.substring(1);
+ if (!nodeIterator.hasNext())
+ error = ResourceHandler.getString("8concat", (new Object[]{parent.getNodeName()})); //$NON-NLS-1$
+ while (nodeIterator.hasNext()) {
+ CMNode elementDecl = (CMNode) nodeIterator.next();
+ if (elementDecl != null) {
+ // only add proposals for the child element's that begin
+ // with the matchstring
+ String proposedText = null;
+ int cursorAdjustment = 0;
+
+ // do a check to see if partial attributes of partial tag
+ // names are in list
+ if ((node != null && node.getAttributes() != null && node.getAttributes().getLength() > 0 && attributeInList(node, parent, elementDecl)) || ((node.getNodeType() != Node.TEXT_NODE) && node.getFirstStructuredDocumentRegion().isEnded())) {
+
+ proposedText = getRequiredName(parent, elementDecl);
+ cursorAdjustment = proposedText.length();
+ } else {
+ proposedText = getRequiredName(parent, elementDecl);
+ cursorAdjustment = proposedText.length();
+ if (elementDecl instanceof CMElementDeclaration) {
+ CMElementDeclaration ed = (CMElementDeclaration) elementDecl;
+ if (ed.getContentType() == CMElementDeclaration.EMPTY) {
+ proposedText += getContentGenerator().getStartTagClose(parent, ed);
+ cursorAdjustment = proposedText.length();
+ } else {
+ cursorAdjustment = proposedText.length() + 1;
+ proposedText += "></" + getRequiredName(parent, elementDecl) + ">"; //$NON-NLS-2$//$NON-NLS-1$
+ }
+ }
+ }
+ if (beginsWith(proposedText, matchString)) {
+ String proposedInfo = getAdditionalInfo(getCMElementDeclaration(parent), elementDecl);
+ CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), cursorAdjustment, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), getRequiredName(parent, elementDecl), null, proposedInfo, XMLRelevanceConstants.R_TAG_NAME);
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ }
+ if (contentAssistRequest.getProposals().size() == 0) {
+ if (error != null)
+ setErrorMessage(error);
+ else if (contentAssistRequest.getMatchString() != null && contentAssistRequest.getMatchString().length() > 0)
+ setErrorMessage(ResourceHandler.getString("27concat", (new Object[]{parent.getNodeName(), contentAssistRequest.getMatchString()}))); //$NON-NLS-1$
+ //$NON-NLS-1$ = "No known child tag names of <{0}> begin with \"{1}\""
+ else
+ setErrorMessage(ResourceHandler.getString("28concat", (new Object[]{parent.getNodeName()}))); //$NON-NLS-1$
+ }
+ } else if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+ List childElements = getAvailableRootChildren((Document) parent, childPosition);
+ for (int i = 0; i < childElements.size(); i++) {
+ CMNode ed = (CMNode) childElements.get(i);
+ if (ed == null)
+ continue;
+ String proposedText = null;
+ int cursorAdjustment = 0;
+ proposedText = getRequiredName(parent, ed);
+ if (!beginsWith(proposedText, matchString))
+ continue;
+ if ((node != null && node.getAttributes() != null && node.getAttributes().getLength() > 0) || ((node.getNodeType() != Node.TEXT_NODE) && node.getFirstStructuredDocumentRegion().isEnded())) {
+ cursorAdjustment = proposedText.length();
+ } else {
+ cursorAdjustment = proposedText.length();
+ if (ed instanceof CMElementDeclaration) {
+ CMElementDeclaration elementDecl = (CMElementDeclaration) ed;
+ if (elementDecl.getContentType() == CMElementDeclaration.EMPTY) {
+ proposedText += getContentGenerator().getStartTagClose(parent, elementDecl);
+ cursorAdjustment = proposedText.length();
+ } else {
+ cursorAdjustment = proposedText.length() + 1;
+ proposedText += "></" + getRequiredName(parent, elementDecl) + ">"; //$NON-NLS-2$//$NON-NLS-1$
+ }
+ }
+ }
+ String proposedInfo = getAdditionalInfo(null, ed);
+ CustomCompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), cursorAdjustment, XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC), getRequiredName(parent, ed), null, proposedInfo, XMLRelevanceConstants.R_TAG_NAME);
+ contentAssistRequest.addProposal(proposal);
+ }
+ }
+ }
+
+ /**
+ * Adds templates to the list of proposals
+ *
+ * @param contentAssistRequest
+ * @param context
+ */
+ protected void addTemplates(ContentAssistRequest contentAssistRequest, String context) {
+ if (macroContexts.contains(context))
+ return;
+ if (contentAssistRequest == null)
+ return;
+ macroContexts.add(context);
+
+ boolean useProposalList = !contentAssistRequest.shouldSeparate();
+
+ if (getTemplateCompletionProcessor() != null) {
+ getTemplateCompletionProcessor().setContextType(context);
+ ICompletionProposal[] proposals = getTemplateCompletionProcessor().computeCompletionProposals(fTextViewer, contentAssistRequest.getReplacementBeginPosition());
+ for (int i = 0; i < proposals.length; ++i) {
+ if (useProposalList)
+ contentAssistRequest.addProposal(proposals[i]);
+ else
+ contentAssistRequest.addMacro(proposals[i]);
+ }
+ }
+ }
+
+ protected void addXMLProposal(ContentAssistRequest contentAssistRequest) {
+ String proposedText = "<?xml version=\"1.0\" encoding=\"" + ContentTypeEncodingPreferences.getUserPreferredCharsetName(IContentTypeIdentifier.ContentTypeID_SSEXML) + "\"?>"; //$NON-NLS-2$//$NON-NLS-1$
+ ICompletionProposal proposal = new CustomCompletionProposal(proposedText, contentAssistRequest.getReplacementBeginPosition(), contentAssistRequest.getReplacementLength(), proposedText.length(), XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION), proposedText, null, null, XMLRelevanceConstants.R_XML_DECLARATION); // TODO
+ // add
+ // special
+ // XML
+ // proposal
+ // info
+ contentAssistRequest.addProposal(proposal);
+ }
+
+ /**
+ * This method determines if any of the attributes in the proposed XMLNode
+ * node, are possible values of attributes from possible Elements at this
+ * point in the document according to the Content Model.
+ *
+ * @param node
+ * the element with attributes that you would like to test if
+ * are possible for possible Elements at this point
+ * @param cmnode
+ * possible element at this point in the document (depending on
+ * what 'node' is)
+ * @return true if any attributes of 'node' match any possible attributes
+ * from 'cmnodes' list.
+ */
+ protected boolean attributeInList(XMLNode node, Node parent, CMNode cmnode) {
+ if (node == null || parent == null || cmnode == null)
+ return false;
+ String elementMatchString = node.getNodeName();
+ String cmnodeName = getRequiredName(parent, cmnode);//cmnode.getNodeName();
+ if (node instanceof Element) {
+ NamedNodeMap map = ((Element) node).getAttributes();
+ String attrMatchString = ""; //$NON-NLS-1$
+ CMNamedNodeMap cmattrMap = null;
+ // iterate attribute possibilities for partially started node
+ for (int i = 0; map != null && i < map.getLength(); i++) {
+ attrMatchString = map.item(i).getNodeName();
+ // filter on whatever user typed for element name already
+ if (beginsWith(cmnodeName, elementMatchString)) {
+ if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+ cmattrMap = ((CMElementDeclaration) cmnode).getAttributes();
+ // iterate possible attributes from a cmnode in
+ // proposal list
+ for (int k = 0; cmattrMap != null && k < cmattrMap.getLength(); k++) {
+ // check if name matches
+ if (cmattrMap.item(k).getNodeName().equals(attrMatchString)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ protected boolean beginsWith(String aString, String prefix) {
+ if (aString == null || prefix == null)
+ return true;
+ // (pa) 221190 matching independent of case to be consistant with Java
+ // editor CA
+ return aString.toLowerCase().startsWith(prefix.toLowerCase());
+ }
+
+ protected ContentAssistRequest computeAttributeProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode nodeAtOffset, XMLNode node) {
+ ContentAssistRequest contentAssistRequest = null;
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+ if (documentPosition < sdRegion.getStartOffset(completionRegion)) {
+ // setup to insert new attributes
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+ } else {
+ // Setup to replace an existing attribute name
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+ }
+ addAttributeNameProposals(contentAssistRequest);
+ contentAssistRequest.setReplacementBeginPosition(documentPosition);
+ contentAssistRequest.setReplacementLength(0);
+ if (node.getFirstStructuredDocumentRegion() != null && (!node.getFirstStructuredDocumentRegion().isEnded())) {
+ addTagCloseProposals(contentAssistRequest);
+ }
+ return contentAssistRequest;
+ }
+
+ protected ContentAssistRequest computeAttributeValueProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode nodeAtOffset, XMLNode node) {
+ ContentAssistRequest contentAssistRequest = null;
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+ if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength() && sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength() != sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
+ // setup to add a new attribute at the documentPosition
+ XMLNode actualNode = (XMLNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+ contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
+ addAttributeNameProposals(contentAssistRequest);
+ if (actualNode.getFirstStructuredDocumentRegion() != null && !actualNode.getFirstStructuredDocumentRegion().isEnded()) {
+ addTagCloseProposals(contentAssistRequest);
+ }
+ } else {
+ // setup to replace the existing value
+ if (!nodeAtOffset.getFirstStructuredDocumentRegion().isEnded() && documentPosition < sdRegion.getStartOffset(completionRegion)) {
+ // if the IStructuredDocumentRegion isn't closed and the
+ // cursor is in front of the value, add
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+ addAttributeNameProposals(contentAssistRequest);
+ } else {
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+ addAttributeValueProposals(contentAssistRequest);
+ }
+ }
+ return contentAssistRequest;
+ }
+
+ protected ContentAssistRequest computeCompletionProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode treeNode, XMLNode xmlnode) {
+ ContentAssistRequest contentAssistRequest = null;
+ String regionType = completionRegion.getType();
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+
+ // Handle the most common and best supported cases
+ if (xmlnode.getNodeType() == Node.ELEMENT_NODE || xmlnode.getNodeType() == Node.DOCUMENT_NODE) {
+ if (regionType == XMLRegionContext.XML_TAG_OPEN) {
+ contentAssistRequest = computeTagOpenProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+ } else if (regionType == XMLRegionContext.XML_TAG_NAME) {
+ contentAssistRequest = computeTagNameProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+ contentAssistRequest = computeAttributeProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+ contentAssistRequest = computeEqualsProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE && documentPosition == sdRegion.getTextEndOffset() && (sdRegion.getText(completionRegion).endsWith("\"") || sdRegion.getText(completionRegion).endsWith("\'"))) //$NON-NLS-1$ //$NON-NLS-2$
+ {
+ // this is for when the cursor is at the end of the closing
+ // quote for an attribute..
+ XMLNode actualNode = (XMLNode) xmlnode.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+ contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition, 0, matchString);
+ addTagCloseProposals(contentAssistRequest);
+ } else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+ contentAssistRequest = computeAttributeValueProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+ } else if ((regionType == XMLRegionContext.XML_TAG_CLOSE) || (regionType == XMLRegionContext.XML_EMPTY_TAG_CLOSE) || (regionType == XMLJSPRegionContexts.JSP_DIRECTIVE_CLOSE)) {
+ contentAssistRequest = computeTagCloseProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+ } else if (regionType == XMLRegionContext.XML_END_TAG_OPEN) {
+ contentAssistRequest = computeEndTagOpenProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+ } else if (regionType == XMLRegionContext.XML_CONTENT || regionType == XMLRegionContext.XML_CHAR_REFERENCE || regionType == XMLRegionContext.XML_ENTITY_REFERENCE || regionType == XMLRegionContext.XML_PE_REFERENCE) {
+ contentAssistRequest = computeContentProposals(documentPosition, matchString, completionRegion, treeNode, xmlnode);
+ }
+
+ // These ITextRegion types begin DOM Elements as well and although
+ // internally harder to assist,
+ // text insertions directly before them can be made
+ else if (documentPosition == sdRegion.getStartOffset(completionRegion) && (regionType == XMLJSPRegionContexts.JSP_COMMENT_OPEN || regionType == XMLJSPRegionContexts.JSP_DECLARATION_OPEN || regionType == XMLJSPRegionContexts.JSP_DIRECTIVE_OPEN || regionType == XMLJSPRegionContexts.JSP_EXPRESSION_OPEN || regionType == XMLJSPRegionContexts.JSP_SCRIPTLET_OPEN || regionType == XMLRegionContext.XML_DECLARATION_OPEN || regionType == XMLRegionContext.XML_PI_OPEN || regionType == XMLRegionContext.XML_COMMENT_OPEN || regionType == XMLRegionContext.XML_CDATA_OPEN)) {
+ contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+ addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode));
+ addStartDocumentProposals(contentAssistRequest);
+ }
+ }
+ // Not a Document or Element? (odd cases go here for now)
+ else if (isCloseRegion(completionRegion)) {
+ contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion) + completionRegion.getLength(), 0, matchString);
+ addStartDocumentProposals(contentAssistRequest);
+ if (documentPosition >= sdRegion.getTextEndOffset(completionRegion))
+ addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode) + 1);
+ } else if (documentPosition == sdRegion.getStartOffset(completionRegion) && (regionType == XMLJSPRegionContexts.JSP_COMMENT_OPEN || regionType == XMLJSPRegionContexts.JSP_DECLARATION_OPEN || regionType == XMLJSPRegionContexts.JSP_DIRECTIVE_OPEN || regionType == XMLJSPRegionContexts.JSP_EXPRESSION_OPEN || regionType == XMLJSPRegionContexts.JSP_SCRIPTLET_OPEN || regionType == XMLRegionContext.XML_DECLARATION_OPEN || regionType == XMLRegionContext.XML_PI_OPEN || regionType == XMLRegionContext.XML_COMMENT_OPEN || regionType == XMLRegionContext.XML_CDATA_OPEN)) {
+ contentAssistRequest = newContentAssistRequest(treeNode, xmlnode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+ addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(treeNode));
+ addStartDocumentProposals(contentAssistRequest);
+ }
+ return contentAssistRequest;
+ }
+
+ /**
+ * CONTENT ASSIST STARTS HERE
+ *
+ * Return a list of proposed code completions based on the specified
+ * location within the document that corresponds to the current cursor
+ * position within the text-editor control.
+ *
+ * @param textViewer
+ * @param documentPosition -
+ * the cursor location within the document
+ * @param treeNode -
+ * the Node at the documentPosition
+ *
+ * @return an array of ICompletionProposals
+ */
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer textViewer, int documentPosition) {
+
+ setErrorMessage(null);
+ macroContexts.clear();
+
+ fTextViewer = textViewer;
+
+ IndexedRegion treeNode = ContentAssistUtils.getNodeAt((StructuredTextViewer) textViewer, documentPosition);
+
+ Node node = (Node) treeNode;
+ while (node != null && node.getNodeType() == Node.TEXT_NODE && node.getParentNode() != null)
+ node = node.getParentNode();
+ XMLNode xmlnode = (XMLNode) node;
+
+ ContentAssistRequest contentAssistRequest = null;
+
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+ ITextRegion completionRegion = getCompletionRegion(documentPosition, node);
+
+ String matchString = getMatchString(sdRegion, completionRegion, documentPosition);
+
+ // Handle empty Documents
+ if (completionRegion == null) {
+ if (((treeNode == null) || ((Node) treeNode).getNodeType() == Node.DOCUMENT_NODE) && completionRegion == null && (xmlnode == null || xmlnode.getChildNodes() == null || xmlnode.getChildNodes().getLength() == 0)) {
+ IStructuredModel sModel = ((IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID)).getModelManager().getExistingModelForRead(textViewer.getDocument());
+ try {
+ if (sModel != null) {
+ XMLDocument docNode = ((XMLModel) sModel).getDocument();
+ contentAssistRequest = newContentAssistRequest(docNode, docNode, sdRegion, completionRegion, documentPosition, 0, null);
+ addEmptyDocumentProposals(contentAssistRequest);
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.ALL);
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.TAG);
+ }
+ } finally {
+ if (sModel != null)
+ sModel.releaseFromRead();
+ }
+ return contentAssistRequest.getCompletionProposals();
+ }
+ // MASSIVE ERROR CONDITION
+ Logger.logException(new IllegalStateException("completion region was null")); //$NON-NLS-1$
+ setErrorMessage(INTERNALERROR);
+ contentAssistRequest = newContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.ALL);
+ return contentAssistRequest.getCompletionProposals();
+ }
+
+
+ // catch documents where no region can be determined
+ if (xmlnode.getNodeType() == Node.DOCUMENT_NODE && (completionRegion == null || xmlnode.getChildNodes() == null || xmlnode.getChildNodes().getLength() == 0)) {
+ contentAssistRequest = computeStartDocumentProposals(documentPosition, matchString, completionRegion, (XMLNode) treeNode, xmlnode);
+ return contentAssistRequest.getCompletionProposals();
+ }
+
+ // compute normal proposals
+ contentAssistRequest = computeCompletionProposals(documentPosition, matchString, completionRegion, (XMLNode) treeNode, xmlnode);
+ if (contentAssistRequest == null) {
+ contentAssistRequest = newContentAssistRequest((Node) treeNode, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, ""); //$NON-NLS-1$
+ if (Debug.displayWarnings)
+ System.out.println(UNKNOWN_CONTEXT + " " + completionRegion.getType() + "@" + documentPosition); //$NON-NLS-2$//$NON-NLS-1$
+ setErrorMessage(UNKNOWN_CONTEXT);
+ }
+ // #180541
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.ALL);
+
+ if (contentAssistRequest.getProposals().size() == 0)
+ setErrorMessage(UNKNOWN_CONTEXT);
+
+ return contentAssistRequest.getCompletionProposals();
+ }
+
+ protected ContentAssistRequest computeContentProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode nodeAtOffset, XMLNode node) {
+ ContentAssistRequest contentAssistRequest = null;
+
+ // setup to add children at the content node's position
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition, 0, matchString);
+ if (node != null && node.getNodeType() == Node.DOCUMENT_NODE && ((Document) node).getDoctype() == null)
+ addStartDocumentProposals(contentAssistRequest);
+ addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+ if (node.getNodeType() != Node.DOCUMENT_NODE) {
+ addEndTagProposals(contentAssistRequest);
+ }
+ // entities?
+ addEntityProposals(contentAssistRequest, documentPosition, completionRegion, node);
+ //addEntityProposals(contentAssistRequest);
+ return contentAssistRequest;
+ }
+
+ /**
+ * Returns information about possible contexts based on the specified
+ * location within the document that corresponds to the current cursor
+ * position within the text viewer.
+ *
+ * @param viewer
+ * the viewer whose document is used to compute the possible
+ * contexts
+ * @param documentPosition
+ * an offset within the document for which context information
+ * should be computed
+ * @return an array of context information objects or <code>null</code>
+ * if no context could be found
+ */
+ public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
+ if (fAttributeInfoProvider == null)
+ fAttributeInfoProvider = new AttributeContextInformationProvider((IStructuredDocument) viewer.getDocument(), (AttributeContextInformationPresenter) getContextInformationValidator());
+ return fAttributeInfoProvider.getAttributeInformation(documentOffset);
+ }
+
+ protected ContentAssistRequest computeEndTagOpenProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode nodeAtOffset, XMLNode node) {
+ ContentAssistRequest contentAssistRequest = null;
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+ int completionRegionStart = sdRegion.getStartOffset(completionRegion);
+ int completionRegionLength = completionRegion.getLength();
+ IStructuredDocumentRegion sdRegionAtCompletionOffset = node.getStructuredDocument().getRegionAtCharacterOffset(completionRegionStart + completionRegionLength);
+ ITextRegion regionAtEndOfCompletion = sdRegionAtCompletionOffset.getRegionAtCharacterOffset(completionRegionStart + completionRegionLength);
+
+ if (documentPosition != completionRegionStart && regionAtEndOfCompletion != null && regionAtEndOfCompletion.getType() == XMLRegionContext.XML_TAG_NAME) {
+ ITextRegion nameRegion = regionAtEndOfCompletion;
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(nameRegion), nameRegion.getTextLength(), matchString);
+ } else {
+ if (nodeAtOffset.getFirstStructuredDocumentRegion() == sdRegion) {
+ // abnormal case, this unmatched end tag will be a sibling
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+ } else {
+ // normal case, this end tag is the parent
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, nodeAtOffset, sdRegion, completionRegion, documentPosition, 0, matchString);
+ }
+ }
+ //if (documentPosition >= sdRegion.getStartOffset(completionRegion) +
+ // completionRegion.getTextLength())
+ addEndTagProposals(contentAssistRequest);
+ //else
+ if (completionRegionStart == documentPosition) {
+ // positioned at start of end tag
+ addTagInsertionProposals(contentAssistRequest, node.getChildNodes().getLength());
+ }
+ return contentAssistRequest;
+ }
+
+ /**
+ * return all possible EntityReferenceProposals (according to current
+ * position in doc)
+ */
+ protected ICompletionProposal[] computeEntityReferenceProposals(int documentPosition, ITextRegion completionRegion, XMLNode treeNode) {
+ // only handle XML content for now
+ Vector proposals = new Vector(); // ICompletionProposals
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+ if (completionRegion != null && completionRegion.getType() == XMLRegionContext.XML_CONTENT) {
+ int nodeOffset = documentPosition - sdRegion.getStartOffset(completionRegion);
+ String regionText = sdRegion.getFullText(completionRegion);
+
+ //if directly to the right of a &, region will be null, need to
+ // move to
+ // the previous region...there might be a better way to do this
+ if (regionText != null && regionText.trim().equals("") && documentPosition > 0) { //$NON-NLS-1$
+ IStructuredDocumentRegion prev = treeNode.getStructuredDocument().getRegionAtCharacterOffset(documentPosition - 1);
+ if (prev != null && prev.getFullText().trim().equals("&")) { //$NON-NLS-1$
+ completionRegion = prev;
+ regionText = prev.getFullText();
+ nodeOffset = 1;
+ }
+ }
+
+ // string must start w/ &
+ if (regionText != null && regionText.startsWith("&")) { //$NON-NLS-1$
+ String key = (nodeOffset > 0) ? regionText.substring(1, nodeOffset) : ""; //$NON-NLS-1$
+
+ // get entity proposals, passing in the appropriate start
+ // string
+ ModelQuery mq = ModelQueryUtil.getModelQuery(((Node) treeNode).getOwnerDocument());
+ if (mq != null) {
+ CMDocument xmlDoc = mq.getCorrespondingCMDocument(treeNode);
+ CMNamedNodeMap cmmap = null;
+ Properties entities = null;
+ if (xmlDoc != null) {
+ cmmap = xmlDoc.getEntities();
+ }
+ if (cmmap != null) {
+ entities = mapToProperties(cmmap);
+ } else // 224787 in absence of content model, just use
+ // minimal 5 entities
+ {
+ entities = new Properties();
+ entities.put("quot", "\""); //$NON-NLS-1$ //$NON-NLS-2$
+ entities.put("apos", "'"); //$NON-NLS-1$ //$NON-NLS-2$
+ entities.put("amp", "&"); //$NON-NLS-1$ //$NON-NLS-2$
+ entities.put("lt", "<"); //$NON-NLS-1$ //$NON-NLS-2$
+ entities.put("gt", ">"); //$NON-NLS-1$ //$NON-NLS-2$
+ entities.put("nbsp", " "); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ addEntityProposals(proposals, entities, key, nodeOffset, sdRegion, completionRegion); //$NON-NLS-1$
+ }
+ }
+ }
+ return (ICompletionProposal[]) ((proposals.size() > 0) ? proposals.toArray(new ICompletionProposal[proposals.size()]) : null);
+ }
+
+ protected ContentAssistRequest computeEqualsProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode nodeAtOffset, XMLNode node) {
+ ContentAssistRequest contentAssistRequest = null;
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+ ITextRegion valueRegion = node.getStartStructuredDocumentRegion().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) + completionRegion.getLength());
+ if (valueRegion != null && valueRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE && sdRegion.getStartOffset(valueRegion) <= documentPosition) {
+ // replace the adjacent attribute value
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, valueRegion, sdRegion.getStartOffset(valueRegion), valueRegion.getTextLength(), matchString);
+ } else {
+ // append an attribute value after the '='
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+ }
+ addAttributeValueProposals(contentAssistRequest);
+ return contentAssistRequest;
+ }
+
+ protected ContentAssistRequest computeStartDocumentProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode nodeAtOffset, XMLNode node) {
+ // setup for a non-empty document, but one that hasn't been formally
+ // started
+ ContentAssistRequest contentAssistRequest = null;
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, getStructuredDocumentRegion(documentPosition), completionRegion, documentPosition, 0, matchString);
+ addStartDocumentProposals(contentAssistRequest);
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.TAG);
+ addTemplates(contentAssistRequest, TemplateContextTypeIds.ALL);
+ return contentAssistRequest;
+ }
+
+ protected ContentAssistRequest computeTagCloseProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode nodeAtOffset, XMLNode node) {
+ ContentAssistRequest contentAssistRequest = null;
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+
+ if ((node.getNodeType() == Node.DOCUMENT_NODE) || (documentPosition >= sdRegion.getEndOffset())) {
+ // this is a content request as the documentPosition is AFTER the
+ // end of the closing region
+ if (node == nodeAtOffset && node.getParentNode() != null)
+ node = (XMLNode) node.getParentNode();
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+ addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+ if (node.getNodeType() != Node.DOCUMENT_NODE && node.getEndStructuredDocumentRegion() == null) {
+ addEndTagProposals(contentAssistRequest);
+ }
+ } else {
+ // at the start of the tag's close or within it
+ ITextRegion closeRegion = sdRegion.getLastRegion();
+ boolean insideTag = !sdRegion.isEnded() || documentPosition <= sdRegion.getStartOffset(closeRegion);
+ if (insideTag) {
+ // this is a request for completions within a tag
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition, 0, matchString);
+ if (node.getNodeType() != Node.DOCUMENT_NODE && node.getEndStructuredDocumentRegion() != null) {
+ addTagCloseProposals(contentAssistRequest);
+ }
+ if (sdRegion == nodeAtOffset.getFirstStructuredDocumentRegion()) {
+ contentAssistRequest.setReplacementBeginPosition(documentPosition);
+ contentAssistRequest.setReplacementLength(0);
+ addAttributeNameProposals(contentAssistRequest);
+ }
+ }
+ }
+ return contentAssistRequest;
+ }
+
+ protected ContentAssistRequest computeTagNameProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode nodeAtOffset, XMLNode node) {
+ ContentAssistRequest contentAssistRequest = null;
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+
+ if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion()) {
+ //completing the *first* tag in "<tagname1 |<tagname2"
+ XMLNode actualNode = (XMLNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+ if (actualNode != null) {
+ if (actualNode.getFirstStructuredDocumentRegion() == sdRegion) {
+ // start tag
+ if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
+ // it's attributes
+ contentAssistRequest = newContentAssistRequest(actualNode, actualNode, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
+ if (node.getStructuredDocument().getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getRegionAtCharacterOffset(sdRegion.getStartOffset(completionRegion) - 1).getType() == XMLRegionContext.XML_TAG_OPEN)
+ addAttributeNameProposals(contentAssistRequest);
+ addTagCloseProposals(contentAssistRequest);
+ } else {
+ // it's name
+ contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
+ addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(actualNode));
+ }
+ } else {
+ if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getLength()) {
+ // insert name
+ contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+ } else {
+ //replace name
+ contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+ }
+ addEndTagNameProposals(contentAssistRequest);
+ }
+ }
+ } else {
+ if (documentPosition > sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
+ // unclosed tag with only a name; should prompt for attributes
+ // and a close instead
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node, sdRegion, completionRegion, documentPosition - matchString.length(), matchString.length(), matchString);
+ addAttributeNameProposals(contentAssistRequest);
+ addTagCloseProposals(contentAssistRequest);
+ } else {
+ if (sdRegion.getRegions().get(0).getType() != XMLRegionContext.XML_END_TAG_OPEN) {
+ contentAssistRequest = newContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+ addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+ } else {
+ XMLNode actualNode = (XMLNode) node.getModel().getIndexedRegion(documentPosition);
+ if (actualNode != null) {
+ if (documentPosition >= sdRegion.getStartOffset(completionRegion) + completionRegion.getTextLength()) {
+ contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+ } else {
+ contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+ }
+ addEndTagNameProposals(contentAssistRequest);
+ }
+ }
+ }
+ }
+ return contentAssistRequest;
+ }
+
+ protected ContentAssistRequest computeTagOpenProposals(int documentPosition, String matchString, ITextRegion completionRegion, XMLNode nodeAtOffset, XMLNode node) {
+ ContentAssistRequest contentAssistRequest = null;
+ IStructuredDocumentRegion sdRegion = getStructuredDocumentRegion(documentPosition);
+ if (sdRegion != nodeAtOffset.getFirstStructuredDocumentRegion()) {
+ //completing the *first* XML_TAG_OPEN in "<<tagname"
+ XMLNode actualNode = (XMLNode) node.getModel().getIndexedRegion(sdRegion.getStartOffset(completionRegion));
+ if (actualNode != null) {
+ contentAssistRequest = newContentAssistRequest(actualNode, actualNode.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+ addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(actualNode));
+ addEndTagProposals(contentAssistRequest); // (pa) 220850
+ }
+ } else {
+ if (documentPosition == sdRegion.getStartOffset(completionRegion)) {
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ // at the start of an existing tag, right before the '<'
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+ addTagInsertionProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+ addEndTagProposals(contentAssistRequest);
+ } else if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ // at the opening of the VERY first tag with a '<'
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(completionRegion), completionRegion.getTextLength(), matchString);
+ addStartDocumentProposals(contentAssistRequest);
+ }
+ } else {
+ // within the white space
+ ITextRegion name = getNameRegion(node.getStartStructuredDocumentRegion());
+ // (pa) ITextRegion refactor
+ //if (name != null && name.containsOffset(documentPosition))
+ // {
+ if (name != null && (sdRegion.getStartOffset(name) <= documentPosition && sdRegion.getEndOffset(name) >= documentPosition)) {
+ // replace the existing name
+ contentAssistRequest = newContentAssistRequest(node, node.getParentNode(), sdRegion, completionRegion, sdRegion.getStartOffset(name), name.getTextLength(), matchString);
+ } else {
+ // insert a valid new name, or possibly an end tag
+ contentAssistRequest = newContentAssistRequest(nodeAtOffset, ((Node) nodeAtOffset).getParentNode(), sdRegion, completionRegion, documentPosition, 0, matchString);
+ addEndTagProposals(contentAssistRequest);
+ contentAssistRequest.setReplacementBeginPosition(documentPosition);
+ contentAssistRequest.setReplacementLength(0);
+ }
+ addTagNameProposals(contentAssistRequest, getElementPositionForModelQuery(nodeAtOffset));
+ }
+ }
+ return contentAssistRequest;
+ }
+
+ /**
+ * Retreives cmnode's documentation to display in the completion
+ * proposal's additional info. If no documentation exists for cmnode, try
+ * displaying parentOrOwner's documentation
+ *
+ * @return String any documentation information to display for cmnode.
+ * <code>null</code> if there is nothing to display.
+ */
+ protected String getAdditionalInfo(CMNode parentOrOwner, CMNode cmnode) {
+ String addlInfo = null;
+
+ if (cmnode == null) {
+ if (Debug.displayWarnings) {
+ new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ addlInfo = getInfoProvider().getInfo(cmnode);
+ if (addlInfo == null && parentOrOwner != null)
+ addlInfo = getInfoProvider().getInfo(parentOrOwner);
+ return addlInfo;
+ }
+
+ // returns a list of ModelQueryActions
+ protected List getAvailableChildrenAtIndex(Element parent, int index) {
+ List list = new ArrayList();
+ CMElementDeclaration parentDecl = getCMElementDeclaration(parent);
+ if (parentDecl != null) {
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(parent.getOwnerDocument());
+ // taken from ActionManagers
+ // int editMode = modelQuery.getEditMode();
+ int editMode = ModelQuery.EDIT_MODE_UNCONSTRAINED;
+ int ic = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.INCLUDE_CHILD_NODES | ModelQuery.INCLUDE_SEQUENCE_GROUPS : ModelQuery.INCLUDE_CHILD_NODES;
+ int vc = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.VALIDITY_STRICT : ModelQuery.VALIDITY_NONE;
+ modelQuery.getInsertActions(parent, parentDecl, index, ic, vc, list);
+ }
+ return list;
+ }
+
+ // returns a list of CMElementDeclarations
+ protected List getAvailableRootChildren(Document document, int childIndex) {
+ List list = null;
+
+ // extract the valid 'root' node name from the DocumentType Node
+ DocumentType docType = document.getDoctype();
+ String rootName = null;
+ if (docType != null) {
+ rootName = docType.getNodeName();
+ }
+ if (rootName == null)
+ return new ArrayList(0);
+
+ for (Node child = document.getFirstChild(); child != null; child = child.getNextSibling()) {
+ //make sure the "root" Element isn't already present
+ // is it required to be an Element?
+ if (child.getNodeType() == Node.ELEMENT_NODE && stringsEqual(child.getNodeName(), rootName)) {
+ // if the node is missing either the start or end tag, don't
+ // count it as present
+ if (child instanceof XMLNode && (((XMLNode) child).getStartStructuredDocumentRegion() == null || ((XMLNode) child).getEndStructuredDocumentRegion() == null))
+ continue;
+ if (Debug.displayInfo)
+ System.out.println(rootName + " already present!"); //$NON-NLS-1$
+ setErrorMessage(ResourceHandler.getString("18concat", (new Object[]{rootName}))); //$NON-NLS-1$ = "The document element <{0}> is already present."
+ return new ArrayList(0);
+ }
+ }
+
+ list = new ArrayList(1);
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(document);
+ if (modelQuery != null) {
+ CMDocument cmdoc = modelQuery.getCorrespondingCMDocument(document);
+ if (cmdoc != null) {
+ if (rootName != null) {
+ CMElementDeclaration rootDecl = (CMElementDeclaration) cmdoc.getElements().getNamedItem(rootName);
+ if (rootDecl != null) {
+ list.add(rootDecl);
+ } else {
+ // supply the given document name anyway, even if it
+ // is an error
+ list.add(new SimpleCMElementDeclaration(rootName));
+ if (Debug.displayInfo || Debug.displayWarnings)
+ System.out.println("No definition found for " + rootName + " in " + docType.getPublicId() + "/" + docType.getSystemId()); //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ if (location.length() > 0)
+ setErrorMessage(ResourceHandler.getString("29concat", (new Object[]{rootName, location}))); //$NON-NLS-1$ = "No definition was found for element <{0}> in {1}"
+ else
+ setErrorMessage(ResourceHandler.getString("20concat", (new Object[]{rootName}))); //$NON-NLS-1$ = "No definition was found for element <{0}>"
+ }
+ }
+ } else {
+ if (Debug.displayInfo || Debug.displayWarnings)
+ System.out.println("No content model found."); //$NON-NLS-1$
+ //$NON-NLS-1$
+ //$NON-NLS-1$
+ String location = "" + (docType.getPublicId() != null ? docType.getPublicId() + "/" : "") + (docType.getSystemId() != null ? docType.getSystemId() : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ if (location.length() > 0)
+ setErrorMessage(ResourceHandler.getString("24concat", (new Object[]{location}))); //$NON-NLS-1$ = "No content model found for {0}."
+ else
+ setErrorMessage(ResourceHandler.getString("No_content_model_found_UI_")); //$NON-NLS-1$ = "No content model found"
+ }
+ }
+
+ return list;
+ }
+
+ protected CMElementDeclaration getCMElementDeclaration(Node node) {
+ CMElementDeclaration result = null;
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+ if (modelQuery != null)
+ result = modelQuery.getCMElementDeclaration((Element) node);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the characters which when entered by the user should
+ * automatically trigger the presentation of possible completions.
+ *
+ * @return the auto activation characters for completion proposal or
+ * <code>null</code> if no auto activation is desired
+ */
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ return completionProposalAutoActivationCharacters;
+ }
+
+ protected ITextRegion getCompletionRegion(int offset, IStructuredDocumentRegion sdRegion) {
+ ITextRegion region = sdRegion.getRegionAtCharacterOffset(offset);
+ if (region == null)
+ return null;
+
+ if (sdRegion.getStartOffset(region) == offset) {
+ // The offset is at the beginning of the region
+ if ((sdRegion.getStartOffset(region) == sdRegion.getStartOffset()) && (sdRegion.getPrevious() != null) && (!sdRegion.getPrevious().isEnded())) {
+ // Is the region also the start of the node? If so, the
+ // previous IStructuredDocumentRegion is
+ // where to look for a useful region.
+ region = sdRegion.getPrevious().getRegionAtCharacterOffset(offset - 1);
+ } else {
+ // Is there no separating whitespace from the previous region?
+ // If not,
+ // then that region is the important one
+ ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(offset - 1);
+ if ((previousRegion != null) && (previousRegion != region) && (previousRegion.getTextLength() == previousRegion.getLength())) {
+ region = previousRegion;
+ }
+ }
+ } else {
+ // The offset is NOT at the beginning of the region
+ if (offset > sdRegion.getStartOffset(region) + region.getTextLength()) {
+ // Is the offset within the whitespace after the text in this
+ // region?
+ // If so, use the next region
+ ITextRegion nextRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) + region.getLength());
+ if (nextRegion != null)
+ region = nextRegion;
+ } else {
+ // Is the offset within the important text for this region?
+ // If so, then we've already got the right one.
+ }
+ }
+
+ // valid WHITE_SPACE region handler (#179924)
+ if (region != null && region.getType() == XMLRegionContext.WHITE_SPACE) {
+ ITextRegion previousRegion = sdRegion.getRegionAtCharacterOffset(sdRegion.getStartOffset(region) - 1);
+ if (previousRegion != null)
+ region = previousRegion;
+ }
+
+ return region;
+ }
+
+ /**
+ * Return the region whose content's require completion. This is something
+ * of a misnomer as sometimes the user wants to be prompted for contents
+ * of a non-existant ITextRegion, such as for enumerated attribute values
+ * following an '=' sign.
+ */
+ protected ITextRegion getCompletionRegion(int documentPosition, Node domnode) {
+ if (domnode == null)
+ return null;
+
+ ITextRegion region = null;
+ int offset = documentPosition;
+ IStructuredDocumentRegion flatNode = null;
+ XMLNode node = (XMLNode) domnode;
+
+ if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ if (node.getStructuredDocument().getLength() == 0)
+ return null;
+ ITextRegion result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
+ while (result == null) {
+ offset--;
+ result = node.getStructuredDocument().getRegionAtCharacterOffset(offset).getRegionAtCharacterOffset(offset);
+ }
+ return result;
+ }
+
+ IStructuredDocumentRegion startTag = node.getStartStructuredDocumentRegion();
+ IStructuredDocumentRegion endTag = node.getEndStructuredDocumentRegion();
+
+ // Determine if the offset is within the start
+ // IStructuredDocumentRegion, end IStructuredDocumentRegion, or
+ // somewhere within the Node's XML content.
+ if ((startTag != null) && (startTag.getStartOffset() <= offset) && (offset < startTag.getStartOffset() + startTag.getLength()))
+ flatNode = startTag;
+ else if ((endTag != null) && (endTag.getStartOffset() <= offset) && (offset < endTag.getStartOffset() + endTag.getLength()))
+ flatNode = endTag;
+
+ if (flatNode != null) {
+ // the offset is definitely within the start or end tag, continue
+ // on and find the region
+ region = getCompletionRegion(offset, flatNode);
+ } else {
+ // the docPosition is neither within the start nor the end, so it
+ // must be content
+ flatNode = node.getStructuredDocument().getRegionAtCharacterOffset(offset);
+ // (pa) ITextRegion refactor
+ //if (flatNode.contains(documentPosition)) {
+ if (flatNode.getStartOffset() <= documentPosition && flatNode.getEndOffset() >= documentPosition) {
+ // we're interesting in completing/extending the previous
+ // IStructuredDocumentRegion if the current
+ // IStructuredDocumentRegion isn't plain content or if it's
+ // preceded by an orphan '<'
+ if ((offset == flatNode.getStartOffset()) && (flatNode.getPrevious() != null) && (flatNode.getRegionAtCharacterOffset(documentPosition) != null && flatNode.getRegionAtCharacterOffset(documentPosition).getType() != XMLRegionContext.XML_CONTENT || flatNode.getPrevious().getLastRegion().getType() == XMLRegionContext.XML_TAG_OPEN || flatNode.getPrevious().getLastRegion().getType() == XMLRegionContext.XML_END_TAG_OPEN)) {
+ // Is the region also the start of the node? If so, the
+ // previous IStructuredDocumentRegion is
+ // where to look for a useful region.
+ region = flatNode.getPrevious().getLastRegion();
+ } else if (flatNode.getEndOffset() == documentPosition) {
+ region = flatNode.getLastRegion();
+ } else
+ region = flatNode.getFirstRegion();
+ } else {
+ // catch end of document positions where the docPosition isn't
+ // in a IStructuredDocumentRegion
+ region = flatNode.getLastRegion();
+ }
+ }
+
+ return region;
+ }
+
+ /**
+ * Provided by default. Subclasses may override with their own
+ * implementations.
+ *
+ * @see AbstractContentAssistProcessor#getContentGenerator()
+ */
+ public XMLContentModelGenerator getContentGenerator() {
+ if (fGenerator == null)
+ fGenerator = new XMLContentModelGenerator();
+ return fGenerator;
+ }
+
+ /**
+ * Returns the characters which when entered by the user should
+ * automatically trigger the presentation of context information.
+ *
+ * @return the auto activation characters for presenting context
+ * information or <code>null</code> if no auto activation is
+ * desired
+ */
+ public char[] getContextInformationAutoActivationCharacters() {
+ return contextInformationAutoActivationCharacters;
+ }
+
+ /**
+ * Returns a validator used to determine when displayed context
+ * information should be dismissed. May only return <code>null</code> if
+ * the processor is incapable of computing context information.
+ *
+ * @return a context information validator, or <code>null</code> if the
+ * processor is incapable of computing context information
+ */
+ public IContextInformationValidator getContextInformationValidator() {
+ if (fContextInformationPresenter == null)
+ fContextInformationPresenter = new AttributeContextInformationPresenter();
+ return fContextInformationPresenter;
+ }
+
+ protected int getElementPosition(Node child) {
+ Node parent = child.getParentNode();
+ if (parent == null)
+ return 0;
+
+ NodeList children = parent.getChildNodes();
+ if (children == null)
+ return 0;
+ int count = 0;
+
+ for (int i = 0; i < children.getLength(); i++) {
+ if (children.item(i) == child)
+ return count;
+ else
+ // if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
+ count++;
+ }
+ return 0;
+ }
+
+ private int getElementPositionForModelQuery(Node child) {
+ return getElementPosition(child);
+ // return -1;
+ }
+
+ /**
+ * Return the reason why computeProposals was not able to find any
+ * completions.
+ *
+ * @return an error message or null if no error occurred
+ */
+ public String getErrorMessage() {
+ return fErrorMessage;
+ }
+
+ /**
+ * @param iResource
+ */
+ // public void initialize(IResource iResource) {
+ // this.resource = iResource;
+ // }
+ /**
+ * Gets the infoProvider.
+ *
+ * @return fInfoProvider and if fInfoProvider was <code>null</code>
+ * create a new instance
+ */
+ public MarkupTagInfoProvider getInfoProvider() {
+ if (fInfoProvider == null) {
+ fInfoProvider = new MarkupTagInfoProvider();
+ }
+ return fInfoProvider;
+ }
+
+ protected String getMatchString(IStructuredDocumentRegion parent, ITextRegion aRegion, int offset) {
+ if (aRegion == null || isCloseRegion(aRegion))
+ return ""; //$NON-NLS-1$
+ String matchString = null;
+ String regionType = aRegion.getType();
+ if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS || regionType == XMLRegionContext.XML_TAG_OPEN || (offset > parent.getStartOffset(aRegion) + aRegion.getTextLength())) {
+ matchString = ""; //$NON-NLS-1$
+ } else if (regionType == XMLRegionContext.XML_CONTENT) {
+ matchString = ""; //$NON-NLS-1$
+ } else {
+ if (parent.getText(aRegion).length() > 0 && parent.getStartOffset(aRegion) < offset)
+ matchString = parent.getText(aRegion).substring(0, offset - parent.getStartOffset(aRegion));
+ else
+ matchString = ""; //$NON-NLS-1$
+ }
+ return matchString;
+ }
+
+ protected ITextRegion getNameRegion(IStructuredDocumentRegion flatNode) {
+ if (flatNode == null)
+ return null;
+ Iterator regionList = flatNode.getRegions().iterator();
+ while (regionList.hasNext()) {
+ ITextRegion region = (ITextRegion) regionList.next();
+ if (isNameRegion(region))
+ return region;
+ }
+ return null;
+ }
+
+ /**
+ * Retrieves all of the possible valid values for this attribute
+ * declaration
+ */
+ protected List getPossibleDataTypeValues(Node node, CMAttributeDeclaration ad) {
+ List list = null;
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ Element element = (Element) node;
+ String[] dataTypeValues = null;
+ // The ModelQuery may not be available if the corresponding
+ // adapter
+ // is absent
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+ if (modelQuery != null) {
+ dataTypeValues = modelQuery.getPossibleDataTypeValues(element, ad);
+ } else {
+ if (ad.getAttrType() != null)
+ dataTypeValues = ad.getAttrType().getEnumeratedValues();
+ }
+ if (dataTypeValues != null) {
+ list = new ArrayList(dataTypeValues.length);
+ for (int i = 0; i < dataTypeValues.length; i++) {
+ list.add(dataTypeValues[i]);
+ }
+ }
+ }
+ if (list == null) {
+ list = new ArrayList(0);
+ }
+ return list;
+ }
+
+ protected String getRequiredName(Node parentOrOwner, CMNode cmnode) {
+ if (cmnode == null || parentOrOwner == null) {
+ if (Debug.displayWarnings) {
+ new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
+ }
+ return ""; //$NON-NLS-1$
+ }
+ return getContentGenerator().getRequiredName(parentOrOwner, cmnode);
+ }
+
+ protected String getRequiredText(Node parentOrOwner, CMAttributeDeclaration attrDecl) {
+ if (attrDecl == null) {
+ if (Debug.displayWarnings) {
+ new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$
+ }
+ return ""; //$NON-NLS-1$
+ }
+ StringBuffer buff = new StringBuffer();
+ getContentGenerator().generateRequiredAttribute(parentOrOwner, attrDecl, buff);
+ return buff.toString();
+ }
+
+ protected String getRequiredText(Node parentOrOwner, CMElementDeclaration elementDecl) {
+ if (elementDecl == null) {
+ if (Debug.displayWarnings) {
+ new IllegalArgumentException("Null attribute declaration!").printStackTrace(); //$NON-NLS-1$
+ }
+ return ""; //$NON-NLS-1$
+ }
+ StringBuffer buff = new StringBuffer();
+ getContentGenerator().generateTag(parentOrOwner, elementDecl, buff);
+ return buff.toString();
+ }
+
+ /**
+ * StructuredTextViewer must be set before using this.
+ */
+ public IStructuredDocumentRegion getStructuredDocumentRegion(int pos) {
+ // (pa) ITextRegion refactor defect 245190
+ //return
+ // (IStructuredDocumentRegion)ContentAssistUtils.getNodeAt((StructuredTextViewer)fTextViewer,
+ // pos);
+ return ContentAssistUtils.getStructuredDocumentRegion((StructuredTextViewer) fTextViewer, pos);
+ }
+
+ /**
+ * @param xmlEndTagOpen
+ * @return
+ */
+ private String getTagName(IStructuredDocumentRegion sdRegion) {
+ ITextRegionList regions = sdRegion.getRegions();
+ ITextRegion region = null;
+ String name = ""; //$NON-NLS-1$
+ for (int i = 0; i < regions.size(); i++) {
+ region = regions.get(i);
+ if (region.getType() == XMLRegionContext.XML_TAG_NAME) {
+ name = sdRegion.getText(region);
+ break;
+ }
+ }
+ return name;
+ }
+
+ /**
+ * Return the template completion processor to be used
+ *
+ * @return AbstractTemplateCompletionProcessor
+ */
+ protected AbstractTemplateCompletionProcessor getTemplateCompletionProcessor() {
+ return null;
+ }
+
+ protected List getValidCMNodes(int childPosition, int kindOfAction, List modelQueryActions) {
+ Iterator iterator = modelQueryActions.iterator();
+ List cmnodes = new Vector();
+ while (iterator.hasNext()) {
+ ModelQueryAction action = (ModelQueryAction) iterator.next();
+ if (childPosition < 0 || (action.getStartIndex() <= childPosition && childPosition <= action.getEndIndex()) && action.getKind() == kindOfAction) {
+ CMNode actionCMNode = action.getCMNode();
+ if (actionCMNode != null && !cmnodes.contains(actionCMNode))
+ cmnodes.add(actionCMNode);
+ }
+ }
+ return cmnodes;
+ }
+
+ /**
+ * Similar to the call in HTMLContentAssistProcessor. Pass in a node, it
+ * tells you if the document is XML type.
+ *
+ * @param node
+ * @return
+ */
+ protected boolean getXML(Node node) {
+ if (node == null)
+ return false;
+
+ Document doc = null;
+ doc = (node.getNodeType() != Node.DOCUMENT_NODE) ? node.getOwnerDocument() : ((Document) node);
+
+ return (doc instanceof XMLDocument) && ((XMLDocument) doc).isXMLType();
+ }
+
+ // Initialize local settings
+ protected void init() {
+ // implement in subclasses
+ }
+
+ protected boolean isCloseRegion(ITextRegion region) {
+ String type = region.getType();
+ return ((type == XMLRegionContext.XML_PI_CLOSE) || (type == XMLRegionContext.XML_TAG_CLOSE) || (type == XMLRegionContext.XML_EMPTY_TAG_CLOSE) || (type == XMLRegionContext.XML_CDATA_CLOSE) || (type == XMLRegionContext.XML_COMMENT_CLOSE) || (type == XMLRegionContext.XML_ATTLIST_DECL_CLOSE) || (type == XMLRegionContext.XML_ELEMENT_DECL_CLOSE) || (type == XMLRegionContext.XML_DOCTYPE_DECLARATION_CLOSE) || (type == XMLJSPRegionContexts.JSP_CLOSE) || (type == XMLJSPRegionContexts.JSP_COMMENT_CLOSE) || (type == XMLJSPRegionContexts.JSP_DIRECTIVE_CLOSE) || (type == XMLRegionContext.XML_DECLARATION_CLOSE));
+ }
+
+ /*
+ * This is to determine if a tag is a special meta-info comment tag that
+ * shows up as an ELEMENT
+ */
+ private boolean isCommentNode(XMLNode node) {
+ return (node != null && node instanceof XMLElement && ((XMLElement) node).isCommentTag());
+ }
+
+ /**
+ * Checks if cursor position is after doctype tag...
+ *
+ * @param car
+ * @return
+ */
+ protected boolean isCursorAfterDoctype(ContentAssistRequest car) {
+ Node aNode = car.getNode();
+ Document parent = aNode.getOwnerDocument();
+ int xmldoctypeNodePosition = -1;
+ boolean isAfterDoctype = true;
+
+ if (parent == null)
+ return true; // blank document case
+
+ for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child instanceof XMLNode) {
+ if (child.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ xmldoctypeNodePosition = ((XMLNode) child).getEndOffset();
+ isAfterDoctype = (car.getReplacementBeginPosition() >= xmldoctypeNodePosition);
+ break;
+ }
+ }
+ }
+ return isAfterDoctype;
+ }
+
+ /**
+ * This method can check if the cursor is after the XMLPI
+ *
+ * @param car
+ * @return
+ */
+ protected boolean isCursorAfterXMLPI(ContentAssistRequest car) {
+ Node aNode = car.getNode();
+ boolean xmlpiFound = false;
+ Document parent = aNode.getOwnerDocument();
+ int xmlpiNodePosition = -1;
+ boolean isAfterXMLPI = false;
+
+ if (parent == null)
+ return true; // blank document case
+
+ for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
+ boolean xmlpi = (child.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && child.getNodeName().equals("xml")); //$NON-NLS-1$
+ xmlpiFound = xmlpiFound || xmlpi;
+ if (xmlpiFound) {
+ if (child instanceof XMLNode) {
+ xmlpiNodePosition = ((XMLNode) child).getEndOffset();
+ isAfterXMLPI = (car.getReplacementBeginPosition() >= xmlpiNodePosition);
+ }
+ break;
+ }
+ }
+ return isAfterXMLPI;
+ }
+
+ protected boolean isNameRegion(ITextRegion region) {
+ String type = region.getType();
+ return ((type == XMLRegionContext.XML_TAG_NAME) || (type == XMLJSPRegionContexts.JSP_DIRECTIVE_NAME) || (type == XMLRegionContext.XML_ELEMENT_DECL_NAME) || (type == XMLRegionContext.XML_DOCTYPE_NAME) || (type == XMLRegionContext.XML_ATTLIST_DECL_NAME) || (type == XMLJSPRegionContexts.JSP_ROOT_TAG_NAME) || type == XMLJSPRegionContexts.JSP_DIRECTIVE_NAME);
+ }
+
+ protected boolean isQuote(String string) {
+ String trimmed = string.trim();
+ if (trimmed.length() > 0) {
+ return trimmed.charAt(0) == '\'' || trimmed.charAt(0) == '"';
+ }
+ return false;
+ }
+
+ /**
+ * @param xmlEndTagOpen
+ * @return
+ */
+ private boolean isSelfClosed(IStructuredDocumentRegion startTag) {
+ ITextRegionList regions = startTag.getRegions();
+ return regions.get(regions.size() - 1).getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE;
+ }
+
+ /**
+ * @param xmlEndTagOpen
+ * @return
+ */
+ private boolean isStartTag(IStructuredDocumentRegion sdRegion) {
+ boolean result = false;
+ if (sdRegion.getRegions().size() > 0) {
+ ITextRegion r = sdRegion.getRegions().get(0);
+ result = r.getType() == XMLRegionContext.XML_TAG_OPEN && sdRegion.isEnded();
+ }
+ return result;
+ }
+
+ protected Properties mapToProperties(CMNamedNodeMap map) {
+ Properties p = new Properties();
+ for (int i = 0; i < map.getLength(); i++) {
+ CMEntityDeclaration decl = (CMEntityDeclaration) map.item(i);
+ p.put(decl.getName(), decl.getValue());
+ }
+ return p;
+ }
+
+ /**
+ * Gets the corresponding XMLNode, and checks if it's closed.
+ *
+ * @param startTag
+ * @return
+ */
+ private boolean needsEndTag(IStructuredDocumentRegion startTag) {
+ boolean result = false;
+ IStructuredModel sModel = ((IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID)).getModelManager().getExistingModelForRead(fTextViewer.getDocument());
+ try {
+ if (sModel != null) {
+ XMLNode xmlNode = (XMLNode) sModel.getIndexedRegion(startTag.getStart());
+ if (!isStartTag(startTag))
+ result = false;
+ else if (isSelfClosed(startTag))
+ result = false;
+ else if (!xmlNode.isContainer())
+ result = false;
+ else
+ result = xmlNode.getEndStructuredDocumentRegion() == null;
+ }
+ } finally {
+ if (sModel != null)
+ sModel.releaseFromRead();
+ }
+ return result;
+ }
+
+ protected ContentAssistRequest newContentAssistRequest(Node node, Node possibleParent, IStructuredDocumentRegion documentRegion, ITextRegion completionRegion, int begin, int length, String filter) {
+ return new ContentAssistRequest(node, possibleParent, documentRegion, completionRegion, begin, length, filter, null);
+ }
+
+ public void release() {
+ fGenerator = null;
+ }
+
+ /**
+ * Set the reason why computeProposals was not able to find any
+ * completions.
+ */
+ public void setErrorMessage(String errorMessage) {
+ fErrorMessage = errorMessage;
+ }
+
+ /**
+ * Set the reason why computeProposals was not able to find any
+ * completions.
+ */
+ protected void setErrorMessage(String errorMessage, String append) {
+ setErrorMessage(errorMessage + append);
+ }
+
+ /**
+ * Set the reason why computeProposals was not able to find any
+ * completions.
+ */
+ protected void setErrorMessage(String errorMessage, String prepend, String append) {
+ setErrorMessage(prepend + errorMessage + append);
+ }
+
+ protected boolean stringsEqual(String a, String b) {
+ // (pa) 221190 matching independent of case to be consistant with Java
+ // editor CA
+ return a.equalsIgnoreCase(b);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractContentModelGenerator.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractContentModelGenerator.java
new file mode 100644
index 0000000000..27b0d7267b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractContentModelGenerator.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.util.DOMNamespaceHelper;
+import org.w3c.dom.Node;
+
+
+public abstract class AbstractContentModelGenerator {
+
+ public static boolean generateChildren = false;
+
+ public AbstractContentModelGenerator() {
+ super();
+ }
+
+ public abstract void generateAttribute(CMAttributeDeclaration attrDecl, StringBuffer buffer);
+
+ protected void generateAttributes(CMElementDeclaration elementDecl, StringBuffer buffer) {
+ CMNamedNodeMap attributes = elementDecl.getAttributes();
+ if (attributes == null)
+ return;
+ for (int i = 0; i < attributes.getLength(); i++) {
+ generateAttribute((CMAttributeDeclaration) attributes.item(i), buffer);
+ }
+ return;
+ }
+
+ protected abstract void generateEndTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer);
+
+ public void generateRequiredChildren(Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer) {
+ if (generateChildren) {
+ }
+ return;
+ }
+
+ protected abstract void generateStartTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer);
+
+ public void generateTag(Node parent, CMElementDeclaration elementDecl, StringBuffer buffer) {
+ if (elementDecl == null || buffer == null)
+ return;
+
+ String tagName = getRequiredName(parent, elementDecl);
+
+ generateStartTag(tagName, parent, elementDecl, buffer);
+ generateRequiredChildren(parent, elementDecl, buffer);
+ generateEndTag(tagName, parent, elementDecl, buffer);
+ return;
+ }
+
+ public abstract int getMinimalStartTagLength(Node node, CMElementDeclaration elementDecl);
+
+ public String getRequiredName(Node ownerNode, CMNode cmnode) {
+ if (ownerNode != null) {
+ return DOMNamespaceHelper.computeName(cmnode, ownerNode, null);
+ }
+ return cmnode.getNodeName();
+ }
+
+ public abstract String getStartTagClose(Node parentNode, CMElementDeclaration elementDecl);
+
+ protected boolean requiresAttributes(CMElementDeclaration ed) {
+ CMNamedNodeMap attributes = ed.getAttributes();
+ if (attributes == null)
+ return false;
+ for (int i = 0; i < attributes.getLength(); i++) {
+ if (((CMAttributeDeclaration) attributes.item(i)).getUsage() == CMAttributeDeclaration.REQUIRED)
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractTemplateCompletionProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractTemplateCompletionProcessor.java
new file mode 100644
index 0000000000..542a7e6397
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AbstractTemplateCompletionProcessor.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+
+/**
+ * A completion processor that computes template proposals and works with
+ * AbstractContentAssistProcessor
+ */
+abstract public class AbstractTemplateCompletionProcessor extends TemplateCompletionProcessor {
+ private String fContextTypeId = null;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#createProposal(org.eclipse.jface.text.templates.Template,
+ * org.eclipse.jface.text.templates.TemplateContext,
+ * org.eclipse.jface.text.Region, int)
+ */
+ protected ICompletionProposal createProposal(Template template, TemplateContext context, Region region, int relevance) {
+ // CustomTemplateProposal turns the additional information to content
+ // fit for HTML
+ return new CustomTemplateProposal(template, context, region, getImage(template), relevance);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getContextType(org.eclipse.jface.text.ITextViewer,
+ * org.eclipse.jface.text.IRegion)
+ */
+ protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) {
+ // another completion processor should have already set the current
+ // context type id, so just use that value instead of trying to
+ // determine
+ // the context type again
+ if (getTemplateContextRegistry() != null) {
+ return getTemplateContextRegistry().getContextType(getContextTypeId());
+ }
+ return null;
+ }
+
+ protected String getContextTypeId() {
+ return fContextTypeId;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getImage(org.eclipse.jface.text.templates.Template)
+ */
+ protected Image getImage(Template template) {
+ // just return the same image for now
+ return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TAG_MACRO);
+ }
+
+ /**
+ * Return the template context registry to use with this completion
+ * processor
+ *
+ * @return ContextTypeRegistry
+ */
+ abstract protected ContextTypeRegistry getTemplateContextRegistry();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getTemplates(java.lang.String)
+ */
+ protected Template[] getTemplates(String contextTypeId) {
+ if (getTemplateStore() != null) {
+ return getTemplateStore().getTemplates(contextTypeId);
+ }
+ return null;
+ }
+
+ /**
+ * Return the template store to use with this template completion
+ * processor
+ *
+ * @return TemplateStore
+ */
+ abstract protected TemplateStore getTemplateStore();
+
+ /**
+ * Set the current context type to use when determining completion
+ * proposals.
+ *
+ * @param contextTypeId
+ */
+ public void setContextType(String contextTypeId) {
+ fContextTypeId = contextTypeId;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformation.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformation.java
new file mode 100644
index 0000000000..79048fba87
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformation.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationExtension;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.ui.util.Assert;
+
+
+/**
+ * Implementation of IContextInformation. Adds knowledge about the information
+ * display string such as required attributes for this context.
+ *
+ * @author pavery
+ */
+public class AttributeContextInformation implements IContextInformation {
+ private HashMap fAttr2RangeMap;
+ /** The name of the context */
+ private String fContextDisplayString;
+ /** The image to be displayed */
+ private Image fImage;
+ /** The information to be displayed */
+ private String fInformationDisplayString;
+ private int fPosition;
+
+ /**
+ * Creates a new context information with an image.
+ *
+ * @param image
+ * the image to display when presenting the context information
+ * @param contextDisplayString
+ * the string to be used when presenting the context
+ * @param informationDisplayString
+ * the string to be displayed when presenting the context
+ * information, may not be <code>null</code>
+ */
+ public AttributeContextInformation(Image image, String contextDisplayString, String informationDisplayString, HashMap attr2RangeMap) {
+ Assert.isNotNull(informationDisplayString);
+
+ fImage = image;
+ fContextDisplayString = contextDisplayString;
+ fInformationDisplayString = informationDisplayString;
+ fAttr2RangeMap = attr2RangeMap;
+ }
+
+ /**
+ * Creates a new context information without an image.
+ *
+ * @param contextDisplayString
+ * the string to be used when presenting the context
+ * @param informationDisplayString
+ * the string to be displayed when presenting the context
+ * information
+ */
+ public AttributeContextInformation(String contextDisplayString, String informationDisplayString, HashMap attr2RangeMap) {
+ this(null, contextDisplayString, informationDisplayString, attr2RangeMap);
+ }
+
+ /**
+ * Maps (String -> Position). The attribute name to the Text position.
+ *
+ * @return
+ */
+ public HashMap getAttr2RangeMap() {
+ return fAttr2RangeMap;
+ }
+
+ /**
+ * @see org.eclipse.jface.text.contentassist.IContextInformation#getContextDisplayString()
+ */
+ public String getContextDisplayString() {
+ if (fContextDisplayString != null)
+ return fContextDisplayString;
+ return fInformationDisplayString;
+ }
+
+ /**
+ * @see IContextInformationExtension#getContextInformationPosition()
+ */
+ public int getContextInformationPosition() {
+ return fPosition;
+ }
+
+ /**
+ * @see org.eclipse.jface.text.contentassist.IContextInformation#getImage()
+ */
+ public Image getImage() {
+ return fImage;
+ }
+
+ /**
+ * @see org.eclipse.jface.text.contentassist.IContextInformation#getInformationDisplayString()
+ */
+ public String getInformationDisplayString() {
+ return fInformationDisplayString;
+ }
+
+ public void setContextInformationPosition(int position) {
+ fPosition = position;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformationPresenter.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformationPresenter.java
new file mode 100644
index 0000000000..ab19b30c7e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformationPresenter.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+/**
+ * Responsible for the presentation of the context info popup. This includes
+ * text style, and when the window should close.
+ *
+ * @author pavery
+ */
+public class AttributeContextInformationPresenter implements IContextInformationPresenter, IContextInformationValidator {
+ private int fDocumentPosition = -1;
+
+ private IContextInformation fInfo = null;
+ private ContextInfoModelUtil fModelUtil = null;
+ private ITextViewer fViewer = null;
+
+ /**
+ * @see org.eclipse.jface.text.contentassist.IContextInformationValidator#install(org.eclipse.jface.text.contentassist.IContextInformation,
+ * org.eclipse.jface.text.ITextViewer, int)
+ */
+ public void install(IContextInformation info, ITextViewer viewer, int documentPosition) {
+ fInfo = info;
+ fViewer = viewer;
+ fDocumentPosition = documentPosition;
+ fModelUtil = new ContextInfoModelUtil((IStructuredDocument) fViewer.getDocument());
+ }
+
+ /**
+ * @see org.eclipse.jface.text.contentassist.IContextInformationValidator#isContextInformationValid(int)
+ */
+ public boolean isContextInformationValid(int documentPosition) {
+ // determine whether or not this context info should still be
+ // showing...
+ // if cursor still within the element it's valid...
+ IStructuredDocumentRegion startRegion = fModelUtil.getXMLNode(fDocumentPosition).getStartStructuredDocumentRegion();
+ int start = startRegion.getStartOffset();
+ int end = startRegion.getEndOffset();
+ return documentPosition < end && documentPosition > start + 1;
+ }
+
+ /**
+ * @see org.eclipse.jface.text.contentassist.IContextInformationPresenter#updatePresentation(int,
+ * org.eclipse.jface.text.TextPresentation)
+ */
+ public boolean updatePresentation(int documentPosition, TextPresentation presentation) {
+ presentation.clear();
+
+ if (!(fInfo instanceof AttributeContextInformation))
+ return false;
+
+ // iterate existing attributes from current node
+ XMLNode xmlNode = fModelUtil.getXMLNode(documentPosition);
+ IStructuredDocumentRegion sdRegion = xmlNode.getFirstStructuredDocumentRegion();
+ ITextRegionList regions = sdRegion.getRegions();
+ ITextRegion r = null;
+ String attrName = ""; //$NON-NLS-1$
+ Object temp = null;
+ Position p = null;
+ HashMap map = ((AttributeContextInformation) fInfo).getAttr2RangeMap();
+
+ // so we can add ranges in order
+ StyleRange[] sorted = new StyleRange[fInfo.getInformationDisplayString().length()];
+ for (int i = 0; i < regions.size(); i++) {
+ r = regions.get(i);
+ if (r.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+ attrName = sdRegion.getText(r);
+ temp = map.get(attrName);
+ if (temp != null) {
+ p = (Position) temp;
+ sorted[p.offset] = new StyleRange(p.offset, p.length, null, null, SWT.BOLD);
+ }
+ }
+ }
+ // style ranges need to be added in order
+ StyleRange sr = null;
+ for (int i = 0; i < sorted.length; i++) {
+ sr = sorted[i];
+ if (sr != null)
+ presentation.addStyleRange(sr);
+ }
+ return true;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformationProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformationProvider.java
new file mode 100644
index 0000000000..fd5b96d255
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/AttributeContextInformationProvider.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.contentassist.ContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMContent;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMGroup;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.CMNodeList;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * Calculates attribute context information based on a StructuedDocument and
+ * document position.
+ *
+ * @author pavery
+ */
+class AttributeContextInformationProvider {
+ private final IContextInformation[] EMPTY_CONTEXT_INFO = new IContextInformation[0];
+ private Comparator fComparator;
+
+ private IStructuredDocument fDocument = null;
+ private ContextInfoModelUtil fModelUtil = null;
+
+ public AttributeContextInformationProvider(IStructuredDocument doc, AttributeContextInformationPresenter presenter) {
+ fDocument = doc;
+ fModelUtil = new ContextInfoModelUtil(fDocument);
+ }
+
+ /**
+ * @param sdRegion
+ * @return
+ */
+ private boolean canProposeInfo(IStructuredDocumentRegion sdRegion) {
+ if (sdRegion != null && isEndTag(sdRegion))
+ return false;
+ else
+ return true;
+ }
+
+ public IContextInformation[] getAttributeInformation(int offset) {
+ /*
+ * need to take care of special cases w/ ambiguous regions <tag>|
+ * </tag> also end tags..
+ */
+ IContextInformation[] results = EMPTY_CONTEXT_INFO;
+
+ IStructuredDocumentRegion sdRegion = fModelUtil.getDocument().getRegionAtCharacterOffset(offset);
+ if (!canProposeInfo(sdRegion))
+ return EMPTY_CONTEXT_INFO;
+
+ XMLNode node = fModelUtil.getXMLNode(offset);
+ if (node != null) {
+ switch (node.getNodeType()) {
+ case Node.ELEMENT_NODE :
+ results = getInfoForElement(node);
+ break;
+ // future...
+ // case Node.TEXT_NODE :
+ // results = getInfoForText(node);
+ // break;
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Returns a comparator that compares CMAttributeDeclaration names.
+ *
+ * @return the comparator
+ */
+ private Comparator getCMAttributeComparator() {
+ if (fComparator == null)
+ fComparator = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return ((CMAttributeDeclaration) o1).getAttrName().compareTo(((CMAttributeDeclaration) o2).getAttrName());
+ }
+ };
+ return fComparator;
+ }
+
+ /**
+ * @param node
+ * @return
+ */
+ private IContextInformation[] getInfoForElement(XMLNode node) {
+ IContextInformation[] results = EMPTY_CONTEXT_INFO;
+ CMElementDeclaration decl = fModelUtil.getModelQuery().getCMElementDeclaration((Element) node);
+ if (decl != null) {
+ CMNamedNodeMap attributes = decl.getAttributes();
+
+ String attrContextString = node.getNodeName();
+ StringBuffer attrInfo = new StringBuffer(" "); //$NON-NLS-1$
+ String name = ""; //$NON-NLS-1$
+ HashMap attrPosMap = new HashMap();
+ int pos = 0;
+ int length = 0;
+ int numPerLine = 8;
+
+ CMAttributeDeclaration[] sortedAttrs = getSortedAttributes(attributes);
+
+ for (int i = 0; i < sortedAttrs.length; i++) {
+ name = sortedAttrs[i].getAttrName();
+ length = name.length();
+ pos = attrInfo.length();
+
+ attrInfo.append(name);
+
+ if (sortedAttrs[i].getUsage() == CMAttributeDeclaration.REQUIRED) {
+ attrInfo.append("*"); //$NON-NLS-1$
+ length++;
+ }
+ if (i < attributes.getLength() - 1) {
+ attrInfo.append(" "); //$NON-NLS-1$
+ if (i != 0 && i % numPerLine == 0)
+ attrInfo.append("\n "); //$NON-NLS-1$
+ }
+ attrPosMap.put(name, new Position(pos, length));
+ }
+ if (!attrInfo.toString().trim().equals("")) //$NON-NLS-1$
+ return new IContextInformation[]{new AttributeContextInformation(attrContextString, attrInfo.toString(), attrPosMap)};
+ }
+ return results;
+ }
+
+ /**
+ * @param node
+ * @return
+ */
+ IContextInformation[] getInfoForText(XMLNode node) {
+ Node parent = node.getParentNode();
+ String contextString = node.getNodeName();
+ StringBuffer info = new StringBuffer(" "); //$NON-NLS-1$
+ if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
+ CMElementDeclaration decl = fModelUtil.getModelQuery().getCMElementDeclaration((Element) parent);
+ CMContent content = decl.getContent();
+ if (content instanceof CMGroup) {
+ CMGroup cmGroup = (CMGroup) content;
+ CMNodeList children = cmGroup.getChildNodes();
+ CMNode cmNode = null;
+ for (int i = 0; i < children.getLength(); i++) {
+ cmNode = children.item(i);
+ contextString = cmNode.getNodeName();
+ if (contextString != null) {
+ info.append("<" + cmNode.getNodeName() + ">"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (i < children.getLength() - 1)
+ info.append(" "); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ if (!info.toString().trim().equals("")) //$NON-NLS-1$
+ return new IContextInformation[]{new ContextInformation(contextString, info.toString())};
+ else
+ return EMPTY_CONTEXT_INFO;
+ }
+
+ /**
+ * Returns sorted array of CMAttributeDeclarations.
+ *
+ * @param attributes
+ * @return
+ */
+ private CMAttributeDeclaration[] getSortedAttributes(CMNamedNodeMap attributes) {
+ List sorted = new ArrayList();
+ for (int i = 0; i < attributes.getLength(); i++)
+ sorted.add(attributes.item(i));
+ Collections.sort(sorted, getCMAttributeComparator());
+ return (CMAttributeDeclaration[]) sorted.toArray(new CMAttributeDeclaration[sorted.size()]);
+ }
+
+ /**
+ * @param sdRegion
+ * @return
+ */
+ private boolean isEndTag(IStructuredDocumentRegion sdRegion) {
+ ITextRegionList regions = sdRegion.getRegions();
+ return regions.get(0).getType() == XMLRegionContext.XML_END_TAG_OPEN;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ContentAssistRequest.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ContentAssistRequest.java
new file mode 100644
index 0000000000..083829e210
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ContentAssistRequest.java
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionCollection;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.sse.ui.preferences.PreferenceManager;
+import org.w3c.dom.Node;
+
+
+public class ContentAssistRequest {
+ protected IStructuredDocumentRegion documentRegion = null;
+
+
+ protected PreferenceManager fPreferenceManager = null;
+ protected List macros = new ArrayList();
+ protected String matchString;
+ protected Node node = null;
+ protected Node parent = null;
+ protected List proposals = new ArrayList();
+ protected ITextRegion region = null;
+ protected int replacementBeginPosition;
+ protected int replacementLength;
+
+ // private Boolean separate = null; // (pa) not used
+ // private Boolean sort = null; // (pa) not used
+ /**
+ * XMLContentAssistRequest constructor comment.
+ */
+ public ContentAssistRequest(Node node, Node parent, IStructuredDocumentRegion documentRegion, ITextRegion completionRegion, int begin, int length, String filter, PreferenceManager preferencesManager) {
+ super();
+ setNode(node);
+ setParent(parent);
+ setDocumentRegion(documentRegion);
+ setRegion(completionRegion);
+ setMatchString(filter);
+ setReplacementBeginPosition(begin);
+ setReplacementLength(length);
+ fPreferenceManager = preferencesManager;
+ }
+
+ public void addMacro(ICompletionProposal newProposal) {
+ macros.add(newProposal);
+ }
+
+ public void addProposal(ICompletionProposal newProposal) {
+ proposals.add(newProposal);
+ }
+
+ public ICompletionProposal[] getCompletionProposals() {
+ ICompletionProposal results[] = null;
+ if (getProposals().size() > 0 || getMacros().size() > 0) {
+ List allProposals = new ArrayList();
+ if (!shouldSeparate()) {
+ allProposals.addAll(getProposals());
+ // should be empty, as all macros should have gone into the
+ // proposal list
+ allProposals.addAll(getMacros());
+ allProposals = sortProposals(allProposals);
+ } else {
+ allProposals.addAll(sortProposals(getProposals()));
+ allProposals.addAll(sortProposals(getMacros()));
+ }
+
+ results = new ICompletionProposal[allProposals.size()];
+ for (int i = 0; i < allProposals.size(); i++) {
+ results[i] = (ICompletionProposal) allProposals.get(i);
+ }
+ }
+ return results;
+ }
+
+ /**
+ *
+ * @return com.ibm.sed.structuredDocument.core.IStructuredDocumentRegion
+ */
+ public IStructuredDocumentRegion getDocumentRegion() {
+ return documentRegion;
+ }
+
+ /**
+ *
+ * @return java.util.List
+ */
+ public java.util.List getMacros() {
+ return macros;
+ }
+
+ /**
+ *
+ * @return java.lang.String
+ */
+ public java.lang.String getMatchString() {
+ return matchString;
+ }
+
+ /**
+ *
+ * @return org.w3c.dom.Node
+ */
+ public org.w3c.dom.Node getNode() {
+ return node;
+ }
+
+ /**
+ *
+ * @return org.w3c.dom.Node
+ */
+ public org.w3c.dom.Node getParent() {
+ return parent;
+ }
+
+ public PreferenceManager getPreferenceManager() {
+ return fPreferenceManager;
+ }
+
+ /**
+ *
+ * @return java.util.List
+ */
+ public java.util.List getProposals() {
+ return proposals;
+ }
+
+ /**
+ *
+ * @return com.ibm.sed.structuredDocument.core.ITextRegion
+ */
+ public ITextRegion getRegion() {
+ return region;
+ }
+
+ /**
+ *
+ * @return int
+ */
+ public int getReplacementBeginPosition() {
+ return replacementBeginPosition;
+ }
+
+ /**
+ * @return int
+ */
+ public int getReplacementLength() {
+ return replacementLength;
+ }
+
+ public int getStartOffset() {
+ if (getDocumentRegion() != null && getRegion() != null)
+ return ((ITextRegionCollection) getDocumentRegion()).getStartOffset(getRegion());
+ return -1;
+ }
+
+ public String getText() {
+ if (getDocumentRegion() != null && getRegion() != null)
+ return ((ITextRegionCollection) getDocumentRegion()).getText(getRegion());
+ return ""; //$NON-NLS-1$
+ }
+
+ public int getTextEndOffset() {
+ if (getDocumentRegion() != null && getRegion() != null)
+ return ((ITextRegionCollection) getDocumentRegion()).getTextEndOffset(getRegion());
+ return -1;
+ }
+
+ /**
+ * @param region
+ */
+ public void setDocumentRegion(IStructuredDocumentRegion region) {
+ documentRegion = region;
+ }
+
+ /**
+ *
+ * @param newMatchString
+ * java.lang.String
+ */
+ public void setMatchString(java.lang.String newMatchString) {
+ matchString = newMatchString;
+ }
+
+ /**
+ *
+ * @param newNode
+ * org.w3c.dom.Node
+ */
+ public void setNode(org.w3c.dom.Node newNode) {
+ node = newNode;
+ }
+
+ /**
+ *
+ * @param newParent
+ * org.w3c.dom.Node
+ */
+ public void setParent(org.w3c.dom.Node newParent) {
+ parent = newParent;
+ }
+
+ /**
+ *
+ * @param newRegion
+ * com.ibm.sed.structuredDocument.ITextRegion
+ */
+ public void setRegion(ITextRegion newRegion) {
+ region = newRegion;
+ }
+
+ /**
+ *
+ * @param newReplacementBeginPosition
+ * int
+ */
+ public void setReplacementBeginPosition(int newReplacementBeginPosition) {
+ replacementBeginPosition = newReplacementBeginPosition;
+ }
+
+ /**
+ *
+ * @param newReplacementEndPosition
+ * int
+ */
+ public void setReplacementLength(int newReplacementLength) {
+ replacementLength = newReplacementLength;
+ }
+
+ public boolean shouldSeparate() {
+ /*
+ * if (separate == null) { PreferenceManager manager =
+ * getPreferenceManager(); if(manager == null) { separate =
+ * Boolean.FALSE; } else { Element caSettings =
+ * manager.getElement(PreferenceNames.CONTENT_ASSIST); separate = new
+ * Boolean(caSettings.getAttribute(PreferenceNames.SEPARATE).equals(PreferenceNames.TRUE)); } }
+ * return separate.booleanValue();
+ */
+ return false;
+ }
+
+ protected List sortProposals(List proposalsIn) {
+ Collections.sort(proposalsIn, new ProposalComparator());
+ return proposalsIn;
+
+ }
+
+ /**
+ *
+ * @return java.lang.String
+ */
+ public java.lang.String toString() {
+ return "Node: " + getNode() //$NON-NLS-1$
+ + "\nParent: " + getParent() //$NON-NLS-1$
+ + "\nStructuredDocumentRegion: " + StringUtils.escape(getDocumentRegion().toString()) //$NON-NLS-1$
+ + "\nRegion: " + getRegion() //$NON-NLS-1$
+ + "\nMatch string: '" + StringUtils.escape(getMatchString()) + "'" //$NON-NLS-2$//$NON-NLS-1$
+ + "\nOffsets: [" + getReplacementBeginPosition() + "-" + (getReplacementBeginPosition() + getReplacementLength()) + "]\n"; //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ContextInfoModelUtil.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ContextInfoModelUtil.java
new file mode 100644
index 0000000000..7810b073c8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ContextInfoModelUtil.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.core.IModelManager;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+
+
+/**
+ * @author pavery
+ */
+public class ContextInfoModelUtil {
+ IStructuredDocument fDocument = null;
+ private final String SSE_MODEL_ID = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+
+ ContextInfoModelUtil(IStructuredDocument doc) {
+ fDocument = doc;
+ }
+
+ public IStructuredDocument getDocument() {
+ return fDocument;
+ }
+
+ public IModelManager getModelManager() {
+ return ((IModelManagerPlugin) Platform.getPlugin(SSE_MODEL_ID)).getModelManager();
+ }
+
+ public ModelQuery getModelQuery() {
+ ModelQuery mq = null;
+
+ XMLModel xmlModel = (XMLModel) getModelManager().getExistingModelForRead(getDocument());
+ mq = ModelQueryUtil.getModelQuery(xmlModel.getDocument());
+ xmlModel.releaseFromRead();
+
+ return mq;
+ }
+
+ public XMLNode getXMLNode(int offset) {
+ XMLModel xmlModel = (XMLModel) getModelManager().getExistingModelForRead(getDocument());
+ XMLNode xmlNode = (XMLNode) xmlModel.getIndexedRegion(offset);
+ xmlModel.releaseFromRead();
+ return xmlNode;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/CustomTemplateProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/CustomTemplateProposal.java
new file mode 100644
index 0000000000..27b24fe59a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/CustomTemplateProposal.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateProposal;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.sse.ui.contentassist.IRelevanceCompletionProposal;
+
+
+/**
+ * Purpose of this class is to make the additional proposal info into content
+ * fit for an HTML viewer (by escaping characters)
+ */
+public class CustomTemplateProposal extends TemplateProposal implements IRelevanceCompletionProposal {
+
+ /**
+ * @param template
+ * @param context
+ * @param region
+ * @param image
+ */
+ public CustomTemplateProposal(Template template, TemplateContext context, IRegion region, Image image) {
+ super(template, context, region, image);
+ }
+
+ /**
+ * @param template
+ * @param context
+ * @param region
+ * @param image
+ * @param relevance
+ */
+ public CustomTemplateProposal(Template template, TemplateContext context, IRegion region, Image image, int relevance) {
+ super(template, context, region, image, relevance);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ String additionalInfo = super.getAdditionalProposalInfo();
+ return StringUtils.convertToHTMLContent(additionalInfo);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/NoRegionContentAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/NoRegionContentAssistProcessor.java
new file mode 100644
index 0000000000..727b1ed635
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/NoRegionContentAssistProcessor.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.ui.IReleasable;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.contentassist.IResourceDependentProcessor;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.eclipse.wst.xml.core.text.rules.StructuredTextPartitionerForXML;
+
+
+/**
+ * ContentAssistProcessor to handle special cases in content assist where the
+ * partitioner cannot determine a partition type at the current cursor
+ * position (usually at EOF).
+ *
+ * @author pavery
+ */
+public class NoRegionContentAssistProcessor implements IContentAssistProcessor, IResourceDependentProcessor, IReleasable {
+
+ protected char completionProposalAutoActivationCharacters[] = null;
+ protected char contextInformationAutoActivationCharacters[] = null;
+
+ private final ICompletionProposal[] EMPTY_PROPOSAL_SET = new ICompletionProposal[0];
+ protected String fErrorMessage = null;
+ protected HashMap fNameToProcessorMap = null;
+ protected HashMap fPartitionToProcessorMap = null;
+ protected IResource fResource = null;
+
+ public NoRegionContentAssistProcessor() {
+ super();
+ fPartitionToProcessorMap = new HashMap();
+ fNameToProcessorMap = new HashMap();
+ initNameToProcessorMap();
+ initPartitionToProcessorMap();
+
+ }
+
+ /**
+ * Figures out what the correct ICompletionProposalProcessor is and
+ * computesCompletionProposals on that.
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer,
+ * int)
+ */
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) {
+ IContentAssistProcessor p = null;
+ ICompletionProposal[] results = EMPTY_PROPOSAL_SET;
+
+ p = guessContentAssistProcessor(viewer, documentOffset);
+ if (p != null)
+ results = p.computeCompletionProposals(viewer, documentOffset);
+
+ return (results != null) ? results : EMPTY_PROPOSAL_SET;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer,
+ * int)
+ */
+ public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
+ // get context info from processor that we end up using...
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
+ */
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ return completionProposalAutoActivationCharacters;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
+ */
+ public char[] getContextInformationAutoActivationCharacters() {
+ return contextInformationAutoActivationCharacters;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
+ */
+ public IContextInformationValidator getContextInformationValidator() {
+ // return the validator for the content assist processor that we
+ // used...
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
+ */
+ public String getErrorMessage() {
+ return fErrorMessage;
+ }
+
+ /**
+ * Gives you the document partition type (String) for the given
+ * StructuredTextViewer and documentPosition.
+ *
+ * @param viewer
+ * @param documentPosition
+ * @return String
+ */
+ protected String getPartitionType(StructuredTextViewer viewer, int documentPosition) {
+ IDocument document = viewer.getDocument();
+ String partitionType = null;
+ ITypedRegion partition = null;
+ try {
+ partition = document.getPartition(documentPosition);
+ partitionType = partition.getType();
+ } catch (BadLocationException e) {
+ partitionType = null;
+ }
+ return partitionType;
+ }
+
+ /**
+ * Guesses a ContentAssistProcessor based on the TextViewer and
+ * documentOffset.
+ *
+ * @param viewer
+ * @param documentOffset
+ * @return
+ */
+ protected IContentAssistProcessor guessContentAssistProcessor(ITextViewer viewer, int documentOffset) {
+ // mapping logic here...
+ // look @ previous region
+ // look @ previous doc partition type
+ // look @ page language
+ IContentAssistProcessor p = null;
+ IStructuredDocumentRegion sdRegion = ContentAssistUtils.getStructuredDocumentRegion((StructuredTextViewer) viewer, documentOffset);
+ if (sdRegion != null) {
+ String currentRegionType = sdRegion.getType();
+ //System.out.println("current region type is >> " +
+ // currentRegionType);
+ if (currentRegionType == XMLRegionContext.UNDEFINED) {
+ IStructuredDocumentRegion sdPrev = sdRegion.getPrevious();
+ if (sdPrev != null) {
+ String prevRegionType = sdPrev.getType();
+ //System.out.println("previous region type is >> " +
+ // prevRegionType);
+ }
+ }
+ }
+ // working w/ viewer & document partition
+ if (p == null && viewer.getDocument().getLength() > 0) {
+ String prevPartitionType = getPartitionType((StructuredTextViewer) viewer, documentOffset - 1);
+ //System.out.println("previous partition type is > " +
+ // prevPartitionType);
+ p = (IContentAssistProcessor) fPartitionToProcessorMap.get(prevPartitionType);
+ }
+ return p;
+ }
+
+ /**
+ * Necessary for certain content assist processors (such as
+ * JSPJavaContentAssistProcessor). This gets set in
+ * StructuredTextViewerConfiguration.
+ *
+ */
+ public void initialize(IResource resource) {
+ fResource = resource;
+ setResourceOnProcessors(resource);
+ }
+
+ /**
+ * Inits map for extra ContentAssistProcessors (useBean, get/setProperty)
+ */
+ protected void initNameToProcessorMap() {
+ }
+
+ /**
+ * Adds all relevent ContentAssistProcessors to the partition to processor
+ * map (just XML here)
+ */
+ protected void initPartitionToProcessorMap() {
+ XMLContentAssistProcessor xmlProcessor = new XMLContentAssistProcessor();
+ fPartitionToProcessorMap.put(StructuredTextPartitionerForXML.ST_DEFAULT_XML, xmlProcessor);
+ }
+
+ public void release() {
+ releasePartitionToProcessorMap();
+ releaseNameToProcessorMap();
+ }
+
+ protected void releaseMap(HashMap map) {
+ if (map != null && !map.isEmpty()) {
+ Iterator it = map.keySet().iterator();
+ Object key = null;
+ while (it.hasNext()) {
+ key = it.next();
+ if (map.get(key) instanceof IReleasable)
+ ((IReleasable) map.get(key)).release();
+ }
+ map.clear();
+ map = null;
+ }
+ }
+
+ protected void releaseNameToProcessorMap() {
+ releaseMap(fNameToProcessorMap);
+ }
+
+ protected void releasePartitionToProcessorMap() {
+ releaseMap(fPartitionToProcessorMap);
+ }
+
+ private void setResourceOnMap(IResource resource, HashMap map) {
+ if (!map.isEmpty()) {
+ Iterator keys = map.keySet().iterator();
+ Object o = null;
+ while (keys.hasNext()) {
+ o = fPartitionToProcessorMap.get(keys.next());
+ if (o instanceof IResourceDependentProcessor)
+ ((IResourceDependentProcessor) o).initialize(resource);
+ }
+ }
+ }
+
+ /**
+ * @param resource
+ */
+ private void setResourceOnProcessors(IResource resource) {
+ setResourceOnMap(resource, fPartitionToProcessorMap);
+ setResourceOnMap(resource, fNameToProcessorMap);
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/NonValidatingModelQueryAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/NonValidatingModelQueryAction.java
new file mode 100644
index 0000000000..1bdfb81983
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/NonValidatingModelQueryAction.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+
+
+import org.eclipse.wst.common.contentmodel.CMNode;
+
+public class NonValidatingModelQueryAction implements org.eclipse.wst.common.contentmodel.modelquery.ModelQueryAction {
+
+ protected CMNode cmnode = null;
+ protected int endIndex = 0;
+ protected int kind = INSERT;
+ protected int startIndex = 0;
+ protected Object userData = null;
+
+ /**
+ * NonValidatingModelQueryAction constructor comment.
+ */
+ protected NonValidatingModelQueryAction() {
+ super();
+ }
+
+ /**
+ * NonValidatingModelQueryAction constructor comment.
+ */
+ public NonValidatingModelQueryAction(CMNode newChild, int newKind, int newStart, int newEnd, Object newUserData) {
+ super();
+ cmnode = newChild;
+ kind = newKind;
+ startIndex = newStart;
+ endIndex = newEnd;
+ userData = newUserData;
+ }
+
+ /**
+ * getCMNode method comment.
+ */
+ public org.eclipse.wst.common.contentmodel.CMNode getCMNode() {
+ return cmnode;
+ }
+
+ /**
+ *
+ * @return int
+ */
+ public int getEndIndex() {
+ return endIndex;
+ }
+
+ /**
+ *
+ * @return int
+ */
+ public int getKind() {
+ return kind;
+ }
+
+ /**
+ * getParent method comment.
+ */
+ public org.w3c.dom.Node getParent() {
+ return null;
+ }
+
+ /**
+ *
+ * @return int
+ */
+ public int getStartIndex() {
+ return startIndex;
+ }
+
+ /**
+ * getUserData method comment.
+ */
+ public Object getUserData() {
+ return null;
+ }
+
+ /**
+ * performAction method comment.
+ */
+ public void performAction() {
+ }
+
+ /**
+ * setCMNode method comment.
+ */
+ protected void setCMNode(org.eclipse.wst.common.contentmodel.CMNode newNode) {
+ cmnode = newNode;
+ }
+
+ /**
+ *
+ * @param newEndIndex
+ * int
+ */
+ protected void setEndIndex(int newEndIndex) {
+ endIndex = newEndIndex;
+ }
+
+ /**
+ *
+ * @param newKind
+ * int
+ */
+ protected void setKind(int newKind) {
+ kind = newKind;
+ }
+
+ /**
+ *
+ * @param newStartIndex
+ * int
+ */
+ protected void setStartIndex(int newStartIndex) {
+ startIndex = newStartIndex;
+ }
+
+ /**
+ * setUserData method comment.
+ */
+ public void setUserData(Object object) {
+ }
+
+ /**
+ *
+ * @return java.lang.String
+ */
+ public String toString() {
+ String actionName = null;
+ switch (kind) {
+ case INSERT :
+ actionName = "INSERT";//$NON-NLS-1$
+ break;
+ case REMOVE :
+ actionName = "REMOVE";//$NON-NLS-1$
+ break;
+ case REPLACE :
+ actionName = "REPLACE";//$NON-NLS-1$
+ break;
+ default :
+ actionName = "UNKNOWN ACTION ";//$NON-NLS-1$
+ }
+ String nodeName = (cmnode != null) ? getCMNode().getNodeName() : "(unknown)";//$NON-NLS-1$
+ return actionName + "=" + nodeName + "(" + startIndex + "..." + endIndex + ")";//$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ProposalComparator.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ProposalComparator.java
new file mode 100644
index 0000000000..3a4bf4d69a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/ProposalComparator.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+
+
+import java.util.Comparator;
+
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.wst.sse.ui.contentassist.IRelevanceCompletionProposal;
+
+
+public class ProposalComparator implements Comparator {
+
+
+ public int compare(Object o1, Object o2) {
+ int relevance = 0;
+ if (o1 instanceof IRelevanceCompletionProposal && o2 instanceof IRelevanceCompletionProposal) {
+ // sort based on relevance
+ IRelevanceCompletionProposal cp1 = (IRelevanceCompletionProposal) o1;
+ IRelevanceCompletionProposal cp2 = (IRelevanceCompletionProposal) o2;
+
+ relevance = cp2.getRelevance() - cp1.getRelevance();
+
+ // if same relevance, secondary sort (lexigraphically)
+ if (relevance == 0 && o1 instanceof ICompletionProposal && o2 instanceof ICompletionProposal) {
+ String displayString1 = ((ICompletionProposal) o1).getDisplayString();
+ String displayString2 = ((ICompletionProposal) o2).getDisplayString();
+ if (displayString1 != null && displayString2 != null)
+ //relevance = displayString1.compareTo(displayString2);
+ // // this didn't mix caps w/ lowercase
+ relevance = java.text.Collator.getInstance().compare(displayString1, displayString2);
+ }
+ }
+ // otherwise if it's not ISEDRelevanceCompletionProposal, don't sort
+ return relevance;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/SimpleCMElementDeclaration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/SimpleCMElementDeclaration.java
new file mode 100644
index 0000000000..42dce88174
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/SimpleCMElementDeclaration.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+
+
+public class SimpleCMElementDeclaration implements org.eclipse.wst.common.contentmodel.CMElementDeclaration {
+
+ String fNodeName;
+
+ /**
+ * SimpleCMELementDeclaration constructor comment.
+ */
+ public SimpleCMElementDeclaration() {
+ super();
+ }
+
+ public SimpleCMElementDeclaration(String nodeName) {
+ super();
+ setNodeName(nodeName);
+ }
+
+ /**
+ * getAttributes method
+ *
+ * @return CMNamedNodeMap
+ *
+ * Returns CMNamedNodeMap of AttributeDeclaration
+ */
+ public org.eclipse.wst.common.contentmodel.CMNamedNodeMap getAttributes() {
+ return null;
+ }
+
+ /**
+ * getCMContent method
+ *
+ * @return CMContent
+ *
+ * Returns the root node of this element's content model. This can be an
+ * CMElementDeclaration or a CMGroup
+ */
+ public org.eclipse.wst.common.contentmodel.CMContent getContent() {
+ return null;
+ }
+
+ /**
+ * getContentType method
+ *
+ * @return int
+ *
+ * Returns one of : ANY, EMPTY, ELEMENT, MIXED, PCDATA, CDATA.
+ */
+ public int getContentType() {
+ return 0;
+ }
+
+ /**
+ * getDataType method
+ *
+ * @return java.lang.String
+ */
+ public org.eclipse.wst.common.contentmodel.CMDataType getDataType() {
+ return null;
+ }
+
+ /**
+ * getElementName method
+ *
+ * @return java.lang.String
+ */
+ public String getElementName() {
+ return null;
+ }
+
+ /**
+ * getLocalElements method
+ *
+ * @return CMNamedNodeMap
+ *
+ * Returns a list of locally defined elements.
+ */
+ public org.eclipse.wst.common.contentmodel.CMNamedNodeMap getLocalElements() {
+ return null;
+ }
+
+ /**
+ * getMaxOccur method
+ *
+ * @return int
+ *
+ * If -1, it's UNBOUNDED.
+ */
+ public int getMaxOccur() {
+ return 0;
+ }
+
+ /**
+ * getMinOccur method
+ *
+ * @return int
+ *
+ * If 0, it's OPTIONAL. If 1, it's REQUIRED.
+ */
+ public int getMinOccur() {
+ return 0;
+ }
+
+ /**
+ *
+ * @return java.lang.String
+ */
+ public java.lang.String getNodeName() {
+ return fNodeName;
+ }
+
+ /**
+ * getNodeType method
+ *
+ * @return int
+ *
+ * Returns one of :
+ *
+ */
+ public int getNodeType() {
+ return 0;
+ }
+
+ /**
+ * getProperty method
+ *
+ * @return java.lang.Object
+ *
+ * Returns the object property desciped by the propertyName
+ *
+ */
+ public Object getProperty(String propertyName) {
+ return null;
+ }
+
+ /**
+ *
+ * @param newNodeName
+ * java.lang.String
+ */
+ public void setNodeName(java.lang.String newNodeName) {
+ fNodeName = newNodeName;
+ }
+
+ /**
+ * supports method
+ *
+ * @return boolean
+ *
+ * Returns true if the CMNode supports a specified property
+ *
+ */
+ public boolean supports(String propertyName) {
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/SourceEditorImageHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/SourceEditorImageHelper.java
new file mode 100644
index 0000000000..637a785cc8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/SourceEditorImageHelper.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.xml.ui.XMLEditorPlugin;
+
+
+/**
+ * @deprecated use internal XMLEditorPluginImageHelper or external
+ * SharedXMLEditorPluginImageHelper instead
+ */
+public class SourceEditorImageHelper {
+
+ public SourceEditorImageHelper() {
+ super();
+ }
+
+ public Image createImage(String resource) {
+ ImageDescriptor desc = AbstractUIPlugin.imageDescriptorFromPlugin(XMLEditorPlugin.ID, resource);
+ Image image = desc.createImage();
+ JFaceResources.getImageRegistry().put(resource, image);
+ return image;
+ }
+
+ public Image getImage(String resource) {
+ Image image = JFaceResources.getImageRegistry().get(resource);
+ if (image == null) {
+ image = createImage(resource);
+ }
+ return image;
+ }
+
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentAssistProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentAssistProcessor.java
new file mode 100644
index 0000000000..0a4b8dc155
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentAssistProcessor.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.ui.EditorPlugin;
+import org.eclipse.wst.sse.ui.preferences.CommonEditorPreferenceNames;
+import org.eclipse.wst.sse.ui.preferences.PreferenceKeyGenerator;
+
+
+public class XMLContentAssistProcessor extends AbstractContentAssistProcessor implements IPropertyChangeListener {
+
+ protected IPreferenceStore fPreferenceStore = null;
+ protected IResource fResource = null;
+ protected AbstractTemplateCompletionProcessor fTemplateProcessor = null;
+
+ public XMLContentAssistProcessor() {
+ super();
+ }
+
+ protected IPreferenceStore getPreferenceStore() {
+ if (fPreferenceStore == null)
+ fPreferenceStore = EditorPlugin.getDefault().getPreferenceStore();
+ //fPreferenceStore =
+ // CommonPreferencesPlugin.getDefault().getPreferenceStore(ContentType.ContentTypeID_XML);
+
+ return fPreferenceStore;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.xml.ui.contentassist.AbstractContentAssistProcessor#getTemplateCompletionProcessor()
+ */
+ protected AbstractTemplateCompletionProcessor getTemplateCompletionProcessor() {
+ if (fTemplateProcessor == null) {
+ fTemplateProcessor = new XMLTemplateCompletionProcessor();
+ }
+ return fTemplateProcessor;
+ }
+
+ protected void init() {
+ getPreferenceStore().addPropertyChangeListener(this);
+ reinit();
+ }
+
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+
+ if (property.compareTo(CommonEditorPreferenceNames.AUTO_PROPOSE) == 0 || property.compareTo(CommonEditorPreferenceNames.AUTO_PROPOSE_CODE) == 0) {
+ reinit();
+ }
+ }
+
+ protected void reinit() {
+ String key = PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.AUTO_PROPOSE, IContentTypeIdentifier.ContentTypeID_SSEXML);
+ boolean doAuto = getPreferenceStore().getBoolean(key);
+ if (doAuto) {
+ key = PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.AUTO_PROPOSE_CODE, IContentTypeIdentifier.ContentTypeID_SSEXML);
+ completionProposalAutoActivationCharacters = getPreferenceStore().getString(key).toCharArray();
+ } else {
+ completionProposalAutoActivationCharacters = null;
+ }
+ }
+
+ public void release() {
+ super.release();
+ getPreferenceStore().removePropertyChangeListener(this);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentAssistUtilities.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentAssistUtilities.java
new file mode 100644
index 0000000000..ad52a23c68
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentAssistUtilities.java
@@ -0,0 +1,473 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.util.ScriptLanguageKeys;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+/**
+ * @author pavery
+ */
+public class XMLContentAssistUtilities extends ContentAssistUtils {
+ public static final String CONTENT = "Content"; //$NON-NLS-1$
+ public static final String CONTENT_SCRIPT_TYPE = "Content-Script-Type"; //$NON-NLS-1$
+ public static final String HEAD = "HEAD"; //$NON-NLS-1$
+ public static final String HTML = "HTML"; //$NON-NLS-1$
+ public static final String HTTP_EQUIV = "HTTP-EQUIV"; //$NON-NLS-1$
+ public static final String META = "META"; //$NON-NLS-1$
+
+ /**
+ * A convenience method for getting the closing proposal given the
+ * contents (IndexedRegion) of a tag that is started, but possibly not
+ * ended
+ *
+ * @param viewer
+ * the text viewer
+ * @param documentPosition
+ * the cursor position in the viewer
+ * @param indexedNode
+ * the contents of the tag that is started but possibly not
+ * ended
+ * @param parentTagName
+ * the tag on which you are checkin for an ending tag
+ * @param imagePath
+ * content assist image path in realation to com.ibm.sed.
+ * structured. contentassist. xmlSourceEditorImageHelper
+ * @return ICompletionProposal
+ */
+ public static ICompletionProposal computeJSPEndTagProposal(ITextViewer viewer, int documentPosition, IndexedRegion indexedNode, String parentTagName, String imagePath) {
+ ICompletionProposal p = null;
+
+ // check if tag is closed
+ boolean hasEndTag = true;
+ boolean isJSPTag = false;
+ XMLNode xnode = null;
+ String tagName = ""; //$NON-NLS-1$
+ if (indexedNode instanceof XMLNode) {
+ xnode = ((XMLNode) indexedNode);
+ // it's ended already...
+ if (xnode.getEndStructuredDocumentRegion() != null)
+ return null;
+ XMLNode openNode = null;
+ if (!xnode.getNodeName().equalsIgnoreCase(parentTagName))
+ openNode = (XMLNode) xnode.getParentNode();
+ if (openNode != null) {
+ if (openNode instanceof XMLElement) {
+ isJSPTag = ((XMLElement) openNode).isJSPTag();
+ }
+ tagName = openNode.getNodeName();
+ hasEndTag = (openNode.getEndStructuredDocumentRegion() != null);
+ }
+ }
+
+ // it's closed, don't add close tag proposal
+ if (!hasEndTag && !isJSPTag) {
+
+ // create appropriate close tag text
+ String proposedText = proposedText = "</" + tagName; // ResourceHandler
+ // wants text
+ // w/out
+ // ending '>'
+ // //$NON-NLS-1$
+ String viewerText = viewer.getTextWidget().getText();
+ if (viewerText.length() >= documentPosition && viewerText.length() >= 2 && documentPosition >= 2) {
+ String last2chars = viewerText.substring(documentPosition - 2, documentPosition);
+ if (last2chars.endsWith("</")) //$NON-NLS-1$
+ proposedText = tagName;
+ else if (last2chars.endsWith("<")) //$NON-NLS-1$
+ proposedText = "/" + tagName; //$NON-NLS-1$
+ }
+
+ // create proposal
+ p = new CustomCompletionProposal(proposedText + ">", //$NON-NLS-1$
+ documentPosition, 0, proposedText.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(imagePath), //$NON-NLS-1$
+ ResourceHandler.getString("15concat", (new Object[]{proposedText})), //$NON-NLS-1$ = "End with '{0}>'"
+ null, null, XMLRelevanceConstants.R_END_TAG);
+ } else if (!hasEndTag && isJSPTag) {
+
+ // create appropriate close tag text
+ String proposedText = proposedText = "%"; // ResourceHandler wants
+ // text w/out ending '>'
+ // //$NON-NLS-1$
+ String viewerText = viewer.getTextWidget().getText();
+
+ // TODO (pa) make it smarter to add "%>" or just ">" if % is
+ // already there...
+ if (viewerText.length() >= documentPosition && viewerText.length() >= 2) {
+ String last2chars = viewerText.substring(documentPosition - 2, documentPosition);
+ String lastchar = viewerText.substring(documentPosition - 1, documentPosition);
+ if (lastchar.equals("%")) //$NON-NLS-1$
+ {
+ if (last2chars.endsWith("<%")) //$NON-NLS-1$
+ proposedText = "%"; //$NON-NLS-1$
+ else
+ proposedText = ""; //$NON-NLS-1$
+ }
+ }
+
+ // create proposal
+ p = new CustomCompletionProposal(proposedText + ">", //$NON-NLS-1$
+ documentPosition, 0, proposedText.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(imagePath), //$NON-NLS-1$
+ ResourceHandler.getString("15concat", (new Object[]{proposedText})), //$NON-NLS-1$ = "End with '{0}>'"
+ null, null, XMLRelevanceConstants.R_END_TAG);
+ }
+
+ return p;
+ }
+
+
+ /**
+ * A convenience method for getting the closing proposal given the
+ * contents (IndexedRegion) of a tag that is started, but possibly not
+ * ended
+ *
+ * @param viewer
+ * the text viewer
+ * @param documentPosition
+ * the cursor position in the viewer
+ * @param indexedNode
+ * the contents of the tag that is started but possibly not
+ * ended
+ * @param parentTagName
+ * the tag on which you are checkin for an ending tag
+ * @param imagePath
+ * content assist image path in realation to com.ibm.sed.
+ * structured. contentassist. xmlSourceEditorImageHelper
+ * @return ICompletionProposal
+ */
+ public static ICompletionProposal computeXMLEndTagProposal(ITextViewer viewer, int documentPosition, IndexedRegion indexedNode, String parentTagName, String imagePath) {
+ ICompletionProposal p = null;
+
+ // check if tag is closed
+ boolean hasEndTag = true;
+ XMLNode xnode = null;
+ String tagName = ""; //$NON-NLS-1$
+ if (indexedNode instanceof XMLNode) {
+ xnode = ((XMLNode) indexedNode);
+ // it's ended already...
+ if (xnode.getEndStructuredDocumentRegion() != null)
+ return null;
+ XMLNode styleNode = null;
+ if (!xnode.getNodeName().equalsIgnoreCase(parentTagName))
+ styleNode = (XMLNode) xnode.getParentNode();
+ if (styleNode != null) {
+ tagName = styleNode.getNodeName();
+ hasEndTag = (styleNode.getEndStructuredDocumentRegion() != null);
+ }
+ }
+
+ // it's closed, don't add close tag proposal
+ if (!hasEndTag) {
+
+ // create appropriate close tag text
+ String proposedText = proposedText = "</" + tagName; // ResourceHandler
+ // wants text
+ // w/out
+ // ending '>'
+ // //$NON-NLS-1$
+ String viewerText = viewer.getTextWidget().getText();
+ if (viewerText.length() >= documentPosition && viewerText.length() >= 2 && documentPosition >= 2) {
+ String last2chars = viewerText.substring(documentPosition - 2, documentPosition);
+ if (last2chars.endsWith("</")) //$NON-NLS-1$
+ proposedText = tagName;
+ else if (last2chars.endsWith("<")) //$NON-NLS-1$
+ proposedText = "/" + tagName; //$NON-NLS-1$
+ }
+
+ // create proposal
+ p = new CustomCompletionProposal(proposedText + ">", //$NON-NLS-1$
+ documentPosition, 0, proposedText.length() + 1, XMLEditorPluginImageHelper.getInstance().getImage(imagePath), //$NON-NLS-1$
+ ResourceHandler.getString("15concat", (new Object[]{proposedText})), //$NON-NLS-1$ = "End with '{0}>'"
+ null, null, XMLRelevanceConstants.R_END_TAG);
+ }
+ return p;
+ }
+
+ private static String getMetaScriptType(Document doc) {
+ // Can not just do a Document.getElementsByTagName(String) as this
+ // needs
+ // to be relatively fast.
+ List metas = new ArrayList();
+ // check for META tags under the Document
+ Node html = null;
+ Node head = null;
+ Node child = null;
+ //----------------------------------------------------------------------
+ // (pa) 20021217
+ // cmvc defect 235554
+ // performance enhancement: using child.getNextSibling() rather than
+ // nodeList(item) for O(n) vs. O(n*n)
+ //----------------------------------------------------------------------
+
+ for (child = doc.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+ if (child.getNodeName().equalsIgnoreCase(META))
+ metas.add(child);
+ else if (child.getNodeName().equalsIgnoreCase(HTML))
+ html = child;
+ }
+ // NodeList children = doc.getChildNodes();
+ // for(int i = 0; i < children.getLength(); i++) {
+ // child = children.item(i);
+ // if(child.getNodeType() != Node.ELEMENT_NODE)
+ // continue;
+ // if(child.getNodeName().equalsIgnoreCase(META))
+ // metas.add(child);
+ // else if(child.getNodeName().equalsIgnoreCase(HTML))
+ // html = child;
+ // }
+
+ // check for META tags under HEAD
+ if (html != null) {
+ for (child = html.getFirstChild(); child != null && head == null; child = child.getNextSibling()) {
+ if (child.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+ if (child.getNodeName().equalsIgnoreCase(HEAD))
+ head = child;
+ }
+ // children = html.getChildNodes();
+ // for(int i = 0; i < children.getLength() && head == null; i++) {
+ // child = children.item(i);
+ // if(child.getNodeType() != Node.ELEMENT_NODE)
+ // continue;
+ // if(child.getNodeName().equalsIgnoreCase(HEAD))
+ // head = child;
+ // }
+ }
+
+ if (head != null) {
+ for (head.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+ if (child.getNodeName().equalsIgnoreCase(META))
+ metas.add(child);
+ }
+ // children = head.getChildNodes();
+ // for(int i = 0 ; i < children.getLength(); i++) {
+ // child = children.item(i);
+ // if(child.getNodeType() != Node.ELEMENT_NODE)
+ // continue;
+ // if(child.getNodeName().equalsIgnoreCase(META))
+ // metas.add(child);
+ // }
+ }
+
+ return getMetaScriptType(metas);
+ }
+
+ private static String getMetaScriptType(List metaNodeList) {
+ Node meta = null;
+ NamedNodeMap attributes = null;
+ boolean httpEquiv = false;
+ String contentScriptType = null;
+
+ for (int i = metaNodeList.size() - 1; i >= 0; i--) {
+ meta = (Node) metaNodeList.get(i);
+ attributes = meta.getAttributes();
+ httpEquiv = false;
+ contentScriptType = null;
+ for (int j = 0; j < attributes.getLength(); j++) {
+ if (attributes.item(j).getNodeName().equalsIgnoreCase(HTTP_EQUIV)) {
+ httpEquiv = attributes.item(j).getNodeValue().equalsIgnoreCase(CONTENT_SCRIPT_TYPE);
+ } else if (attributes.item(j).getNodeName().equalsIgnoreCase(CONTENT)) {
+ contentScriptType = attributes.item(j).getNodeValue();
+ }
+ }
+ if (httpEquiv && contentScriptType != null)
+ return contentScriptType;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the scripting language the scriptNode is in Currently returns
+ * javascript unless some unknown type or language is specified. Then the
+ * unknown type/language is returned
+ *
+ * @param scriptNode
+ * @return
+ */
+ public static String getScriptLanguage(Node scriptNode) {
+ Node attr = null;
+
+ boolean specified = false;
+ // try to find a scripting adapter for 'type'
+ if ((scriptNode == null) || (scriptNode.getAttributes() == null))
+ return null;
+
+ attr = scriptNode.getAttributes().getNamedItem("type");//$NON-NLS-1$
+ if (attr != null) {
+ specified = true;
+ String type = attr.getNodeValue();
+ return lookupScriptType(type);
+ }
+ // now try to find a scripting adapter for 'language' (deprecated by
+ // HTML specifications)
+ attr = scriptNode.getAttributes().getNamedItem("language");//$NON-NLS-1$
+ if (attr != null) {
+ specified = true;
+ String language = attr.getNodeValue();
+ return lookupScriptLanguage(language);
+ }
+ // check if one is specified by a META tag at the root level or inside
+ // of HEAD
+ String type = null;
+ if (!specified)
+ type = getMetaScriptType(scriptNode.getOwnerDocument());
+ if (type != null) {
+ specified = true;
+ return lookupScriptType(type);
+ }
+ // return default
+ if (!specified)
+ return ScriptLanguageKeys.JAVASCRIPT;
+ return null;
+ }
+
+ /**
+ * Tells you if the flatnode is the %> delimiter
+ *
+ * @param fn
+ * @return boolean
+ */
+ public static boolean isJSPCloseDelimiter(IStructuredDocumentRegion fn) {
+ if (fn == null)
+ return false;
+ return isJSPCloseDelimiter(fn.getType());
+ }
+
+ public static boolean isJSPCloseDelimiter(String type) {
+ if (type == null)
+ return false;
+ return (type == XMLJSPRegionContexts.JSP_CLOSE || type == XMLRegionContext.XML_TAG_CLOSE);
+ }
+
+ /**
+ * Tells you if the flatnode is the JSP region <%%>, <%=%>, <%!%>
+ *
+ * @param fn
+ * @return boolean
+ */
+ public static boolean isJSPDelimiter(IStructuredDocumentRegion fn) {
+ boolean isDelimiter = false;
+ String type = fn.getType();
+ if (type != null) {
+ isDelimiter = isJSPDelimiter(type);
+ }
+ return isDelimiter;
+ }
+
+ public static boolean isJSPDelimiter(String type) {
+ if (type == null)
+ return false;
+ return (isJSPOpenDelimiter(type) || isJSPCloseDelimiter(type));
+ }
+
+ /**
+ * Tells you if the flatnode is <%, <%=, or <%!
+ *
+ * @param fn
+ * @return boolean
+ */
+ public static boolean isJSPOpenDelimiter(IStructuredDocumentRegion fn) {
+ if (fn == null)
+ return false;
+ return isJSPOpenDelimiter(fn.getType());
+ }
+
+ public static boolean isJSPOpenDelimiter(String type) {
+ if (type == null)
+ return false;
+ return (type == XMLJSPRegionContexts.JSP_SCRIPTLET_OPEN || type == XMLJSPRegionContexts.JSP_DECLARATION_OPEN || type == XMLJSPRegionContexts.JSP_EXPRESSION_OPEN);
+ }
+
+ /**
+ * Tells you if the flatnode is the <jsp:scriptlet>, <jsp:expression>, or
+ * <jsp:declaration>tag
+ *
+ * @param fn
+ * @return boolean
+ */
+ public static boolean isXMLJSPDelimiter(IStructuredDocumentRegion fn) {
+ boolean isDelimiter = false;
+ if (fn != null && fn instanceof ITextRegionContainer) {
+ Object[] regions = ((ITextRegionContainer) fn).getRegions().toArray();
+ ITextRegion temp = null;
+ String regionText = ""; //$NON-NLS-1$
+ for (int i = 0; i < regions.length; i++) {
+ temp = (ITextRegion) regions[i];
+ if (temp.getType() == XMLRegionContext.XML_TAG_NAME) {
+ regionText = fn.getText(temp);
+ if (regionText.equalsIgnoreCase("jsp:scriptlet") || regionText.equalsIgnoreCase("jsp:expression") || regionText.equalsIgnoreCase("jsp:declaration")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ isDelimiter = true;
+ }
+ }
+ }
+ return isDelimiter;
+ }
+
+ /**
+ * Returns "javascript" if language attribute is some form of javascript,
+ * "java" if language attribute is some form of java. Otherwise, just
+ * returns type.
+ *
+ * @param language
+ * @return
+ */
+ public static String lookupScriptLanguage(String language) {
+ for (int i = 0; i < ScriptLanguageKeys.JAVASCRIPT_LANGUAGE_KEYS.length; i++) {
+ if (ScriptLanguageKeys.JAVASCRIPT_LANGUAGE_KEYS[i].equalsIgnoreCase(language))
+ return ScriptLanguageKeys.JAVASCRIPT;
+ }
+ for (int i = 0; i < ScriptLanguageKeys.JAVA_LANGUAGE_KEYS.length; i++) {
+ if (ScriptLanguageKeys.JAVA_LANGUAGE_KEYS[i].equalsIgnoreCase(language))
+ return ScriptLanguageKeys.JAVA;
+ }
+ return language;
+ }
+
+ /**
+ * Returns "javascript" if type (used in <script type="xxx"> is actually
+ * javascript type. Otherwise, just returns type
+ *
+ * @param type
+ * @return
+ */
+ public static String lookupScriptType(String type) {
+ for (int i = 0; i < ScriptLanguageKeys.JAVASCRIPT_MIME_TYPE_KEYS.length; i++)
+ if (ScriptLanguageKeys.JAVASCRIPT_MIME_TYPE_KEYS[i].equalsIgnoreCase(type))
+ return ScriptLanguageKeys.JAVASCRIPT;
+ return type;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentModelGenerator.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentModelGenerator.java
new file mode 100644
index 0000000000..22cdb40a40
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLContentModelGenerator.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+
+
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMDataType;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
+import org.w3c.dom.Node;
+
+
+public class XMLContentModelGenerator extends AbstractContentModelGenerator {
+
+ /**
+ * XMLContentModelGenerator constructor comment.
+ */
+ public XMLContentModelGenerator() {
+ super();
+ }
+
+ public void generateAttribute(CMAttributeDeclaration attrDecl, StringBuffer buffer) {
+ if (attrDecl == null || buffer == null)
+ return;
+ int usage = attrDecl.getUsage();
+ if (usage == CMAttributeDeclaration.REQUIRED) {
+ buffer.append(" "); //$NON-NLS-1$
+ generateRequiredAttribute(null, attrDecl, buffer); //todo pass
+ // ownerNode as
+ // 1st param
+ }
+ return;
+ }
+
+ protected void generateEndTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer) {
+ if (elementDecl == null)
+ return;
+ if (elementDecl.getContentType() != CMElementDeclaration.EMPTY)
+ buffer.append("</" + tagName + ">");//$NON-NLS-2$//$NON-NLS-1$
+ return;
+ }
+
+ public void generateRequiredAttribute(Node ownerNode, CMAttributeDeclaration attrDecl, StringBuffer buffer) {
+ if (attrDecl == null || buffer == null)
+ return;
+
+ // attribute name
+ String attributeName = getRequiredName(ownerNode, attrDecl);
+ CMDataType attrType = attrDecl.getAttrType();
+ // = sign
+ buffer.append(attributeName + "=\""); //$NON-NLS-1$
+ // attribute value
+ if (attrType != null) {
+ // insert any value that is implied
+ if (attrType.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE && attrType.getImpliedValue() != null) {
+ buffer.append(attrType.getImpliedValue());
+ }
+ // otherwise, if an enumerated list of values exists, use the
+ // first value
+ else if (attrType.getEnumeratedValues() != null && attrType.getEnumeratedValues().length > 0) {
+ buffer.append(attrType.getEnumeratedValues()[0]);
+ }
+ }
+ buffer.append("\""); //$NON-NLS-1$
+ return;
+ }
+
+ protected void generateStartTag(String tagName, Node parentNode, CMElementDeclaration elementDecl, StringBuffer buffer) {
+ if (elementDecl == null || buffer == null)
+ return;
+ buffer.append("<" + tagName);//$NON-NLS-1$
+ generateAttributes(elementDecl, buffer);
+ buffer.append(getStartTagClose(parentNode, elementDecl));
+ return;
+ }
+
+ public int getMinimalStartTagLength(Node node, CMElementDeclaration elementDecl) {
+ if (elementDecl == null)
+ return 0;
+ if (requiresAttributes(elementDecl)) {
+ return getRequiredName(node, elementDecl).length() + 2; // < +
+ // name +
+ // space
+ } else {
+ return 1 + getRequiredName(node, elementDecl).length() + getStartTagClose(node, elementDecl).length(); // < +
+ // name
+ // +
+ // appropriate
+ // close
+ }
+ }
+
+ protected String getOtherClose(Node notATagNode) {
+ if (notATagNode instanceof XMLNode) {
+ IStructuredDocumentRegion node = ((XMLNode) notATagNode).getStartStructuredDocumentRegion();
+ if (node != null && node.getNumberOfRegions() > 1 && node.getRegions().get(0).getType() == XMLJSPRegionContexts.JSP_DIRECTIVE_OPEN) {
+ return "%>"; //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
+
+ public String getStartTagClose(Node parentNode, CMElementDeclaration elementDecl) {
+ String other = getOtherClose(parentNode);
+ if (other != null)
+ return other;
+ if (elementDecl == null)
+ return ">";//$NON-NLS-1$
+ if (elementDecl.getContentType() == CMElementDeclaration.EMPTY)
+ return "/>"; //$NON-NLS-1$
+ return ">"; //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLRelevanceConstants.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLRelevanceConstants.java
new file mode 100644
index 0000000000..0ac5df3932
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLRelevanceConstants.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import org.eclipse.wst.sse.ui.internal.contentassist.IRelevanceConstants;
+
+
+
+/**
+ * some relevance constants for content assist higher relevance means it shows
+ * up higher on the list
+ */
+public interface XMLRelevanceConstants extends IRelevanceConstants {
+
+ int R_CDATA = 400;
+ int R_CLOSE_TAG = 1500;
+
+ int R_COMMENT = 100;
+
+ // moved this above macros
+ int R_DOCTYPE = 600;
+ int R_END_TAG = 1400;
+ int R_END_TAG_NAME = 1100;
+ int R_ENTITY = 1000;
+ int R_JSP = 500;
+
+ int R_JSP_ATTRIBUTE_VALUE = 700;
+
+ // (pa) make these the same relevance so proposals are same order for V501
+ int R_MACRO = 500;
+
+ // add this onto "required" attrs, elements, etc to bubble them up on
+ // sorting...
+ // CMVC 246618
+ int R_REQUIRED = 10;
+ int R_TAG_INSERTION = 500;
+ int R_TAG_NAME = 1200;
+ int R_XML_ATTRIBUTE_NAME = 900;
+ int R_XML_ATTRIBUTE_VALUE = 800;
+ int R_XML_DECLARATION = 1300;
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLTemplateCompletionProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLTemplateCompletionProcessor.java
new file mode 100644
index 0000000000..c6aea8e33b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/contentassist/XMLTemplateCompletionProcessor.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.contentassist;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.wst.xml.ui.XMLEditorPlugin;
+import org.eclipse.wst.xml.ui.templates.TemplateContextTypeXML;
+
+
+/**
+ * Completion processor for XML Templates
+ */
+public class XMLTemplateCompletionProcessor extends AbstractTemplateCompletionProcessor {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.xml.ui.contentassist.AbstractTemplateCompletionProcessor#getContextTypeId()
+ */
+ protected String getContextTypeId() {
+ // turn the context type id into content type specific
+ return TemplateContextTypeXML.generateContextTypeId(super.getContextTypeId());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.xml.ui.contentassist.AbstractTemplateCompletionProcessor#getTemplateContextRegistry()
+ */
+ protected ContextTypeRegistry getTemplateContextRegistry() {
+ return getXMLEditorPlugin().getTemplateContextRegistry();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.xml.ui.contentassist.AbstractTemplateCompletionProcessor#getTemplateStore()
+ */
+ protected TemplateStore getTemplateStore() {
+ return getXMLEditorPlugin().getTemplateStore();
+ }
+
+ /**
+ * Returns the XMLEditorPlugin
+ *
+ * @return XMLEditorPlugin
+ */
+ private XMLEditorPlugin getXMLEditorPlugin() {
+ return (XMLEditorPlugin) Platform.getPlugin(XMLEditorPlugin.ID);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditAttributeDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditAttributeDialog.java
new file mode 100644
index 0000000000..ed7a5f7b7f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditAttributeDialog.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.ui.util.XMLCommonUIContextIds;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+
+
+public class EditAttributeDialog extends Dialog implements ModifyListener {
+ protected Attr attribute;
+ protected String attributeName;
+ protected Text attributeNameField;
+ protected String attributeValue;
+ protected Text attributeValueField;
+ protected Label errorMessageLabel;
+ protected Button okButton;
+ protected Element ownerElement;
+
+ public EditAttributeDialog(Shell parentShell, Element ownerElement, Attr attribute) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ this.ownerElement = ownerElement;
+ this.attribute = attribute;
+ }
+
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.OK_ID) {
+ attributeName = getModelValue(attributeNameField.getText());
+ attributeValue = attributeValueField.getText();
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ attributeNameField.forceFocus();
+ attributeNameField.selectAll();
+ updateErrorMessage();
+ return control;
+ }
+
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogArea = (Composite) super.createDialogArea(parent);
+ WorkbenchHelp.setHelp(dialogArea, XMLCommonUIContextIds.XCUI_ATTRIBUTE_DIALOG);
+
+ Composite composite = new Composite(dialogArea, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginWidth = 0;
+ composite.setLayout(layout);
+
+ //
+ // Style convenience constants
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label attributeNameLabel = new Label(composite, SWT.NONE);
+ attributeNameLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_NAME_COLON")); //$NON-NLS-1$
+
+ attributeNameField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 300;
+ attributeNameField.setLayoutData(gd);
+ attributeNameField.setText(getDisplayValue(attribute != null ? attribute.getName() : "")); //$NON-NLS-1$
+ attributeNameField.addModifyListener(this);
+
+ Label attributeValueLabel = new Label(composite, SWT.NONE);
+ attributeValueLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_VALUE_COLON")); //$NON-NLS-1$
+
+ String value = attribute != null ? attribute.getValue() : ""; //$NON-NLS-1$
+ int style = SWT.SINGLE | SWT.BORDER;
+ if (value.indexOf("\n") != -1) { //$NON-NLS-1$
+ style = SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL;
+ }
+
+ attributeValueField = new Text(composite, style);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 300;
+ attributeValueField.setLayoutData(gd);
+ attributeValueField.setText(getDisplayValue(attribute != null ? attribute.getValue() : "")); //$NON-NLS-1$
+
+ // error message
+ errorMessageLabel = new Label(composite, SWT.WRAP);
+ errorMessageLabel.setText(ResourceHandler.getString("error_message_goes_here")); //$NON-NLS-1$
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 200;
+ gd.heightHint = Math.max(30, errorMessageLabel.computeSize(0, 0, false).y * 2);
+ gd.horizontalSpan = 2;
+ errorMessageLabel.setLayoutData(gd);
+ Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+ errorMessageLabel.setForeground(color);
+
+ return dialogArea;
+ }
+
+ public String getAttributeName() {
+ return attributeName;
+ }
+
+ public String getAttributeValue() {
+ return attributeValue;
+ }
+
+ protected String getDisplayValue(String string) {
+ return string != null ? string : ""; //$NON-NLS-1$
+ }
+
+ protected String getModelValue(String string) {
+ String result = null;
+ if (string != null && string.trim().length() > 0) {
+ result = string;
+ }
+ return result;
+ }
+
+ public void modifyText(ModifyEvent e) {
+ updateErrorMessage();
+ }
+
+ protected void updateErrorMessage() {
+ String errorMessage = null;
+ String name = attributeNameField.getText().trim();
+ if (name.length() > 0) {
+ Attr matchingAttribute = ownerElement.getAttributeNode(name);
+ if (matchingAttribute != null && matchingAttribute != attribute) {
+ errorMessage = XMLCommonResources.getInstance().getString("_ERROR_XML_ATTRIBUTE_ALREADY_EXISTS"); //$NON-NLS-1$
+ } else {
+ // TODO get checkName from Model
+ //errorMessage = ValidateHelper.checkXMLName(name);
+ }
+ } else {
+ errorMessage = ""; //$NON-NLS-1$
+ }
+
+ errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+ errorMessageLabel.getParent().layout();
+ okButton.setEnabled(errorMessage == null);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditDoctypeDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditDoctypeDialog.java
new file mode 100644
index 0000000000..6fd0ea01b4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditDoctypeDialog.java
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.ui.util.XMLCommonUIContextIds;
+import org.w3c.dom.DocumentType;
+
+
+
+public class EditDoctypeDialog extends Dialog {
+ protected boolean computeSystemId;
+ protected String[] doctypeData;
+ protected boolean errorChecking;
+ protected Label errorMessageLabel;
+ protected Button okButton;
+ protected Button publicIdBrowseButton;
+ protected Text publicIdField;
+ protected IPath resourceLocation;
+ protected Text rootElementNameField;
+ protected Button systemIdBrowseButton;
+ protected Text systemIdField;
+
+ public EditDoctypeDialog(Shell parentShell, DocumentType doctype) {
+ this(parentShell, doctype.getName(), doctype.getPublicId(), doctype.getSystemId());
+ }
+
+ public EditDoctypeDialog(Shell parentShell, String name, String publicId, String systemId) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ doctypeData = new String[3];
+ doctypeData[0] = name;
+ doctypeData[1] = publicId;
+ doctypeData[2] = systemId;
+ }
+
+ protected void buttonPressed(int buttonId) {
+ doctypeData[0] = getModelValue(rootElementNameField.getText());
+ doctypeData[1] = getModelValue(publicIdField.getText());
+ doctypeData[2] = getModelValue(systemIdField.getText());
+ super.buttonPressed(buttonId);
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ updateErrorMessage();
+ return control;
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogControl = (Composite) super.createDialogArea(parent);
+ WorkbenchHelp.setHelp(dialogControl, XMLCommonUIContextIds.XCUI_DOCTYPE_DIALOG);
+
+ Composite composite = new Composite(dialogControl, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.marginWidth = 0;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+
+ ModifyListener modifyListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (e.widget == systemIdField) {
+ computeSystemId = false;
+ }
+ updateErrorMessage();
+ }
+ };
+
+ // row 1
+ //
+ Label rootElementNameLabel = new Label(composite, SWT.NONE);
+ rootElementNameLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_ROOT_ELEMENT_NAME_COLON")); //$NON-NLS-1$
+
+ rootElementNameField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ WorkbenchHelp.setHelp(rootElementNameField, XMLCommonUIContextIds.XCUI_DOCTYPE_ROOT);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 200;
+ rootElementNameField.setLayoutData(gd);
+ rootElementNameField.setText(getDisplayValue(doctypeData[0]));
+ rootElementNameField.addModifyListener(modifyListener);
+
+ Label placeHolder = new Label(composite, SWT.NONE);
+ placeHolder.setLayoutData(new GridData());
+
+ // row 2
+ //
+ Label publicIdLabel = new Label(composite, SWT.NONE);
+ publicIdLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_PUBLIC_ID_COLON")); //$NON-NLS-1$
+
+ publicIdField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ WorkbenchHelp.setHelp(publicIdField, XMLCommonUIContextIds.XCUI_DOCTYPE_PUBLIC);
+ publicIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ publicIdField.setText(getDisplayValue(doctypeData[1]));
+
+ SelectionListener selectionListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ EditEntityHelper helper = new EditEntityHelper();
+ if (e.widget == publicIdBrowseButton) {
+ helper.performBrowseForPublicId(getShell(), publicIdField, computeSystemId ? systemIdField : null);
+ } else if (e.widget == systemIdBrowseButton) {
+ helper.performBrowseForSystemId(getShell(), systemIdField, resourceLocation);
+ }
+ }
+ };
+
+ publicIdBrowseButton = new Button(composite, SWT.NONE);
+ WorkbenchHelp.setHelp(publicIdBrowseButton, XMLCommonUIContextIds.XCUI_DOCTYPE_PUBLIC_BROWSE);
+ publicIdBrowseButton.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_BROWSE")); //$NON-NLS-1$
+ publicIdBrowseButton.addSelectionListener(selectionListener);
+
+ // row 3
+ Label systemIdLabel = new Label(composite, SWT.NONE);
+ systemIdLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_SYSTEM_ID_COLON")); //$NON-NLS-1$
+
+ systemIdField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ WorkbenchHelp.setHelp(systemIdField, XMLCommonUIContextIds.XCUI_DOCTYPE_SYSTEM);
+ systemIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ systemIdField.setText(getDisplayValue(doctypeData[2]));
+ systemIdField.addModifyListener(modifyListener);
+
+
+ systemIdBrowseButton = new Button(composite, SWT.NONE);
+ WorkbenchHelp.setHelp(systemIdBrowseButton, XMLCommonUIContextIds.XCUI_DOCTYPE_SYSTEM_BROWSE);
+ systemIdBrowseButton.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_BROWSE")); //$NON-NLS-1$
+ systemIdBrowseButton.addSelectionListener(selectionListener);
+
+ // error message
+ errorMessageLabel = new Label(dialogControl, SWT.NONE);
+ errorMessageLabel.setText(""); //$NON-NLS-1$
+ errorMessageLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+ errorMessageLabel.setForeground(color);
+
+ return dialogControl;
+ }
+
+
+ protected Label createMessageArea(Composite composite) {
+ Label label = new Label(composite, SWT.NONE);
+ //label.setText(message);
+ return label;
+ }
+
+
+ protected String getDisplayValue(String string) {
+ return string != null ? string : ""; //$NON-NLS-1$
+ }
+
+ public boolean getErrorChecking() {
+ return errorChecking;
+ }
+
+
+ protected String getModelValue(String string) {
+ String result = null;
+ if (string != null && string.trim().length() > 0) {
+ result = string;
+ }
+ return result;
+ }
+
+ public String getName() {
+ return doctypeData[0];
+ }
+
+ public String getPublicId() {
+ return doctypeData[1];
+ }
+
+ public String getSystemId() {
+ return doctypeData[2];
+ }
+
+ public void setComputeSystemId(boolean computeSystemId) {
+ this.computeSystemId = computeSystemId;
+ }
+
+ public void setErrorChecking(boolean errorChecking) {
+ this.errorChecking = errorChecking;
+ }
+
+ public void setResourceLocation(IPath path) {
+ resourceLocation = path;
+ }
+
+ public void updateErrorMessage() {
+ if (errorChecking) {
+ String errorMessage = null;
+ if (getModelValue(systemIdField.getText()) == null) {
+ errorMessage = XMLCommonResources.getInstance().getString("_UI_WARNING_SYSTEM_ID_MUST_BE_SPECIFIED"); //$NON-NLS-1$
+ } else if (getModelValue(rootElementNameField.getText()) == null) {
+ errorMessage = XMLCommonResources.getInstance().getString("_UI_WARNING_ROOT_ELEMENT_MUST_BE_SPECIFIED"); //$NON-NLS-1$
+ }
+
+ errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+ okButton.setEnabled(errorMessage == null);
+ }
+ }
+}
+
+
+
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditElementDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditElementDialog.java
new file mode 100644
index 0000000000..82e2bf8ba0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditElementDialog.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.wst.xml.core.NameValidator;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.ui.util.XMLCommonUIContextIds;
+import org.w3c.dom.Element;
+
+
+
+public class EditElementDialog extends Dialog implements ModifyListener {
+ protected Element element;
+ protected String elementName;
+ protected Text elementNameField;
+ protected Label errorMessageLabel;
+ protected Button okButton;
+
+ public EditElementDialog(Shell parentShell, Element element) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ this.element = element;
+ }
+
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.OK_ID) {
+ elementName = getModelValue(elementNameField.getText());
+ }
+ super.buttonPressed(buttonId);
+ }
+
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ elementNameField.forceFocus();
+ elementNameField.selectAll();
+ updateErrorMessage();
+ return control;
+ }
+
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogArea = (Composite) super.createDialogArea(parent);
+ WorkbenchHelp.setHelp(dialogArea, XMLCommonUIContextIds.XCUI_ELEMENT_DIALOG);
+
+ Composite composite = new Composite(dialogArea, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginWidth = 0;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label elementNameLabel = new Label(composite, SWT.NONE);
+ elementNameLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_ELEMENT_NAME")); //$NON-NLS-1$
+
+ elementNameField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 200;
+ elementNameField.setLayoutData(gd);
+ elementNameField.setText(getDisplayValue(element != null ? element.getNodeName() : "")); //$NON-NLS-1$
+ elementNameField.addModifyListener(this);
+
+ // error message
+ errorMessageLabel = new Label(composite, SWT.NONE);
+ errorMessageLabel.setText(ResourceHandler.getString("error_message_goes_here")); //$NON-NLS-1$
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ errorMessageLabel.setLayoutData(gd);
+ Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+ errorMessageLabel.setForeground(color);
+
+ return dialogArea;
+ }
+
+ protected String getDisplayValue(String string) {
+ return string != null ? string : ""; //$NON-NLS-1$
+ }
+
+ public String getElementName() {
+ return elementName;
+ }
+
+ protected String getModelValue(String string) {
+ String result = null;
+ if (string != null && string.trim().length() > 0) {
+ result = string;
+ }
+ return result;
+ }
+
+ public void modifyText(ModifyEvent e) {
+ updateErrorMessage();
+ }
+
+ protected void updateErrorMessage() {
+ String errorMessage = null;
+ String name = elementNameField.getText();
+ // String name = elementNameField.getText().trim();
+ if (name.length() > 0) {
+ // TODO use checkName from model level
+ //errorMessage = ValidateHelper.checkXMLName(name);
+ if (!NameValidator.isValid(name)) {
+ errorMessage = XMLCommonResources.getInstance().getString("_UI_INVALID_NAME");
+ }
+ } else {
+ errorMessage = ""; //$NON-NLS-1$
+ }
+
+ errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+ okButton.setEnabled(errorMessage == null);
+ }
+}
+
+
+
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditEntityHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditEntityHelper.java
new file mode 100644
index 0000000000..8e61d1dde8
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditEntityHelper.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogEntry;
+import org.eclipse.wst.xml.uriresolver.util.URIHelper;
+
+
+
+public class EditEntityHelper {
+
+ public void performBrowseForPublicId(Shell parentShell, Text publicIdField) {
+ performBrowseForPublicId(parentShell, publicIdField, null);
+ }
+
+ public void performBrowseForPublicId(Shell parentShell, Text publicIdField, Text systemIdField) {
+ String[] extensions = {"dtd", "txt"}; //$NON-NLS-1$ //$NON-NLS-2$
+ SelectXMLCatalogIdDialog dialog = new SelectXMLCatalogIdDialog(parentShell, extensions);
+ dialog.create();
+ dialog.getShell().setText(XMLCommonResources.getInstance().getString("_UI_LABEL_SELECT_XML_CATALOG_ENTRY")); //$NON-NLS-1$
+ dialog.setBlockOnOpen(true);
+ dialog.open();
+ if (dialog.getReturnCode() == Window.OK) {
+ String id = dialog.getId();
+ if (id != null) {
+ publicIdField.setText(id);
+ if (systemIdField != null && dialog.getSystemId() != null) {
+ systemIdField.setText(dialog.getSystemId());
+ }
+ }
+ }
+ }
+
+ public void performBrowseForSystemId(Shell parentShell, Text systemIdField, IPath resourceLocation) {
+ String[] extensions = {"dtd"}; //$NON-NLS-1$
+ SelectFileOrXMLCatalogIdDialog dialog = new SelectFileOrXMLCatalogIdDialog(parentShell, extensions, XMLCatalogEntry.SYSTEM);
+ dialog.create();
+ dialog.getShell().setText(XMLCommonResources.getInstance().getString("_UI_LABEL_SPECIFY_SYSTEM_ID")); //$NON-NLS-1$
+ dialog.setBlockOnOpen(true);
+ dialog.open();
+ if (dialog.getReturnCode() == Window.OK) {
+ String id = dialog.getId();
+ IFile file = dialog.getFile();
+ if (id != null) {
+ systemIdField.setText(id);
+ } else if (file != null) {
+ String uri = null;
+ if (resourceLocation != null) {
+ uri = URIHelper.getRelativeURI(file.getLocation(), resourceLocation);
+ } else {
+ uri = file.getLocation().toOSString();
+ }
+ systemIdField.setText(uri);
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditNamespaceInfoDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditNamespaceInfoDialog.java
new file mode 100644
index 0000000000..8ff59ea164
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditNamespaceInfoDialog.java
@@ -0,0 +1,255 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.common.contentmodel.CMDocument;
+import org.eclipse.wst.common.contentmodel.CMPlugin;
+import org.eclipse.wst.common.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.uriresolver.util.IdResolver;
+import org.eclipse.wst.xml.uriresolver.util.IdResolverImpl;
+import org.eclipse.wst.xml.uriresolver.util.URIHelper;
+
+
+
+public class EditNamespaceInfoDialog extends Dialog {
+
+ public static EditNamespaceInfoDialog invokeDialog(Shell shell, String title, NamespaceInfo info, IPath resourceLocation) {
+ EditNamespaceInfoDialog dialog = new EditNamespaceInfoDialog(shell, info);
+ dialog.create();
+ dialog.getShell().setText(title);
+ dialog.setBlockOnOpen(true);
+ dialog.setResourceLocation(resourceLocation);
+ dialog.open();
+ return dialog;
+ }
+
+ protected Button browseButton;
+ protected String errorMessage;
+
+ protected Label errorMessageLabel;
+ protected NamespaceInfo info;
+ protected Text locationHintField;
+
+ protected Button okButton;
+ protected Text prefixField;
+ protected IPath resourceLocation;
+ protected Text uriField;
+
+ public EditNamespaceInfoDialog(Shell parentShell, NamespaceInfo info) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ this.info = info;
+ }
+
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.OK_ID) {
+ info.uri = uriField.getText();
+ info.prefix = prefixField.getText();
+ info.locationHint = locationHintField.getText();
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ protected void computeErrorMessage() {
+ errorMessage = null;
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ okButton.setEnabled(false);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ updateWidgets();
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogArea = (Composite) super.createDialogArea(parent);
+ //TODO... SSE port
+ //WorkbenchHelp.setHelp(dialogArea,
+ // XMLCommonUIContextIds.XCUI_NAMESPACE_DIALOG);
+
+ Composite composite = new Composite(dialogArea, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.marginWidth = 0;
+ composite.setLayout(layout);
+
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 350;
+ composite.setLayoutData(gd);
+
+ ModifyListener modifyListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ updateWidgets();
+ }
+ };
+
+
+ // row 1
+ //
+ Label uriLabel = new Label(composite, SWT.NONE);
+ uriLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_NAMESPACE_NAME_COLON")); //$NON-NLS-1$
+
+ uriField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.grabExcessHorizontalSpace = true;
+ uriField.setLayoutData(gd);
+ uriField.setText(getDisplayValue(info.uri));
+ uriField.addModifyListener(modifyListener);
+ uriField.setEnabled(info.getProperty("uri-readOnly") == null); //$NON-NLS-1$
+
+ Label placeHolder1 = new Label(composite, SWT.NONE);
+
+ // row 2
+ //
+ Label prefixLabel = new Label(composite, SWT.NONE);
+ prefixLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_PREFIX_COLON")); //$NON-NLS-1$
+
+ prefixField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.grabExcessHorizontalSpace = true;
+ prefixField.setLayoutData(gd);
+ prefixField.setText(getDisplayValue(info.prefix));
+ prefixField.addModifyListener(modifyListener);
+ prefixField.setEnabled(info.getProperty("prefix-readOnly") == null); //$NON-NLS-1$
+ Label placeHolder2 = new Label(composite, SWT.NONE);
+
+ // row 3
+ //
+ Label locationHintLabel = new Label(composite, SWT.NONE);
+ locationHintLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_LOCATION_HINT_COLON")); //$NON-NLS-1$
+
+ locationHintField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.grabExcessHorizontalSpace = true;
+ locationHintField.setLayoutData(gd);
+ locationHintField.setText(getDisplayValue(info.locationHint));
+ locationHintField.addModifyListener(modifyListener);
+ locationHintField.setEnabled(info.getProperty("locationHint-readOnly") == null); //$NON-NLS-1$
+
+ SelectionListener selectionListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ performBrowse();
+ }
+ };
+
+ browseButton = new Button(composite, SWT.NONE);
+ browseButton.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_BROWSE")); //$NON-NLS-1$
+ browseButton.addSelectionListener(selectionListener);
+ browseButton.setEnabled(locationHintField.getEnabled());
+
+ // error message
+ errorMessageLabel = new Label(dialogArea, SWT.NONE);
+ errorMessageLabel.setText(ResourceHandler.getString("error_message_goes_here")); //$NON-NLS-1$
+ errorMessageLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+ errorMessageLabel.setForeground(color);
+
+ return dialogArea;
+ }
+
+ protected String getDisplayValue(String string) {
+ return string != null ? string : ""; //$NON-NLS-1$
+ }
+
+ protected void performBrowse() {
+ String[] extensions = {".xsd"}; //$NON-NLS-1$
+ SelectFileOrXMLCatalogIdDialog dialog = new SelectFileOrXMLCatalogIdDialog(getShell(), extensions);
+ dialog.create();
+ dialog.getShell().setText(XMLCommonResources.getInstance().getString("_UI_LABEL_SELECT_FILE")); //$NON-NLS-1$
+ dialog.setBlockOnOpen(true);
+ dialog.open();
+
+ if (dialog.getReturnCode() == Window.OK) {
+ String grammarURI = null;
+ IFile file = dialog.getFile();
+ String id = dialog.getId();
+ if (file != null) {
+ String uri = null;
+ if (resourceLocation != null) {
+ uri = URIHelper.getRelativeURI(file.getLocation(), resourceLocation);
+ grammarURI = file.getLocation().toOSString();
+ } else {
+ uri = file.getLocation().toOSString();
+ grammarURI = uri;
+ }
+ locationHintField.setText(uri);
+ } else if (id != null) {
+ locationHintField.setText(id);
+ IdResolver resolver = new IdResolverImpl(null);
+ grammarURI = resolver.resolveId(id, id);
+ }
+
+ try {
+ CMDocument document = CMPlugin.getInstance().createCMDocument(grammarURI, "xsd"); //$NON-NLS-1$
+ List namespaceInfoList = (List) document.getProperty("http://com.ibm.etools/cm/properties/namespaceInfo"); //$NON-NLS-1$
+ NamespaceInfo info = (NamespaceInfo) namespaceInfoList.get(0);
+ if (uriField.getText().trim().length() == 0 && info.uri != null) {
+ uriField.setText(info.uri);
+ }
+ if (prefixField.getText().trim().length() == 0 && info.prefix != null) {
+ prefixField.setText(info.prefix);
+ }
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ public void setResourceLocation(IPath path) {
+ resourceLocation = path;
+ }
+
+ protected void updateErrorMessageLabel() {
+ errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+ }
+
+ protected void updateOKButtonState() {
+ if (okButton != null) {
+ if (uriField.getText().trim().length() == 0 && prefixField.getText().trim().length() == 0 && locationHintField.getText().trim().length() == 0)
+ okButton.setEnabled(false);
+ else
+ okButton.setEnabled(errorMessage == null);
+ }
+ }
+
+ protected void updateWidgets() {
+ computeErrorMessage();
+ updateErrorMessageLabel();
+ updateOKButtonState();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditProcessingInstructionDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditProcessingInstructionDialog.java
new file mode 100644
index 0000000000..be3ae9f817
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditProcessingInstructionDialog.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.ui.util.XMLCommonUIContextIds;
+import org.w3c.dom.ProcessingInstruction;
+
+
+
+public class EditProcessingInstructionDialog extends Dialog {
+ protected String data;
+ protected Text dataField;
+ protected String target;
+ protected Text targetField;
+
+ public EditProcessingInstructionDialog(Shell parentShell, ProcessingInstruction pi) {
+ this(parentShell, pi.getTarget(), pi.getData());
+ }
+
+ public EditProcessingInstructionDialog(Shell parentShell, String target, String data) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ this.target = target;
+ this.data = data;
+ }
+
+ protected void buttonPressed(int buttonId) {
+ target = getModelValue(targetField.getText());
+ data = getModelValue(dataField.getText());
+ super.buttonPressed(buttonId);
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ Button okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogArea = (Composite) super.createDialogArea(parent);
+ WorkbenchHelp.setHelp(dialogArea, XMLCommonUIContextIds.XCUI_PROCESSING_DIALOG);
+
+ Composite composite = new Composite(dialogArea, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginWidth = 0;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 250;
+
+ Label targetLabel = new Label(composite, SWT.NONE);
+ targetLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_TARGET_COLON")); //$NON-NLS-1$
+
+ targetField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ targetField.setLayoutData(gd);
+ targetField.setText(getDisplayValue(target));
+
+ Label dataLabel = new Label(composite, SWT.NONE);
+ dataLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_DATA_COLON")); //$NON-NLS-1$
+
+ dataField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ dataField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ dataField.setText(getDisplayValue(data));
+
+ return dialogArea;
+ }
+
+ protected Label createMessageArea(Composite composite) {
+ Label label = new Label(composite, SWT.NONE);
+ //label.setText(message);
+ return label;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ protected String getDisplayValue(String string) {
+ return string != null ? string : ""; //$NON-NLS-1$
+ }
+
+ protected String getModelValue(String string) {
+ String result = null;
+ if (string != null && string.trim().length() > 0) {
+ result = string;
+ }
+ return result;
+ }
+
+
+ public String getTarget() {
+ return target;
+ }
+}
+
+
+
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditSchemaInfoDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditSchemaInfoDialog.java
new file mode 100644
index 0000000000..93f26c98ec
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/EditSchemaInfoDialog.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.dialogs;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.ui.nsedit.CommonEditNamespacesDialog;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+
+
+public class EditSchemaInfoDialog extends Dialog implements UpdateListener {
+ // protected NamespaceInfoTable namespaceInfoTable;
+ protected Label errorMessageLabel;
+ protected List namespaceInfoList;
+ protected IPath resourceLocation;
+
+ public EditSchemaInfoDialog(Shell parentShell, IPath resourceLocation) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ this.resourceLocation = resourceLocation;
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ Button okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogArea = (Composite) super.createDialogArea(parent);
+ CommonEditNamespacesDialog editNamespacesControl = new CommonEditNamespacesDialog(dialogArea, resourceLocation, XMLCommonResources.getInstance().getString("_UI_NAMESPACE_DECLARATIONS"), false, true); //$NON-NLS-1$
+ editNamespacesControl.setNamespaceInfoList(namespaceInfoList);
+
+ editNamespacesControl.updateErrorMessage(namespaceInfoList);
+
+ return dialogArea;
+ }
+
+ protected Control getDialogArea(Composite parent) {
+ return super.createDialogArea(parent);
+ }
+
+ public List getNamespaceInfoList() {
+ return namespaceInfoList;
+ }
+
+ public void setNamespaceInfoList(List list) {
+ namespaceInfoList = list;
+ }
+
+ public void updateErrorMessage(List namespaceInfoList) {
+ NamespaceInfoErrorHelper helper = new NamespaceInfoErrorHelper();
+ String errorMessage = helper.computeErrorMessage(namespaceInfoList, null);
+ errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+ }
+
+ public void updateOccured(Object object, Object arg) {
+ updateErrorMessage((List) arg);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/NamespaceInfoErrorHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/NamespaceInfoErrorHelper.java
new file mode 100644
index 0000000000..1a5f7c8378
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/NamespaceInfoErrorHelper.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.dialogs;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.common.contentmodel.util.DOMNamespaceInfoManager;
+import org.eclipse.wst.common.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.uriresolver.util.IdResolver;
+import org.eclipse.wst.xml.uriresolver.util.URIHelper;
+
+
+
+public class NamespaceInfoErrorHelper {
+
+ protected List errorList;
+
+ public NamespaceInfoErrorHelper() {
+ }
+
+ public String computeErrorMessage(List namespaceInfoList, IdResolver idResolver) {
+ String result = null;
+ Hashtable prefixTable = new Hashtable();
+ Hashtable uriTable = new Hashtable();
+ for (Iterator iterator = namespaceInfoList.iterator(); iterator.hasNext();) {
+ NamespaceInfo nsInfo = (NamespaceInfo) iterator.next();
+ nsInfo.normalize();
+
+ String urikey = nsInfo.uri != null ? nsInfo.uri : ""; //$NON-NLS-1$
+ NamespaceInfo nsInfo2 = null;
+ if ((nsInfo2 = (NamespaceInfo) uriTable.get(urikey)) != null) {
+ if (nsInfo.uri != null && nsInfo.uri.equals(nsInfo2.uri)) {
+ result = XMLCommonResources.getInstance().getString("_UI_WARNING_MORE_THAN_ONE_NS_WITH_NAME") + "'" + nsInfo.uri + "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ } else {
+ result = XMLCommonResources.getInstance().getString("_UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_NAME"); //$NON-NLS-1$
+ }
+ break;
+ } else {
+ uriTable.put(urikey, nsInfo);
+ }
+
+ if (nsInfo.uri != null) {
+ String key = nsInfo.prefix != null ? nsInfo.prefix : ""; //$NON-NLS-1$
+ if (prefixTable.get(key) != null) {
+ if (nsInfo.prefix != null) {
+ result = XMLCommonResources.getInstance().getString("_UI_WARNING_MORE_THAN_ONE_NS_WITH_PREFIX") + "'" + nsInfo.prefix + "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ } else {
+ result = XMLCommonResources.getInstance().getString("_UI_WARNING_MORE_THAN_ONE_NS_WITHOUT_PREFIX"); //$NON-NLS-1$
+ break;
+ }
+ } else {
+ prefixTable.put(key, nsInfo);
+ }
+
+ if (nsInfo.locationHint != null && idResolver != null) {
+ String grammarURI = idResolver.resolveId(nsInfo.locationHint, nsInfo.locationHint);
+ if (!URIHelper.isReadableURI(grammarURI, false)) {
+ result = XMLCommonResources.getInstance().getString("_UI_WARNING_SCHEMA_CAN_NOT_BE_LOCATED") + " '" + nsInfo.locationHint + "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ }
+ }
+ if (idResolver != null && nsInfo.locationHint == null && !nsInfo.uri.equals(DOMNamespaceInfoManager.XSI_URI)) {
+ result = XMLCommonResources.getInstance().getString("_UI_WARNING_LOCATION_HINT_NOT_SPECIFIED") + " '" + nsInfo.uri + "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ }
+ } else {
+ if (nsInfo.prefix != null) {
+ result = XMLCommonResources.getInstance().getString("_UI_WARNING_NAMESPACE_NAME_NOT_SPECIFIED") + " '" + nsInfo.prefix + "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ }
+ }
+ }
+ // additional tests
+ if (result == null) {
+ for (Iterator iterator = namespaceInfoList.iterator(); iterator.hasNext();) {
+ NamespaceInfo nsInfo = (NamespaceInfo) iterator.next();
+ nsInfo.normalize();
+ if (nsInfo.uri != null && nsInfo.isPrefixRequired && nsInfo.prefix == null) {
+ result = XMLCommonResources.getInstance().getString("_UI_WARNING_PREFIX_NOT_SPECIFIED") + " '" + nsInfo.uri + "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/NamespaceInfoTable.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/NamespaceInfoTable.java
new file mode 100644
index 0000000000..9a3c4aff15
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/NamespaceInfoTable.java
@@ -0,0 +1,391 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.dialogs;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.wst.common.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+
+
+public class NamespaceInfoTable extends Composite {
+
+ /**
+ * NamespaceInfoTableLabelProvider
+ */
+ protected class NamespaceInfoTableLabelProvider implements ITableLabelProvider, IStructuredContentProvider {
+
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ public void dispose() {
+ }
+
+ public Image getColumnImage(Object object, int columnIndex) {
+ return null;
+ }
+
+ public String getColumnText(Object object, int column) {
+ NamespaceInfo info = (NamespaceInfo) object;
+ String result = null;
+ switch (column) {
+ case 0 : {
+ result = info.uri;
+ break;
+ }
+ case 1 : {
+ result = info.prefix;
+ break;
+ }
+ case 2 : {
+ result = info.locationHint;
+ break;
+ }
+ }
+ result = result != null ? result : ""; //$NON-NLS-1$
+ if (result.equals("")) { //$NON-NLS-1$
+ switch (column) {
+ case 0 : {
+ result = XMLCommonResources.getInstance().getString("_UI_NO_NAMESPACE_NAME"); //$NON-NLS-1$
+ break;
+ }
+ case 1 : {
+ result = XMLCommonResources.getInstance().getString("_UI_NO_PREFIX"); //$NON-NLS-1$
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ String getDefaultPrefix() {
+ String defaultPrefix = "p"; //$NON-NLS-1$
+ if (namespaceInfoList == null)
+ return defaultPrefix;
+ Vector v = new Vector();
+ for (int i = 0; i < namespaceInfoList.size(); i++) {
+ NamespaceInfo nsinfo = (NamespaceInfo) namespaceInfoList.get(i);
+ if (nsinfo.prefix != null)
+ v.addElement(nsinfo.prefix);
+ }
+ if (v.contains(defaultPrefix)) {
+ String s = defaultPrefix;
+ for (int j = 0; v.contains(s); j++) {
+ s = defaultPrefix + Integer.toString(j);
+ }
+ return s;
+ } else
+ return defaultPrefix;
+ }
+
+ public Object[] getElements(Object inputElement) {
+ return namespaceInfoList.toArray();
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public boolean isDeleted(Object element) {
+ return false;
+ }
+
+ public boolean isLabelProperty(Object object, Object property) {
+ return false;
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ }
+ }
+
+ protected static final String LOCATION_HINT = XMLCommonResources.getInstance().getString("_UI_LABEL_LOCATION_HINT"); //$NON-NLS-1$
+ protected static final String NAMESPACE_URI = XMLCommonResources.getInstance().getString("_UI_LABEL_NAMESPACE_NAME"); //$NON-NLS-1$
+ protected static final String PREFIX = XMLCommonResources.getInstance().getString("_UI_LABEL_PREFIX"); //$NON-NLS-1$
+ protected Button deleteButton;
+ protected boolean dummyRowsRemoved = false;
+ protected Button editButton;
+ protected List namespaceInfoList = new Vector();
+ protected Button newButton;
+ protected NamespaceInfoTableLabelProvider provider;
+ protected IPath resourceLocation;
+ protected TableViewer tableViewer;
+ protected UpdateListener updateListener;
+ protected int visibleRows = -1;
+
+ public NamespaceInfoTable(Composite parent) {
+ this(parent, -1, -1, -1);
+ }
+
+ public NamespaceInfoTable(Composite parent, int visibleRows) {
+ this(parent, -1, -1, visibleRows);
+ }
+
+ public NamespaceInfoTable(Composite parent, int widthHint, int heightHint) {
+ this(parent, widthHint, heightHint, -1);
+ }
+
+ public NamespaceInfoTable(Composite parent, int widthHint, int heightHint, int visibleRows) {
+ super(parent, SWT.NONE);
+ setLayout(createGridLayout());
+ setLayoutData(new GridData(GridData.FILL_BOTH));
+ Group namespaceInfoGroup = new Group(this, SWT.NONE);
+ namespaceInfoGroup.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_XML_SCHEMA_INFORMATION")); //$NON-NLS-1$
+ namespaceInfoGroup.setLayout(new GridLayout());
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ if (widthHint != -1) {
+ gd.widthHint = widthHint;
+ }
+ if (heightHint != -1) {
+ gd.heightHint = heightHint;
+ }
+ namespaceInfoGroup.setLayoutData(gd);
+ //WorkbenchHelp.setHelp(namespaceInfoGroup, new
+ // ControlContextComputer(namespaceInfoGroup,
+ // XMLBuilderContextIds.XMLC_NAMESPACE_GROUP));
+ String[] titleArray = {NAMESPACE_URI, PREFIX, LOCATION_HINT};
+ tableViewer = new TableViewer(namespaceInfoGroup, SWT.FULL_SELECTION);
+ provider = new NamespaceInfoTableLabelProvider();
+ tableViewer.setContentProvider(provider);
+ tableViewer.setLabelProvider(provider);
+ tableViewer.setColumnProperties(titleArray);
+ Table table = tableViewer.getTable();
+ table.setHeaderVisible(true);
+ table.setLayoutData(new GridData(GridData.FILL_BOTH));
+ int[] widthArray = {50, 20, 30};
+ TableLayout layout = new TableLayout();
+ for (int i = 0; i < titleArray.length; i++) {
+ TableColumn column = new TableColumn(table, i);
+ column.setText(titleArray[i]);
+ column.setAlignment(SWT.LEFT);
+ layout.addColumnData(new ColumnWeightData(widthArray[i], true));
+ }
+ this.visibleRows = visibleRows;
+ for (int i = 0; i < visibleRows; i++) {
+ TableItem item = new TableItem(table, SWT.NONE);
+ item.setText("#######"); //$NON-NLS-1$
+ }
+ table.setLayout(layout);
+ CellEditor[] cellEditors = new CellEditor[titleArray.length];
+ cellEditors[1] = new TextCellEditor(table);
+ cellEditors[2] = new TextCellEditor(table);
+ tableViewer.setCellEditors(cellEditors);
+ MouseAdapter mouseAdapter = new MouseAdapter() {
+ public void mouseDoubleClick(MouseEvent e) {
+ if (tableViewer.getTable().getItem(new Point(e.x, e.y)) != null) {
+ performEdit();
+ }
+ }
+ };
+ table.addMouseListener(mouseAdapter);
+ createButtons(namespaceInfoGroup);
+ ISelectionChangedListener selectionChangedListener = new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateButtonEnabledState();
+ }
+ };
+ tableViewer.addSelectionChangedListener(selectionChangedListener);
+ }
+
+ protected void createButtons(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 2;
+ gridLayout.marginHeight = 0;
+ gridLayout.marginWidth = 0;
+ composite.setLayout(gridLayout);
+ Button hiddenButton = new Button(composite, SWT.NONE);
+ hiddenButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ hiddenButton.setVisible(false);
+ hiddenButton.setEnabled(false);
+ SelectionListener selectionListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (e.widget == newButton) {
+ performNew();
+ } else if (e.widget == editButton) {
+ performEdit();
+ } else if (e.widget == deleteButton) {
+ performDelete();
+ }
+ }
+ };
+ // create a composite to hold the three buttons
+ Composite buttonComposite = new Composite(composite, SWT.NONE);
+ buttonComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ GridLayout buttonGridLayout = new GridLayout();
+ buttonGridLayout.numColumns = 3;
+ buttonGridLayout.makeColumnsEqualWidth = true;
+ buttonComposite.setLayout(buttonGridLayout);
+ // add the New button
+ //
+ newButton = new Button(buttonComposite, SWT.NONE);
+ newButton.setText(XMLCommonResources.getInstance().getString("_UI_BUTTON_NEW")); //$NON-NLS-1$
+ newButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ newButton.addSelectionListener(selectionListener);
+ // add the Edit button
+ //
+ editButton = new Button(buttonComposite, SWT.NONE);
+ editButton.setText(XMLCommonResources.getInstance().getString("_UI_BUTTON_EDIT")); //$NON-NLS-1$
+ editButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ editButton.addSelectionListener(selectionListener);
+ // add the Delete button
+ //
+ deleteButton = new Button(buttonComposite, SWT.NONE);
+ deleteButton.setText(XMLCommonResources.getInstance().getString("_UI_BUTTON_DELETE")); //$NON-NLS-1$
+ deleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ deleteButton.addSelectionListener(selectionListener);
+ }
+
+ public GridLayout createGridLayout() {
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginWidth = 0;
+ gridLayout.horizontalSpacing = 0;
+ return gridLayout;
+ }
+
+ public List getNamespaceInfoList() {
+ return namespaceInfoList;
+ }
+
+ protected NamespaceInfo getTargetNamespaceInfo() {
+ return (namespaceInfoList != null && namespaceInfoList.size() > 0) ? (NamespaceInfo) namespaceInfoList.get(0) : null;
+ }
+
+ protected EditNamespaceInfoDialog invokeDialog(String title, NamespaceInfo info) {
+ Shell shell = XMLCommonResources.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+ EditNamespaceInfoDialog dialog = new EditNamespaceInfoDialog(shell, info);
+ dialog.create();
+ dialog.getShell().setText(title);
+ dialog.setBlockOnOpen(true);
+ dialog.setResourceLocation(resourceLocation);
+ dialog.open();
+ return dialog;
+ }
+
+ protected void performDelayedUpdate() {
+ Runnable delayedUpdate = new Runnable() {
+ public void run() {
+ update();
+ }
+ };
+ getDisplay().asyncExec(delayedUpdate);
+ if (updateListener != null) {
+ updateListener.updateOccured(this, namespaceInfoList);
+ }
+ }
+
+ public void performDelete() {
+ ISelection selection = tableViewer.getSelection();
+ Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+ if (selectedObject != null) {
+ namespaceInfoList.remove(selectedObject);
+ performDelayedUpdate();
+ }
+ }
+
+ public void performEdit() {
+ ISelection selection = tableViewer.getSelection();
+ Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+ if (selectedObject instanceof NamespaceInfo) {
+ EditNamespaceInfoDialog dialog = invokeDialog(XMLCommonResources.getInstance().getString("_UI_LABEL_NEW_NAMESPACE_INFORMATION"), (NamespaceInfo) selectedObject); //$NON-NLS-1$
+ performDelayedUpdate();
+ }
+ }
+
+ public void performNew() {
+ NamespaceInfo info = new NamespaceInfo();
+ EditNamespaceInfoDialog dialog = invokeDialog(XMLCommonResources.getInstance().getString("_UI_LABEL_NEW_NAMESPACE_INFORMATION"), info); //$NON-NLS-1$
+ if (dialog.getReturnCode() == Window.OK) {
+ namespaceInfoList.add(info);
+ performDelayedUpdate();
+ }
+ }
+
+ public void setNamespaceInfoList(List namespaceInfoList) {
+ this.namespaceInfoList = namespaceInfoList;
+ update();
+ }
+
+ public void setResourceLocation(IPath resourceLocation) {
+ this.resourceLocation = resourceLocation;
+ }
+
+ public void setUpdateListener(UpdateListener updateListener) {
+ this.updateListener = updateListener;
+ }
+
+ public void update() {
+ updateHelper(namespaceInfoList);
+ }
+
+ public void updateButtonEnabledState() {
+ ISelection selection = tableViewer.getSelection();
+ Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+ NamespaceInfo info = (NamespaceInfo) selectedObject;
+ editButton.setEnabled(info != null);
+ deleteButton.setEnabled(info != null && info.getProperty("unremovable") == null); //$NON-NLS-1$
+ }
+
+ public void updateHelper(List namespaceInfoList) {
+ if (visibleRows != -1 && !dummyRowsRemoved) {
+ dummyRowsRemoved = true;
+ tableViewer.getTable().removeAll();
+ }
+ ISelection selection = tableViewer.getSelection();
+ tableViewer.setInput(namespaceInfoList);
+ if (selection.isEmpty()) {
+ if (namespaceInfoList.size() > 0) {
+ tableViewer.setSelection(new StructuredSelection(namespaceInfoList.get(0)));
+ }
+ } else {
+ tableViewer.setSelection(selection);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectFileOrXMLCatalogIdDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectFileOrXMLCatalogIdDialog.java
new file mode 100644
index 0000000000..4c8397c90e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectFileOrXMLCatalogIdDialog.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.dialogs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+
+public class SelectFileOrXMLCatalogIdDialog extends Dialog {
+ protected int catalogEntryType;
+ protected String[] extensions;
+ protected IFile file;
+ protected String id;
+ protected Button okButton;
+ protected SelectFileOrXMLCatalogIdPanel panel;
+
+ public SelectFileOrXMLCatalogIdDialog(Shell parentShell, String[] extensions) {
+ this(parentShell, extensions, 0);
+ }
+
+ public SelectFileOrXMLCatalogIdDialog(Shell parentShell, String[] extensions, int catalogEntryType) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ this.extensions = extensions;
+ this.catalogEntryType = catalogEntryType;
+ }
+
+
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.OK_ID) {
+ file = panel.getFile();
+ id = panel.getXMLCatalogId();
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ okButton.setEnabled(false);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogArea = (Composite) super.createDialogArea(parent);
+
+ panel = new SelectFileOrXMLCatalogIdPanel(dialogArea);
+ panel.setCatalogEntryType(catalogEntryType);
+ panel.setFilterExtensions(extensions);
+ panel.setVisibleHelper(true);
+ SelectFileOrXMLCatalogIdPanel.Listener listener = new SelectFileOrXMLCatalogIdPanel.Listener() {
+ public void completionStateChanged() {
+ updateButtonState();
+ }
+ };
+ panel.setListener(listener);
+
+ return dialogArea;
+ }
+
+ public IFile getFile() {
+ return file;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ protected void updateButtonState() {
+ okButton.setEnabled(panel.getFile() != null || panel.getXMLCatalogId() != null);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectFileOrXMLCatalogIdPanel.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectFileOrXMLCatalogIdPanel.java
new file mode 100644
index 0000000000..3805e8f4de
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectFileOrXMLCatalogIdPanel.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.wst.ui.viewers.SelectSingleFileView;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.uriresolver.XMLCatalog;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogEntry;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogPlugin;
+
+
+public class SelectFileOrXMLCatalogIdPanel extends Composite implements SelectionListener {
+
+ /**
+ * TODO: Change the name of this interface; "Listener" is used by SWT.
+ */
+ public interface Listener {
+ void completionStateChanged();
+ }
+
+ protected class MySelectSingleFileView extends SelectSingleFileView implements SelectSingleFileView.Listener {
+ protected Control control;
+
+ public MySelectSingleFileView(Composite parent) {
+ super(null, true);
+ //String[] ext = {".dtd"};
+ //addFilterExtensions(ext);
+ control = createControl(parent);
+ control.setLayoutData(new GridData(GridData.FILL_BOTH));
+ MySelectSingleFileView.this.setListener(this);
+ }
+
+ public Control getControl() {
+ return control;
+ }
+
+ public void setControlComplete(boolean isComplete) {
+ updateCompletionStateChange();
+ }
+
+ public void setVisibleHelper(boolean isVisible) {
+ super.setVisibleHelper(isVisible);
+ }
+ }
+
+ protected Listener listener;
+ protected PageBook pageBook;
+
+ protected Button[] radioButton;
+ protected MySelectSingleFileView selectSingleFileView;
+ protected SelectXMLCatalogIdPanel selectXMLCatalogIdPanel;
+
+ public SelectFileOrXMLCatalogIdPanel(Composite parent) {
+ super(parent, SWT.NONE);
+
+ // container group
+ setLayout(new GridLayout());
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = 400;
+ gd.widthHint = 400;
+ setLayoutData(gd);
+
+ radioButton = new Button[2];
+ radioButton[0] = new Button(this, SWT.RADIO);
+ radioButton[0].setText(XMLCommonResources.getInstance().getString("_UI_RADIO_BUTTON_SELECT_FROM_WORKSPACE")); //$NON-NLS-1$
+ radioButton[0].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ radioButton[0].setSelection(true);
+ radioButton[0].addSelectionListener(this);
+
+ radioButton[1] = new Button(this, SWT.RADIO);
+ radioButton[1].setText(XMLCommonResources.getInstance().getString("_UI_RADIO_BUTTON_SELECT_FROM_CATALOG")); //$NON-NLS-1$
+ radioButton[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ radioButton[1].addSelectionListener(this);
+
+ pageBook = new PageBook(this, SWT.NONE);
+ pageBook.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ selectSingleFileView = new MySelectSingleFileView(pageBook);
+
+ XMLCatalog xmlCatalog = XMLCatalogPlugin.getInstance().getDefaultXMLCatalog();
+ selectXMLCatalogIdPanel = new SelectXMLCatalogIdPanel(pageBook, xmlCatalog);
+ selectXMLCatalogIdPanel.getTableViewer().addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateCompletionStateChange();
+ }
+ });
+ pageBook.showPage(selectSingleFileView.getControl());
+ }
+
+ public IFile getFile() {
+ IFile result = null;
+ if (radioButton[0].getSelection()) {
+ result = selectSingleFileView.getFile();
+ }
+ return result;
+ }
+
+ public XMLCatalogEntry getXMLCatalogEntry() {
+ XMLCatalogEntry result = null;
+ if (radioButton[1].getSelection()) {
+ result = selectXMLCatalogIdPanel.getXMLCatalogEntry();
+ }
+ return result;
+ }
+
+ public String getXMLCatalogId() {
+ String result = null;
+ if (radioButton[1].getSelection()) {
+ result = selectXMLCatalogIdPanel.getId();
+ }
+ return result;
+ }
+
+ public String getXMLCatalogURI() {
+ String result = null;
+ if (radioButton[1].getSelection()) {
+ result = selectXMLCatalogIdPanel.getURI();
+ }
+ return result;
+ }
+
+ public void setCatalogEntryType(int catalogEntryType) {
+ selectXMLCatalogIdPanel.setCatalogEntryType(catalogEntryType);
+ }
+
+ public void setFilterExtensions(String[] filterExtensions) {
+ selectSingleFileView.resetFilters();
+ selectSingleFileView.addFilterExtensions(filterExtensions);
+
+ selectXMLCatalogIdPanel.getTableViewer().setFilterExtensions(filterExtensions);
+ }
+
+ public void setListener(Listener listener) {
+ this.listener = listener;
+ }
+
+ public void setVisibleHelper(boolean isVisible) {
+ selectSingleFileView.setVisibleHelper(isVisible);
+ }
+
+ public void updateCompletionStateChange() {
+ if (listener != null) {
+ listener.completionStateChanged();
+ }
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ if (e.widget == radioButton[0]) {
+ pageBook.showPage(selectSingleFileView.getControl());
+ } else {
+ pageBook.showPage(selectXMLCatalogIdPanel);
+ }
+ updateCompletionStateChange();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectXMLCatalogIdDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectXMLCatalogIdDialog.java
new file mode 100644
index 0000000000..65cb8bd065
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectXMLCatalogIdDialog.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.xml.uriresolver.XMLCatalog;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogEntry;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogPlugin;
+
+
+
+public class SelectXMLCatalogIdDialog extends Dialog {
+ protected String[] extensions;
+ protected Button okButton;
+ protected SelectXMLCatalogIdPanel panel;
+ protected String publicId;
+ protected String systemId;
+
+ public SelectXMLCatalogIdDialog(Shell parentShell, String[] extensions) {
+ super(parentShell);
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ this.extensions = extensions;
+ }
+
+
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.OK_ID) {
+ ISelection selection = panel.getTableViewer().getSelection();
+ Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+
+ if (selectedObject instanceof XMLCatalogEntry) {
+ XMLCatalogEntry mappingInfo = (XMLCatalogEntry) selectedObject;
+ publicId = mappingInfo.getKey();
+ systemId = computeDefaultSystemId(mappingInfo);
+ }
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ protected String computeDefaultSystemId(XMLCatalogEntry mappingInfo) {
+ String result = mappingInfo.getWebAddress();
+ if (result == null && mappingInfo.getURI() != null) {
+ int index = mappingInfo.getURI().lastIndexOf("/"); //$NON-NLS-1$
+ String lastSegment = index != -1 ? mappingInfo.getURI().substring(index + 1) : mappingInfo.getURI();
+ result = lastSegment;
+ }
+ return result;
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ okButton.setEnabled(false);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogArea = (Composite) super.createDialogArea(parent);
+ // TODO... SSE port
+ //WorkbenchHelp.setHelp(dialogArea,
+ // XMLCommonUIContextIds.XCUI_CATALOG_DIALOG);
+
+ XMLCatalog xmlCatalog = XMLCatalogPlugin.getInstance().getDefaultXMLCatalog();
+ panel = new SelectXMLCatalogIdPanel(dialogArea, xmlCatalog);
+
+ ISelectionChangedListener listener = new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateButtonState();
+ }
+ };
+ panel.getTableViewer().setFilterExtensions(extensions);
+ panel.getTableViewer().addSelectionChangedListener(listener);
+ return dialogArea;
+ }
+
+
+
+ public String getId() {
+ return publicId;
+ }
+
+ public String getSystemId() {
+ return systemId;
+ }
+
+ protected void updateButtonState() {
+ ISelection selection = panel.getTableViewer().getSelection();
+ okButton.setEnabled(!selection.isEmpty());
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectXMLCatalogIdPanel.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectXMLCatalogIdPanel.java
new file mode 100644
index 0000000000..19390cc0fa
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/SelectXMLCatalogIdPanel.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.uriresolver.XMLCatalog;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogEntry;
+
+
+public class SelectXMLCatalogIdPanel extends Composite {
+ protected int catalogEntryType;
+ protected boolean doTableSizeHack = false;
+
+ protected XMLCatalogTableViewer tableViewer;
+ protected XMLCatalog xmlCatalog;
+
+ public SelectXMLCatalogIdPanel(Composite parent, XMLCatalog xmlCatalog) {
+ super(parent, SWT.NONE);
+ this.xmlCatalog = xmlCatalog;
+
+ GridLayout gridLayout = new GridLayout();
+ this.setLayout(gridLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.heightHint = 200;
+ gd.widthHint = 700;
+ this.setLayoutData(gd);
+
+ Label label = new Label(this, SWT.NONE);
+ label.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_XML_CATALOG_COLON")); //$NON-NLS-1$
+
+ tableViewer = createTableViewer(this);
+ tableViewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
+ tableViewer.setInput("dummy"); //$NON-NLS-1$
+ }
+
+ protected XMLCatalogTableViewer createTableViewer(Composite parent) {
+ String headings[] = new String[2];
+ headings[0] = XMLCommonResources.getInstance().getString("_UI_LABEL_KEY"); //$NON-NLS-1$
+ headings[1] = XMLCommonResources.getInstance().getString("_UI_LABEL_URI"); //$NON-NLS-1$
+
+ XMLCatalogTableViewer theTableViewer = new XMLCatalogTableViewer(parent, headings) {
+
+ protected void addXMLCatalogEntries(List list, Collection collection) {
+ for (Iterator i = collection.iterator(); i.hasNext();) {
+ XMLCatalogEntry entry = (XMLCatalogEntry) i.next();
+ if (catalogEntryType == 0) {
+ list.add(entry);
+ } else if (catalogEntryType == entry.getType()) {
+ list.add(entry);
+ }
+ }
+ }
+
+ public Collection getXMLCatalogEntries() {
+ List result = null;
+
+ if (xmlCatalog == null || doTableSizeHack) {
+ // this lets us create a table with an initial height of
+ // 10 rows
+ // otherwise we get stuck with 0 row heigh table... that's
+ // too small
+ doTableSizeHack = false;
+ result = new Vector();
+ for (int i = 0; i < 6; i++) {
+ result.add(""); //$NON-NLS-1$
+ }
+ } else {
+ result = new Vector();
+
+ addXMLCatalogEntries(result, xmlCatalog.getChildCatalog(XMLCatalog.SYSTEM_CATALOG_ID).getEntries());
+ addXMLCatalogEntries(result, xmlCatalog.getChildCatalog(XMLCatalog.USER_CATALOG_ID).getEntries());
+ }
+ return result;
+ }
+ };
+ return theTableViewer;
+ }
+
+
+ public String getId() {
+ XMLCatalogEntry entry = getXMLCatalogEntry();
+ return entry != null ? entry.getKey() : null;
+ }
+
+ public XMLCatalogTableViewer getTableViewer() {
+ return tableViewer;
+ }
+
+ public String getURI() {
+ XMLCatalogEntry entry = getXMLCatalogEntry();
+ return entry != null ? entry.getURI() : null;
+ }
+
+ public XMLCatalogEntry getXMLCatalogEntry() {
+ XMLCatalogEntry result = null;
+ ISelection selection = tableViewer.getSelection();
+ Object selectedObject = (selection instanceof IStructuredSelection) ? ((IStructuredSelection) selection).getFirstElement() : null;
+ if (selectedObject instanceof XMLCatalogEntry) {
+ result = (XMLCatalogEntry) selectedObject;
+ }
+ return result;
+ }
+
+ public void setCatalogEntryType(int catalogEntryType) {
+ this.catalogEntryType = catalogEntryType;
+ tableViewer.refresh();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/UpdateListener.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/UpdateListener.java
new file mode 100644
index 0000000000..2ae05bdcb1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/UpdateListener.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+public interface UpdateListener {
+
+ public void updateOccured(Object object, Object arg);
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/XMLCatalogTableViewer.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/XMLCatalogTableViewer.java
new file mode 100644
index 0000000000..3f5262c8a5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dialogs/XMLCatalogTableViewer.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dialogs;
+
+import java.text.Collator;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogEntry;
+import org.eclipse.wst.xml.uriresolver.util.URIHelper;
+
+
+public class XMLCatalogTableViewer extends TableViewer {
+
+
+ public class CatalogEntryContentProvider implements IStructuredContentProvider {
+
+ public void dispose() {
+ }
+
+ public Object[] getElements(Object element) {
+ Object[] array = getXMLCatalogEntries().toArray();
+ Comparator comparator = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ int result = 0;
+ if (o1 instanceof XMLCatalogEntry && o2 instanceof XMLCatalogEntry) {
+ XMLCatalogEntry mappingInfo1 = (XMLCatalogEntry) o1;
+ XMLCatalogEntry mappingInfo2 = (XMLCatalogEntry) o2;
+ result = Collator.getInstance().compare(mappingInfo1.getKey(), mappingInfo2.getKey());
+ }
+ return result;
+ }
+ };
+ Arrays.sort(array, comparator);
+ return array;
+ }
+
+ public void inputChanged(Viewer viewer, Object old, Object newobj) {
+ }
+
+ public boolean isDeleted(Object object) {
+ return false;
+ }
+ }
+
+ public class CatalogEntryLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+ public Image getColumnImage(Object object, int columnIndex) {
+ Image result = null;
+ if (columnIndex == 0) {
+ Image base = null;
+ if (object instanceof XMLCatalogEntry) {
+ XMLCatalogEntry catalogEntry = (XMLCatalogEntry) object;
+ String uri = catalogEntry.getURI();
+ if (uri.endsWith("dtd")) { //$NON-NLS-1$
+ base = dtdFileImage;
+ } else if (uri.endsWith("xsd")) { //$NON-NLS-1$
+ base = xsdFileImage;
+ } else {
+ base = unknownFileImage;
+ }
+
+ if (base != null) {
+ if (URIHelper.isReadableURI(uri, false)) {
+ result = base;
+ } else {
+ //TODO... SSE port
+ result = base;//imageFactory.createCompositeImage(base,
+ // errorImage,
+ // ImageFactory.BOTTOM_LEFT);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ public String getColumnText(Object object, int columnIndex) {
+ String result = null;
+ if (object instanceof XMLCatalogEntry) {
+ XMLCatalogEntry catalogEntry = (XMLCatalogEntry) object;
+ result = columnIndex == 0 ? catalogEntry.getKey() : catalogEntry.getURI();
+ result = URIHelper.removePlatformResourceProtocol(result);
+ }
+ return result != null ? result : ""; //$NON-NLS-1$
+ }
+ }
+
+
+ class XMLCatalogTableViewerFilter extends ViewerFilter {
+ protected String[] extensions;
+
+ public XMLCatalogTableViewerFilter(String[] extensions) {
+ this.extensions = extensions;
+ }
+
+ public boolean isFilterProperty(Object element, Object property) {
+ return false;
+ }
+
+ public boolean select(Viewer viewer, Object parent, Object element) {
+ boolean result = false;
+ if (element instanceof XMLCatalogEntry) {
+ XMLCatalogEntry catalogEntry = (XMLCatalogEntry) element;
+ for (int i = 0; i < extensions.length; i++) {
+ if (catalogEntry.getURI().endsWith(extensions[i])) {
+ result = true;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+ }
+
+ protected static Image dtdFileImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_DTDFILE);
+
+ protected static String ERROR_STATE_KEY = "errorstatekey"; //$NON-NLS-1$
+ protected static Image errorImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OVR_ERROR);
+
+ protected static Image unknownFileImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TXTEXT);
+ protected static Image xsdFileImage = XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_XSDFILE);
+
+ //protected ImageFactory imageFactory = new ImageFactory();
+
+ public XMLCatalogTableViewer(Composite parent, String[] columnProperties) {
+ super(parent, SWT.FULL_SELECTION);
+
+ Table table = getTable();
+ table.setLinesVisible(true);
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+
+ TableLayout layout = new TableLayout();
+ for (int i = 0; i < columnProperties.length; i++) {
+ TableColumn column = new TableColumn(table, i);
+ column.setText(columnProperties[i]);
+ column.setAlignment(SWT.LEFT);
+ layout.addColumnData(new ColumnWeightData(50, true));
+ }
+ table.setLayout(layout);
+ table.setLinesVisible(false);
+
+ setColumnProperties(columnProperties);
+
+ setContentProvider(new CatalogEntryContentProvider());
+ setLabelProvider(new CatalogEntryLabelProvider());
+ }
+
+ public Collection getXMLCatalogEntries() {
+ return null;
+ }
+
+
+ public void menuAboutToShow(IMenuManager menuManager) {
+ Action action = new Action("hello") { //$NON-NLS-1$
+ public void run() {
+ System.out.println("run!"); //$NON-NLS-1$
+ }
+ };
+ menuManager.add(action);
+ }
+
+ public void setFilterExtensions(String[] extensions) {
+ resetFilters();
+ addFilter(new XMLCatalogTableViewerFilter(extensions));
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dnd/DragNodeCommand.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dnd/DragNodeCommand.java
new file mode 100644
index 0000000000..94118e20a5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dnd/DragNodeCommand.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.dnd;
+
+
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.ui.dnd.DefaultDragAndDropCommand;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class DragNodeCommand extends DefaultDragAndDropCommand {
+ public DragNodeCommand(Object target, float location, int operations, int operation, Collection sources) {
+ super(target, location, operations, operation, sources);
+ }
+
+ protected void beginModelChange(Node node, boolean batchUpdate) {
+ IStructuredModel structuredModel = getStructedModel(node);
+ if (structuredModel != null) {
+ structuredModel.beginRecording(this, ResourceHandler.getString("DragNodeCommand.0")); //$NON-NLS-1$
+ if (batchUpdate) {
+ // structuredModel.aboutToChangeModel();
+ }
+ }
+ }
+
+ public boolean canExecute() {
+ return executeHelper(true);
+ }
+
+
+ public boolean doMove(Node source, Node parentNode, Node refChild, boolean testOnly) {
+ boolean result = false;
+ if (source.getNodeType() == Node.ATTRIBUTE_NODE) {
+ Attr sourceAttribute = (Attr) source;
+ Element sourceAttributeOwnerElement = sourceAttribute.getOwnerElement();
+ if (parentNode.getNodeType() == Node.ELEMENT_NODE && sourceAttributeOwnerElement != parentNode) {
+ result = true;
+ if (!testOnly) {
+ try {
+ Element targetElement = (Element) parentNode;
+ targetElement.setAttribute(sourceAttribute.getName(), sourceAttribute.getValue());
+ sourceAttributeOwnerElement.removeAttributeNode(sourceAttribute);
+ } catch (Exception e) {
+ }
+ }
+ }
+ } else {
+ if ((parentNode.getNodeType() == Node.ELEMENT_NODE || parentNode.getNodeType() == Node.DOCUMENT_NODE) && !(refChild instanceof Attr)) {
+ result = true;
+
+ if (!testOnly) {
+ if (isAncestor(source, parentNode)) {
+ //System.out.println("can not perform this drag drop
+ // operation.... todo... pop up dialog");
+ } else {
+ // defect 221055 this test is required or else the
+ // node will
+ // be removed from the tree and the insert will fail
+ if (source != refChild) {
+ source.getParentNode().removeChild(source);
+ parentNode.insertBefore(source, refChild);
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ protected void endModelChange(Node node, boolean batchUpdate) {
+ IStructuredModel structuredModel = getStructedModel(node);
+ if (structuredModel != null) {
+ structuredModel.endRecording(this);
+ if (batchUpdate) {
+ // structuredModel.changedModel();
+ }
+ }
+ }
+
+ public void execute() {
+ executeHelper(false);
+ }
+
+ //
+ //
+ public boolean executeHelper(boolean testOnly) {
+ boolean result = true;
+ if (target instanceof Node) {
+ Node targetNode = (Node) target;
+ Node parentNode = getParentForDropPosition(targetNode);
+ Node refChild = getRefChild(targetNode);
+
+ Vector sourcesList = new Vector();
+ sourcesList.addAll(sources);
+
+ removeMemberDescendants(sourcesList);
+ boolean performBatchUpdate = sourcesList.size() > 5;
+
+ if (!testOnly) {
+ beginModelChange(targetNode, performBatchUpdate);
+ }
+ for (Iterator i = sourcesList.iterator(); i.hasNext();) {
+ Object source = i.next();
+ if (source instanceof Node) {
+ if (!(refChild == null && targetNode instanceof Attr)) {
+ result = doMove((Node) source, parentNode, refChild, testOnly);
+ } else {
+ result = false;
+ }
+ if (!result) {
+ break;
+ }
+ }
+ }
+ if (!testOnly) {
+ endModelChange(targetNode, performBatchUpdate);
+ }
+ } else {
+ result = false;
+ }
+ return result;
+ }
+
+
+ public int getFeedback() {
+ int result = DND.FEEDBACK_SELECT;
+ if (location > 0.75) {
+ result = DND.FEEDBACK_INSERT_AFTER;
+ } else if (location < 0.25) {
+ result = DND.FEEDBACK_INSERT_BEFORE;
+ }
+ return result;
+ }
+
+ protected Node getParentForDropPosition(Node node) {
+ Node result = null;
+
+ int feedback = getFeedback();
+ if (feedback == DND.FEEDBACK_SELECT) {
+ result = node;
+ } else {
+ result = getParentOrOwner(node);
+ }
+ return result;
+ }
+
+
+ protected Node getParentOrOwner(Node node) {
+ return (node.getNodeType() == Node.ATTRIBUTE_NODE) ? ((Attr) node).getOwnerElement() : node.getParentNode();
+ }
+
+
+ protected Node getRefChild(Node node) {
+ Node result = null;
+
+ int feedback = getFeedback();
+
+ if (feedback == DND.FEEDBACK_INSERT_BEFORE) {
+ result = node;
+ } else if (feedback == DND.FEEDBACK_INSERT_AFTER) {
+ result = node.getNextSibling();
+ }
+ return result;
+ }
+
+ protected IStructuredModel getStructedModel(Node node) {
+ IStructuredModel result = null;
+ if (node instanceof XMLNode) {
+ result = ((XMLNode) node).getModel();
+ }
+ return result;
+ }
+
+ // returns true if a is an ancestore of b
+ //
+ protected boolean isAncestor(Node a, Node b) {
+ boolean result = false;
+ for (Node parent = b; parent != null; parent = parent.getParentNode()) {
+ if (parent == a) {
+ result = true;
+ break;
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * This method removes members of the list that have ancestors that are
+ * also members of the list.
+ */
+ protected void removeMemberDescendants(List list) {
+ Hashtable table = new Hashtable();
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ Object node = i.next();
+ table.put(node, node);
+ }
+
+ for (int i = list.size() - 1; i >= 0; i--) {
+ Node node = (Node) list.get(i);
+ for (Node parent = getParentOrOwner(node); parent != null; parent = getParentOrOwner(parent)) {
+ if (table.get(parent) != null) {
+ list.remove(i);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dnd/XMLDragAndDropManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dnd/XMLDragAndDropManager.java
new file mode 100644
index 0000000000..432cafd73b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/dnd/XMLDragAndDropManager.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.dnd;
+
+import java.util.Collection;
+
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.wst.ui.dnd.DragAndDropCommand;
+import org.eclipse.wst.ui.dnd.DragAndDropManager;
+import org.eclipse.wst.ui.dnd.ObjectTransfer;
+import org.eclipse.wst.ui.dnd.ViewerDragAdapter;
+import org.eclipse.wst.ui.dnd.ViewerDropAdapter;
+import org.w3c.dom.Node;
+
+public class XMLDragAndDropManager implements DragAndDropManager {
+ public static void addDragAndDropSupport(TreeViewer viewer) {
+ int dndOperations = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
+ Transfer[] transfers = new Transfer[]{ObjectTransfer.getInstance()};
+ viewer.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(viewer));
+ viewer.addDropSupport(dndOperations, transfers, new ViewerDropAdapter(viewer, new XMLDragAndDropManager()));
+ }
+
+ public XMLDragAndDropManager() {
+ }
+
+ public DragAndDropCommand createCommand(Object target, float location, int operations, int operation, Collection source) {
+ DragAndDropCommand result = null;
+ if (target instanceof Node) {
+ Node node = (Node) target;
+ result = new DragNodeCommand(target, location, operations, operation, source);
+ }
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/doubleclick/XMLDoubleClickStrategy.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/doubleclick/XMLDoubleClickStrategy.java
new file mode 100644
index 0000000000..aca4617ed0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/doubleclick/XMLDoubleClickStrategy.java
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.doubleclick;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.text.DefaultTextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.wst.sse.core.IModelManager;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Node;
+
+
+public class XMLDoubleClickStrategy extends DefaultTextDoubleClickStrategy {
+ protected static final char DOUBLE_QUOTE = '\"';
+ protected static final char SINGLE_QUOTE = '\'';
+ protected static final char SPACE = ' ';
+ protected int fCaretPosition = -1;
+ protected int fDoubleClickCount = 0;
+ protected Node fNode = null;
+ protected IStructuredDocumentRegion fStructuredDocumentRegion = null;
+ protected String fStructuredDocumentRegionText = ""; //$NON-NLS-1$
+ protected IStructuredModel fStructuredModel = null;
+ protected StructuredTextViewer fStructuredTextViewer;
+ protected ITextRegion fTextRegion = null;
+
+ public void doubleClicked(ITextViewer textViewer) {
+ if (textViewer instanceof StructuredTextViewer) {
+ fStructuredTextViewer = (StructuredTextViewer) textViewer;
+ try {
+ fStructuredModel = getModelManager().getExistingModelForRead(fStructuredTextViewer.getDocument());
+
+ if (fStructuredModel != null) {
+ int caretPosition = textViewer.getSelectedRange().x;
+ if (caretPosition < 0)
+ return;
+
+ fNode = (Node) fStructuredModel.getIndexedRegion(caretPosition);
+ if (fNode == null)
+ return;
+
+ updateDoubleClickCount(caretPosition);
+ updateStructuredDocumentRegion();
+ updateTextRegion();
+
+ if (fNode.getNodeType() == Node.TEXT_NODE)
+ processTextDoubleClicked();
+ else
+ processElementDoubleClicked();
+ }
+ } finally {
+ if (fStructuredModel != null)
+ fStructuredModel.releaseFromRead();
+ }
+ }
+ }
+
+ protected IModelManager getModelManager() {
+ IModelManagerPlugin plugin = (IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID);
+ return plugin.getModelManager();
+ }
+
+ protected Point getWord(String string, int cursor) {
+ if (string == null)
+ return null;
+
+ int wordStart = 0;
+ int wordEnd = string.length();
+
+ wordStart = string.lastIndexOf(SPACE, cursor - 1);
+ int temp = string.lastIndexOf(SINGLE_QUOTE, cursor - 1);
+ wordStart = Math.max(wordStart, temp);
+ temp = string.lastIndexOf(DOUBLE_QUOTE, cursor - 1);
+ wordStart = Math.max(wordStart, temp);
+ if (wordStart == -1)
+ wordStart = cursor;
+ else
+ wordStart++;
+
+ wordEnd = string.indexOf(SPACE, cursor);
+ if (wordEnd == -1)
+ wordEnd = string.length();
+ temp = string.indexOf(SINGLE_QUOTE, cursor);
+ if (temp == -1)
+ temp = string.length();
+ wordEnd = Math.min(wordEnd, temp);
+ temp = string.indexOf(DOUBLE_QUOTE, cursor);
+ if (temp == -1)
+ temp = string.length();
+ wordEnd = Math.min(wordEnd, temp);
+ if (wordEnd == string.length())
+ wordEnd = cursor;
+
+ if ((wordStart == wordEnd) && !isQuoted(string)) {
+ wordStart = 0;
+ wordEnd = string.length();
+ }
+
+ return new Point(wordStart, wordEnd);
+ }
+
+ protected boolean isQuoted(String string) {
+ if ((string == null) || (string.length() < 2))
+ return false;
+
+ int lastIndex = string.length() - 1;
+ char firstChar = string.charAt(0);
+ char lastChar = string.charAt(lastIndex);
+
+ return (((firstChar == SINGLE_QUOTE) && (lastChar == SINGLE_QUOTE)) || ((firstChar == DOUBLE_QUOTE) && (lastChar == DOUBLE_QUOTE)));
+ }
+
+ protected void processElementAttrEqualsDoubleClicked2Times() {
+ int prevRegionOffset = fStructuredDocumentRegion.getStartOffset(fTextRegion) - 1;
+ ITextRegion prevRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(prevRegionOffset);
+ int nextRegionOffset = fStructuredDocumentRegion.getEndOffset(fTextRegion);
+ ITextRegion nextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(nextRegionOffset);
+
+ if ((prevRegion != null) && (prevRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) && (nextRegion != null) && (nextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(prevRegion), nextRegion.getTextEnd() - prevRegion.getStart());
+ }
+ }
+
+ protected void processElementAttrNameDoubleClicked2Times() {
+ int nextRegionOffset = fStructuredDocumentRegion.getEndOffset(fTextRegion);
+ ITextRegion nextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(nextRegionOffset);
+
+ if (nextRegion != null) {
+ nextRegionOffset = fStructuredDocumentRegion.getEndOffset(nextRegion);
+ nextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(nextRegionOffset);
+ if ((nextRegion != null) && (nextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), nextRegion.getTextEnd() - fTextRegion.getStart());
+ } else {
+ // attribute has no value
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+ fDoubleClickCount = 0;
+ }
+ }
+ }
+
+ protected void processElementAttrValueDoubleClicked() {
+ String regionText = fStructuredDocumentRegion.getText(fTextRegion);
+
+ if (fDoubleClickCount == 1) {
+ Point word = getWord(regionText, fCaretPosition - fStructuredDocumentRegion.getStartOffset(fTextRegion));
+ if (word.x == word.y) { // no word found; select whole region
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), regionText.length());
+ fDoubleClickCount++;
+ } else
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion) + word.x, word.y - word.x);
+ } else if (fDoubleClickCount == 2) {
+ if (isQuoted(regionText)) {
+ // ==> // Point word = getWord(regionText, fCaretPosition -
+ // fStructuredDocumentRegion.getStartOffset(fTextRegion));
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), regionText.length());
+ } else
+ processElementAttrValueDoubleClicked2Times();
+ } else if (fDoubleClickCount == 3) {
+ if (isQuoted(regionText))
+ processElementAttrValueDoubleClicked2Times();
+ else {
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+ fDoubleClickCount = 0;
+ }
+ } else { // fDoubleClickCount == 4
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+ fDoubleClickCount = 0;
+ }
+ }
+
+ protected void processElementAttrValueDoubleClicked2Times() {
+ int prevRegionOffset = fStructuredDocumentRegion.getStartOffset(fTextRegion) - 1;
+ ITextRegion prevRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(prevRegionOffset);
+
+ if (prevRegion != null) {
+ prevRegionOffset = fStructuredDocumentRegion.getStartOffset(prevRegion) - 1;
+ prevRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(prevRegionOffset);
+ if ((prevRegion != null) && (prevRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(prevRegion), fTextRegion.getTextEnd() - prevRegion.getStart());
+ }
+ }
+ }
+
+ protected void processElementDoubleClicked() {
+ if (fTextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+ processElementAttrValueDoubleClicked(); // special handling for
+ // XML_TAG_ATTRIBUTE_VALUE
+ else {
+ if (fDoubleClickCount == 1) {
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart() + fTextRegion.getStart(), fTextRegion.getTextLength());
+ } else if (fDoubleClickCount == 2) {
+ if (fTextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME)
+ processElementAttrNameDoubleClicked2Times();
+ else if (fTextRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS)
+ processElementAttrEqualsDoubleClicked2Times();
+ else {
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+ fDoubleClickCount = 0;
+ }
+ } else { // fDoubleClickCount == 3
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+ fDoubleClickCount = 0;
+ }
+ }
+ }
+
+ protected void processTextDoubleClicked() {
+ if (fDoubleClickCount == 1) {
+ super.doubleClicked(fStructuredTextViewer);
+
+ Point selectedRange = fStructuredTextViewer.getSelectedRange();
+ if ((selectedRange.x == fStructuredDocumentRegion.getStartOffset(fTextRegion)) && (selectedRange.y == fTextRegion.getTextLength()))
+ // only one word in region, skip one level of double click
+ // selection
+ fDoubleClickCount++;
+ } else if (fDoubleClickCount == 2) {
+ if (fTextRegion.getType() == XMLRegionContext.UNDEFINED) {
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+ fDoubleClickCount = 0;
+ } else {
+ if (isQuoted(fStructuredDocumentRegion.getFullText(fTextRegion)))
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion) + 1, fTextRegion.getTextLength() - 2);
+ else
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), fTextRegion.getTextLength());
+ }
+ } else {
+ if ((fDoubleClickCount == 3) && isQuoted(fStructuredDocumentRegion.getFullText(fTextRegion)))
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStartOffset(fTextRegion), fTextRegion.getTextLength());
+ else {
+ if ((fDoubleClickCount == 3) && isQuoted(fStructuredDocumentRegionText))
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart() + 1, fStructuredDocumentRegion.getLength() - 2);
+ else {
+ fStructuredTextViewer.setSelectedRange(fStructuredDocumentRegion.getStart(), fStructuredDocumentRegion.getLength());
+ fDoubleClickCount = 0;
+ }
+ }
+ }
+ }
+
+ public void setModel(IStructuredModel structuredModel) {
+ fStructuredModel = structuredModel;
+ }
+
+ protected void updateDoubleClickCount(int caretPosition) {
+ if (fCaretPosition == caretPosition) {
+ if (fStructuredDocumentRegion != null)
+ fDoubleClickCount++;
+ else
+ fDoubleClickCount = 1;
+ } else {
+ fCaretPosition = caretPosition;
+ fDoubleClickCount = 1;
+ }
+ }
+
+ protected void updateStructuredDocumentRegion() {
+ fStructuredDocumentRegion = fStructuredModel.getStructuredDocument().getRegionAtCharacterOffset(fCaretPosition);
+ if (fStructuredDocumentRegion != null)
+ fStructuredDocumentRegionText = fStructuredDocumentRegion.getText();
+ else
+ fStructuredDocumentRegionText = ""; //$NON-NLS-1$
+ }
+
+ protected void updateTextRegion() {
+ if (fStructuredDocumentRegion != null) {
+ fTextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(fCaretPosition);
+ // if fTextRegion is null, it means we are at just past the last
+ // fStructuredDocumentRegion,
+ // at the very end of the document, so we'll use the last text
+ // region in the document
+ if (fTextRegion == null) {
+ fTextRegion = fStructuredDocumentRegion.getRegionAtCharacterOffset(fCaretPosition - 1);
+ }
+ } else
+ fTextRegion = null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extension/IDesignViewerSelectionManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extension/IDesignViewerSelectionManager.java
new file mode 100644
index 0000000000..5792dbf777
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extension/IDesignViewerSelectionManager.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.extension;
+
+import org.eclipse.wst.sse.ui.ViewerSelectionManager;
+import org.w3c.dom.Node;
+import org.w3c.dom.ranges.Range;
+
+
+/*
+ * This class is currently an internal class used by Quick Edit view.
+ */
+public interface IDesignViewerSelectionManager extends ViewerSelectionManager {
+ Node getFocusedNode();
+
+ Range getRange();
+
+ void pause();
+
+ void reset();
+
+ void resume();
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extension/IExtendedDesignEditor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extension/IExtendedDesignEditor.java
new file mode 100644
index 0000000000..c73b66f47c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extension/IExtendedDesignEditor.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.extension;
+
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.ui.extension.IExtendedMarkupEditorExtension;
+
+
+/*
+ * This class is currently an internal class used by Quick Edit view.
+ */
+public interface IExtendedDesignEditor extends IExtendedMarkupEditorExtension {
+
+ IEditorInput getActiveEditorInput();
+
+ IStructuredModel getActiveModel();
+
+ IDesignViewerSelectionManager getDesignViewerSelectionMediator();
+
+ IEditorInput getEditorInput();
+
+ IStructuredModel getModel();
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extensions/XMLSourceEditingTextTools.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extensions/XMLSourceEditingTextTools.java
new file mode 100644
index 0000000000..6d610cab75
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/extensions/XMLSourceEditingTextTools.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.extensions;
+
+
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.IModelManager;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.ui.extensions.breakpoint.NodeLocation;
+import org.eclipse.wst.sse.ui.extensions.breakpoint.SourceEditingTextTools;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.document.XMLText;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+
+/**
+ * Implements SourceEditingTextTools interface
+ */
+public class XMLSourceEditingTextTools implements SourceEditingTextTools, INodeAdapter {
+
+ protected class NodeLocationImpl implements NodeLocation {
+ private XMLNode node;
+
+ public NodeLocationImpl(XMLNode xmlnode) {
+ super();
+ node = xmlnode;
+ }
+
+ public int getEndTagEndOffset() {
+ if (node.getEndStructuredDocumentRegion() != null)
+ return node.getEndStructuredDocumentRegion().getEndOffset();
+ return -1;
+ }
+
+ public int getEndTagStartOffset() {
+ if (node.getEndStructuredDocumentRegion() != null)
+ return node.getEndStructuredDocumentRegion().getStartOffset();
+ return -1;
+ }
+
+ public int getStartTagEndOffset() {
+ if (node.getStartStructuredDocumentRegion() != null)
+ return node.getStartStructuredDocumentRegion().getEndOffset();
+ return -1;
+ }
+
+ public int getStartTagStartOffset() {
+ if (node.getStartStructuredDocumentRegion() != null)
+ return node.getStartStructuredDocumentRegion().getStartOffset();
+ return -1;
+ }
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.extensions.SourceEditingTextTools#getDOMDocument(org.eclipse.core.resources.IMarker)
+ */
+ public Document getDOMDocument(IMarker marker) {
+ if (marker == null)
+ return null;
+
+ IResource res = marker.getResource();
+ if (res == null || !(res instanceof IFile))
+ return null;
+
+ IModelManagerPlugin plugin = (IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID);
+ IModelManager mm = plugin.getModelManager();
+ IStructuredModel model = null;
+ try {
+ model = mm.getExistingModelForRead((IFile) res);
+ if (model == null || !(model instanceof XMLModel))
+ return null;
+
+ return ((XMLModel) model).getDocument();
+ } finally {
+ if (model != null)
+ model.releaseFromRead();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.extensions.SourceEditingTextTools#getNodeLocation(org.w3c.dom.Node)
+ */
+ public NodeLocation getNodeLocation(Node node) {
+ if (node.getNodeType() == Node.ELEMENT_NODE && node instanceof XMLNode)
+ return new NodeLocationImpl((XMLNode) node);
+ return null;
+ }
+
+ public String getPageLanguage(Node node) {
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.extensions.SourceEditingTextTools#getStartOffset(org.w3c.dom.Node)
+ */
+ public int getStartOffset(Node node) {
+ if (node == null || !(node instanceof XMLText))
+ return -1;
+
+ IStructuredDocumentRegion fnode = ((XMLText) node).getFirstStructuredDocumentRegion();
+ return fnode.getStartOffset();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.core.INodeAdapter#isAdapterForType(java.lang.Object)
+ */
+ public boolean isAdapterForType(Object type) {
+ return SourceEditingTextTools.class.equals(type);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.core.core.INodeAdapter#notifyChanged(org.eclipse.wst.sse.core.core.INodeNotifier,
+ * int, java.lang.Object, java.lang.Object, java.lang.Object, int)
+ */
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/StructuredAutoEditStrategyXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/StructuredAutoEditStrategyXML.java
new file mode 100644
index 0000000000..0d7f5a692e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/autoedit/StructuredAutoEditStrategyXML.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.autoedit;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+import org.eclipse.wst.sse.core.IModelManager;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.ui.StructuredDocumentCommand;
+import org.eclipse.wst.sse.ui.edit.util.BasicAutoEditStrategy;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.ui.Logger;
+import org.w3c.dom.Node;
+
+
+public class StructuredAutoEditStrategyXML extends BasicAutoEditStrategy {
+ public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
+ StructuredDocumentCommand structuredDocumentCommand = (StructuredDocumentCommand) command;
+ Object textEditor = getActiveTextEditor();
+ if (!(textEditor instanceof ITextEditorExtension3 && ((ITextEditorExtension3) textEditor).getInsertMode() == ITextEditorExtension3.SMART_INSERT))
+ return;
+
+ IStructuredModel model = null;
+ try {
+ model = getModelManager().getExistingModelForRead(document);
+ if (model != null) {
+ if (structuredDocumentCommand.text != null) {
+ smartInsertForComment(structuredDocumentCommand, document, model);
+ smartInsertForEndTag(structuredDocumentCommand, document, model);
+ }
+ }
+ } finally {
+ if (model != null)
+ model.releaseFromRead();
+ }
+ }
+
+ private IModelManager getModelManager() {
+
+ IModelManagerPlugin plugin = (IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID);
+ return plugin.getModelManager();
+ }
+
+ private boolean isCommentNode(XMLNode node) {
+ return (node != null && node instanceof XMLElement && ((XMLElement) node).isCommentTag());
+ }
+
+ private boolean isDocumentNode(XMLNode node) {
+ return (node != null && node.getNodeType() == Node.DOCUMENT_NODE);
+ }
+
+ protected boolean isEndTagRequired(XMLNode node) {
+
+ if (node == null)
+ return false;
+ return node.isContainer();
+ }
+
+ protected boolean prefixedWith(IDocument document, int offset, String string) {
+
+ try {
+ return document.getLength() >= string.length() && document.get(offset - string.length(), string.length()).equals(string);
+ } catch (BadLocationException e) {
+ Logger.logException(e);
+ return false;
+ }
+ }
+
+ protected void smartInsertForComment(StructuredDocumentCommand structuredDocumentCommand, IDocument document, IStructuredModel model) {
+ try {
+ if (structuredDocumentCommand.text.equals("-") && document.getLength() >= 3 && document.get(structuredDocumentCommand.offset - 3, 3).equals("<!-")) { //$NON-NLS-1$ //$NON-NLS-2$
+ structuredDocumentCommand.text += " "; //$NON-NLS-1$
+ structuredDocumentCommand.doit = false;
+ structuredDocumentCommand.addCommand(structuredDocumentCommand.offset, 0, " -->", null); //$NON-NLS-1$
+ }
+ } catch (BadLocationException e) {
+ Logger.logException(e);
+ }
+
+ }
+
+ protected void smartInsertForEndTag(StructuredDocumentCommand structuredDocumentCommand, IDocument document, IStructuredModel model) {
+ try {
+ if (structuredDocumentCommand.text.equals("/") && document.getLength() >= 1 && document.get(structuredDocumentCommand.offset - 1, 1).equals("<")) { //$NON-NLS-1$ //$NON-NLS-2$
+ XMLNode parentNode = (XMLNode) ((XMLNode) model.getIndexedRegion(structuredDocumentCommand.offset - 1)).getParentNode();
+ if (isCommentNode(parentNode)) {
+ // loop and find non comment node parent
+ while (parentNode != null && isCommentNode(parentNode)) {
+ parentNode = (XMLNode) parentNode.getParentNode();
+ }
+ }
+
+ if (!isDocumentNode(parentNode)) {
+ IStructuredDocumentRegion endTagStructuredDocumentRegion = parentNode.getEndStructuredDocumentRegion();
+ if (endTagStructuredDocumentRegion == null) {
+ structuredDocumentCommand.text += parentNode.getNodeName();
+ structuredDocumentCommand.text += ">"; //$NON-NLS-1$
+ }
+ }
+ }
+ } catch (BadLocationException e) {
+ Logger.logException(e);
+ }
+
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionProcessorXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionProcessorXML.java
new file mode 100644
index 0000000000..bfb47cb15d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/CorrectionProcessorXML.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.ui.internal.correction.IQuickAssistProcessor;
+import org.eclipse.wst.sse.ui.internal.correction.IQuickFixProcessor;
+import org.eclipse.wst.sse.ui.internal.correction.StructuredCorrectionProcessor;
+
+
+public class CorrectionProcessorXML extends StructuredCorrectionProcessor {
+ protected IQuickAssistProcessor fQuickAssistProcessor;
+ protected IQuickFixProcessor fQuickFixProcessor;
+
+ public CorrectionProcessorXML(ITextEditor editor) {
+ super(editor);
+ }
+
+ protected IQuickAssistProcessor getQuickAssistProcessor() {
+ if (fQuickAssistProcessor == null)
+ fQuickAssistProcessor = new QuickAssistProcessorXML();
+
+ return fQuickAssistProcessor;
+ }
+
+ protected IQuickFixProcessor getQuickFixProcessor() {
+ if (fQuickFixProcessor == null)
+ fQuickFixProcessor = new QuickFixProcessorXML();
+
+ return fQuickFixProcessor;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/InsertRequiredAttrsQuickAssistProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/InsertRequiredAttrsQuickAssistProposal.java
new file mode 100644
index 0000000000..1624d44452
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/InsertRequiredAttrsQuickAssistProposal.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+
+public class InsertRequiredAttrsQuickAssistProposal implements ICompletionProposal, ICompletionProposalExtension2 {
+ private final List fRequiredAttrs;
+
+ /**
+ * @param requiredAttrs
+ */
+ public InsertRequiredAttrsQuickAssistProposal(List requiredAttrs) {
+ fRequiredAttrs = requiredAttrs;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
+ */
+ public void apply(IDocument document) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+ * char, int, int)
+ */
+ public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
+ XMLNode node = (XMLNode) ContentAssistUtils.getNodeAt((StructuredTextViewer) viewer, offset);
+ IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+ int index = startStructuredDocumentRegion.getEndOffset();
+ ITextRegion lastRegion = startStructuredDocumentRegion.getLastRegion();
+ if (lastRegion.getType() == XMLRegionContext.XML_TAG_CLOSE) {
+ index--;
+ lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+ } else if (lastRegion.getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE) {
+ index = index - 2;
+ lastRegion = startStructuredDocumentRegion.getRegionAtCharacterOffset(index - 1);
+ }
+ MultiTextEdit multiTextEdit = new MultiTextEdit();
+ try {
+ for (int i = 0; i < fRequiredAttrs.size(); i++) {
+ CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) fRequiredAttrs.get(i);
+ String requiredAttributeName = attrDecl.getAttrName();
+ String defaultValue = attrDecl.getDefaultValue();
+ if (defaultValue == null)
+ defaultValue = ""; //$NON-NLS-1$
+ String nameAndDefaultValue = " "; //$NON-NLS-1$
+ if (i == 0 && lastRegion.getLength() > lastRegion.getTextLength())
+ nameAndDefaultValue = ""; //$NON-NLS-1$
+ nameAndDefaultValue += requiredAttributeName + "=\"" + defaultValue + "\""; //$NON-NLS-1$//$NON-NLS-2$
+ multiTextEdit.addChild(new InsertEdit(index, nameAndDefaultValue));
+ // BUG3381: MultiTextEdit applies all child TextEdit's basing
+ // on offsets
+ // in the document before the first TextEdit, not after each
+ // child TextEdit. Therefore, do not need to advance the
+ // index.
+ //index += nameAndDefaultValue.length();
+ }
+ multiTextEdit.apply(viewer.getDocument());
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return ResourceHandler.getString("InsertRequiredAttrsQuickAssistProposal.0"); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
+ */
+ public IContextInformation getContextInformation() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return ResourceHandler.getString("InsertRequiredAttrsQuickAssistProposal.1"); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ // return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
+ return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ADD_CORRECTION);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
+ */
+ public Point getSelection(IDocument document) {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
+ * boolean)
+ */
+ public void selected(ITextViewer viewer, boolean smartToggle) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
+ */
+ public void unselected(ITextViewer viewer) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
+ * int, org.eclipse.jface.text.DocumentEvent)
+ */
+ public boolean validate(IDocument document, int offset, DocumentEvent event) {
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/ProblemIDsXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/ProblemIDsXML.java
new file mode 100644
index 0000000000..4d0008bb7a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/ProblemIDsXML.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+public interface ProblemIDsXML {
+ int AttrsInEndTag = 3;
+ int AttrValueNotQuoted = 13;
+ int EmptyTag = 1;
+ int InvalidAttrValue = 11;
+ int MissingAttrValue = 4;
+ int MissingClosingBracket = 14;
+ int MissingEndTag = 2;
+ int MissingRequiredAttr = 12;
+ int NamespaceInPI = 8;
+ int NoAttrValue = 5;
+ int SpacesBeforePI = 7;
+ int SpacesBeforeTagName = 6;
+ int Unclassified = 0;
+ int UnknownAttr = 10;
+ int UnknownElement = 9;
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickAssistProcessorXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickAssistProcessorXML.java
new file mode 100644
index 0000000000..b2f00fa8dd
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickAssistProcessorXML.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.sse.ui.internal.correction.IQuickAssistProcessor;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+public class QuickAssistProcessorXML implements IQuickAssistProcessor {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.correction.IQuickAssistProcessor#canAssist(org.eclipse.wst.sse.core.text.IStructuredDocument,
+ * int)
+ */
+ public boolean canAssist(StructuredTextViewer viewer, int offset) {
+ return true;
+ }
+
+ /**
+ * @param proposals
+ * @param viewer
+ * @param offset
+ */
+ protected void getInsertRequiredAttrs(ArrayList proposals, StructuredTextViewer viewer, int offset) {
+ XMLNode node = (XMLNode) ContentAssistUtils.getNodeAt(viewer, offset);
+ if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
+ IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+ if (startStructuredDocumentRegion != null && startStructuredDocumentRegion.containsOffset(offset)) {
+ XMLNode cursorNode = (XMLNode) ContentAssistUtils.getNodeAt(viewer, offset);
+ List requiredAttrs = getRequiredAttrs(cursorNode);
+ if (requiredAttrs.size() > 0) {
+ NamedNodeMap currentAttrs = node.getAttributes();
+ List insertAttrs = new ArrayList();
+ if (currentAttrs.getLength() == 0)
+ insertAttrs.addAll(requiredAttrs);
+ else {
+ for (int i = 0; i < requiredAttrs.size(); i++) {
+ String requiredAttrName = ((CMAttributeDeclaration) requiredAttrs.get(i)).getAttrName();
+ boolean found = false;
+ for (int j = 0; j < currentAttrs.getLength(); j++) {
+ String currentAttrName = currentAttrs.item(j).getNodeName();
+ if (requiredAttrName.compareToIgnoreCase(currentAttrName) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ insertAttrs.add(requiredAttrs.get(i));
+ }
+ }
+ if (insertAttrs.size() > 0)
+ proposals.add(new InsertRequiredAttrsQuickAssistProposal(insertAttrs));
+ }
+ }
+ }
+ }
+
+ /**
+ * @param proposals
+ * @param viewer
+ * @param offset
+ */
+ protected void getLocalRenameQuickAssistProposal(ArrayList proposals, StructuredTextViewer viewer, int offset) {
+ XMLNode node = (XMLNode) ContentAssistUtils.getNodeAt(viewer, offset);
+ IStructuredDocumentRegion startStructuredDocumentRegion = node == null ? null : node.getStartStructuredDocumentRegion();
+ IStructuredDocumentRegion endStructuredDocumentRegion = node == null ? null : node.getEndStructuredDocumentRegion();
+
+ ITextRegion region = null;
+ int regionTextEndOffset = 0;
+ if (startStructuredDocumentRegion != null && startStructuredDocumentRegion.containsOffset(offset)) {
+ region = startStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+ regionTextEndOffset = startStructuredDocumentRegion.getTextEndOffset(region);
+ } else if (endStructuredDocumentRegion != null && endStructuredDocumentRegion.containsOffset(offset)) {
+ region = endStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+ regionTextEndOffset = endStructuredDocumentRegion.getTextEndOffset(region);
+ }
+
+ if (region != null && (region.getType() == XMLRegionContext.XML_TAG_NAME || region.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) && offset <= regionTextEndOffset)
+ proposals.add(new RenameInFileQuickAssistProposal());
+ }
+
+ protected ModelQuery getModelQuery(Node node) {
+ if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ return ModelQueryUtil.getModelQuery((Document) node);
+ } else {
+ return ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.correction.IQuickAssistProcessor#getProposals(org.eclipse.wst.sse.core.text.IStructuredDocument,
+ * int)
+ */
+ public ICompletionProposal[] getProposals(StructuredTextViewer viewer, int offset) throws CoreException {
+ ArrayList proposals = new ArrayList();
+
+ getLocalRenameQuickAssistProposal(proposals, viewer, offset);
+ getSurroundWithNewElementQuickAssistProposal(proposals, viewer, offset);
+ getInsertRequiredAttrs(proposals, viewer, offset);
+
+ return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
+ }
+
+ protected List getRequiredAttrs(Node node) {
+ List result = new ArrayList();
+
+ ModelQuery modelQuery = getModelQuery(node);
+ if (modelQuery != null) {
+ CMElementDeclaration elementDecl = modelQuery.getCMElementDeclaration((Element) node);
+ if (elementDecl != null) {
+ CMNamedNodeMap attrMap = elementDecl.getAttributes();
+ Iterator it = attrMap.iterator();
+ CMAttributeDeclaration attr = null;
+ while (it.hasNext()) {
+ attr = (CMAttributeDeclaration) it.next();
+ if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
+ result.add(attr);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * @param proposals
+ * @param viewer
+ * @param offset
+ */
+ protected void getSurroundWithNewElementQuickAssistProposal(ArrayList proposals, StructuredTextViewer viewer, int offset) {
+ XMLNode node = (XMLNode) ContentAssistUtils.getNodeAt(viewer, offset);
+ if (node != null)
+ proposals.add(new SurroundWithNewElementQuickAssistProposal());
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickFixProcessorXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickFixProcessorXML.java
new file mode 100644
index 0000000000..27444d8067
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/QuickFixProcessorXML.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.ui.internal.correction.IQuickFixProcessor;
+import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+
+public class QuickFixProcessorXML implements IQuickFixProcessor {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.correction.IQuickFixProcessor#canFix(int)
+ */
+ public boolean canFix(Annotation annotation) {
+ boolean result = false;
+
+ if (annotation instanceof TemporaryAnnotation) {
+ TemporaryAnnotation tempAnnotation = (TemporaryAnnotation) annotation;
+ int problemID = tempAnnotation.getProblemID();
+ switch (problemID) {
+ case ProblemIDsXML.EmptyTag :
+ case ProblemIDsXML.MissingEndTag :
+ case ProblemIDsXML.AttrsInEndTag :
+ case ProblemIDsXML.MissingAttrValue :
+ case ProblemIDsXML.NoAttrValue :
+ case ProblemIDsXML.SpacesBeforeTagName :
+ case ProblemIDsXML.SpacesBeforePI :
+ case ProblemIDsXML.NamespaceInPI :
+ case ProblemIDsXML.UnknownElement :
+ case ProblemIDsXML.UnknownAttr :
+ case ProblemIDsXML.InvalidAttrValue :
+ case ProblemIDsXML.MissingRequiredAttr :
+ case ProblemIDsXML.AttrValueNotQuoted :
+ case ProblemIDsXML.MissingClosingBracket :
+ result = true;
+ }
+ }
+
+ return result;
+ }
+
+ public Image getImage() {
+ //return
+ // JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
+ return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_CORRECTION_CHANGE);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.correction.IQuickFixProcessor#getProposals(org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation)
+ */
+ public ICompletionProposal[] getProposals(Annotation annotation) throws CoreException {
+ ArrayList proposals = new ArrayList();
+
+ if (annotation instanceof TemporaryAnnotation) {
+ TemporaryAnnotation tempAnnotation = (TemporaryAnnotation) annotation;
+ int problemID = tempAnnotation.getProblemID();
+ switch (problemID) {
+ case ProblemIDsXML.EmptyTag :
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.0"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ case ProblemIDsXML.MissingEndTag :
+ String tagName = (String) ((Object[]) tempAnnotation.getAdditionalFixInfo())[0];
+ String tagClose = (String) ((Object[]) tempAnnotation.getAdditionalFixInfo())[1];
+ int tagCloseOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[2]).intValue();
+ int startTagEndOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[3]).intValue();
+ int firstChildStartOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[4]).intValue();
+ int endOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[5]).intValue();
+ proposals.add(new CompletionProposal(tagClose, tagCloseOffset, 0, 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.1"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), startTagEndOffset - tempAnnotation.getPosition().getOffset(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.2"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ proposals.add(new CompletionProposal("</" + tagName + ">", firstChildStartOffset, 0, 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.3"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ proposals.add(new CompletionProposal("</" + tagName + ">", endOffset, 0, 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.4"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ break;
+ case ProblemIDsXML.AttrsInEndTag :
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.5"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ case ProblemIDsXML.MissingAttrValue :
+ String defaultAttrValue = (String) ((Object[]) tempAnnotation.getAdditionalFixInfo())[0];
+ int insertOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[1]).intValue();
+ proposals.add(new CompletionProposal("\"" + defaultAttrValue + "\"", tempAnnotation.getPosition().getOffset() + tempAnnotation.getPosition().getLength() + insertOffset, 0, defaultAttrValue.length() + 2, getImage(), ResourceHandler.getString("QuickFixProcessorXML.6"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.7"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ case ProblemIDsXML.NoAttrValue :
+ defaultAttrValue = (String) tempAnnotation.getAdditionalFixInfo();
+ proposals.add(new CompletionProposal("=\"" + defaultAttrValue + "\"", tempAnnotation.getPosition().getOffset() + tempAnnotation.getPosition().getLength(), 0, defaultAttrValue.length() + 3, getImage(), ResourceHandler.getString("QuickFixProcessorXML.6"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.7"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ case ProblemIDsXML.SpacesBeforeTagName :
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.8"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ case ProblemIDsXML.SpacesBeforePI :
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.9"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ case ProblemIDsXML.NamespaceInPI :
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.10"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ case ProblemIDsXML.UnknownElement :
+ proposals.add(new RemoveUnknownElementQuickFixProposal(tempAnnotation.getAdditionalFixInfo(), getImage(), ResourceHandler.getString("QuickFixProcessorXML.11"))); //$NON-NLS-1$
+ proposals.add(new RenameInFileQuickAssistProposal());
+ break;
+ case ProblemIDsXML.UnknownAttr :
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.7"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ proposals.add(new RenameInFileQuickAssistProposal());
+ break;
+ case ProblemIDsXML.InvalidAttrValue :
+ proposals.add(new CompletionProposal("", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), 0, getImage(), ResourceHandler.getString("QuickFixProcessorXML.12"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ break;
+ case ProblemIDsXML.MissingRequiredAttr :
+ String requiredAttr = (String) ((Object[]) tempAnnotation.getAdditionalFixInfo())[0];
+ insertOffset = ((Integer) ((Object[]) tempAnnotation.getAdditionalFixInfo())[1]).intValue();
+ proposals.add(new CompletionProposal(requiredAttr, tempAnnotation.getPosition().getOffset() + insertOffset, 0, requiredAttr.length(), getImage(), ResourceHandler.getString("QuickFixProcessorXML.13"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$
+ break;
+ case ProblemIDsXML.AttrValueNotQuoted :
+ String attrValue = (String) tempAnnotation.getAdditionalFixInfo();
+ proposals.add(new CompletionProposal("\"" + attrValue + "\"", tempAnnotation.getPosition().getOffset(), tempAnnotation.getPosition().getLength(), attrValue.length() + 2, getImage(), ResourceHandler.getString("QuickFixProcessorXML.14"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ break;
+ case ProblemIDsXML.MissingClosingBracket :
+ proposals.add(new CompletionProposal(">", tempAnnotation.getPosition().getOffset() + tempAnnotation.getPosition().getLength(), 0, 1, getImage(), ResourceHandler.getString("QuickFixProcessorXML.15"), null, "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ break;
+ }
+ }
+
+ return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RemoveUnknownElementQuickFixProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RemoveUnknownElementQuickFixProposal.java
new file mode 100644
index 0000000000..909b06a151
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RemoveUnknownElementQuickFixProposal.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+
+public class RemoveUnknownElementQuickFixProposal implements ICompletionProposal, ICompletionProposalExtension2 {
+ private Object fAdditionalFixInfo = null;
+ private String fDisplayString;
+ private Image fImage;
+ private Point fSelection; // initialized by apply()
+
+ /**
+ * @param additionalFixInfo
+ * @param image
+ * @param string
+ */
+ public RemoveUnknownElementQuickFixProposal(Object additionalFixInfo, Image image, String displayString) {
+ fAdditionalFixInfo = additionalFixInfo;
+ fImage = image;
+ fDisplayString = displayString;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
+ */
+ public void apply(IDocument document) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+ * char, int, int)
+ */
+ public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
+ int startTagOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[0]).intValue();
+ int startTagLength = ((Integer) ((Object[]) fAdditionalFixInfo)[1]).intValue();
+ int endTagOffset = ((Integer) ((Object[]) fAdditionalFixInfo)[2]).intValue();
+ int endTagLength = ((Integer) ((Object[]) fAdditionalFixInfo)[3]).intValue();
+
+ MultiTextEdit multiTextEdit = new MultiTextEdit();
+ if (endTagOffset != -1) {
+ multiTextEdit.addChild(new DeleteEdit(endTagOffset, endTagLength));
+ fSelection = new Point(endTagOffset, 0);
+ }
+ if (startTagOffset != -1) {
+ multiTextEdit.addChild(new DeleteEdit(startTagOffset, startTagLength));
+ fSelection = new Point(startTagOffset, 0);
+ }
+
+ try {
+ multiTextEdit.apply(viewer.getDocument());
+ } catch (MalformedTreeException e) {
+ throw new SourceEditingRuntimeException(e);
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
+ */
+ public IContextInformation getContextInformation() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ if (fDisplayString == null)
+ fDisplayString = ResourceHandler.getString("QuickFixProcessorXML.11"); //$NON-NLS-1$
+
+ return fDisplayString;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ return fImage;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
+ */
+ public Point getSelection(IDocument document) {
+ return fSelection;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
+ * boolean)
+ */
+ public void selected(ITextViewer viewer, boolean smartToggle) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
+ */
+ public void unselected(ITextViewer viewer) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
+ * int, org.eclipse.jface.text.DocumentEvent)
+ */
+ public boolean validate(IDocument document, int offset, DocumentEvent event) {
+ return false;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RenameInFileQuickAssistProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RenameInFileQuickAssistProposal.java
new file mode 100644
index 0000000000..c1e655f9f5
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/RenameInFileQuickAssistProposal.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.link.LinkedModeModel;
+import org.eclipse.jface.text.link.LinkedModeUI;
+import org.eclipse.jface.text.link.LinkedPosition;
+import org.eclipse.jface.text.link.LinkedPositionGroup;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+
+public class RenameInFileQuickAssistProposal implements ICompletionProposal, ICompletionProposalExtension2 {
+ protected IRegion fSelectedRegion; // initialized by apply()
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument)
+ */
+ public void apply(IDocument document) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+ * char, int, int)
+ */
+ public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
+ IDocument document = viewer.getDocument();
+ LinkedPositionGroup group = new LinkedPositionGroup();
+ try {
+ if (viewer instanceof StructuredTextViewer) {
+ XMLNode node = (XMLNode) ContentAssistUtils.getNodeAt((StructuredTextViewer) viewer, offset);
+ IStructuredDocumentRegion startStructuredDocumentRegion = node.getStartStructuredDocumentRegion();
+ ITextRegion region = (startStructuredDocumentRegion == null) ? null : startStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+ if (region != null) {
+ group.addPosition(new LinkedPosition(document, startStructuredDocumentRegion.getStartOffset() + region.getStart(), region.getTextLength(), 0));
+
+ if (region.getType() == XMLRegionContext.XML_TAG_NAME && node.getEndStructuredDocumentRegion() != null) {
+ region = node.getEndStructuredDocumentRegion().getRegions().get(1);
+ if (region != null)
+ group.addPosition(new LinkedPosition(document, node.getEndStructuredDocumentRegion().getStartOffset() + region.getStart(), region.getTextLength(), 1));
+ }
+ } else {
+ IStructuredDocumentRegion endStructuredDocumentRegion = node.getEndStructuredDocumentRegion();
+ region = (endStructuredDocumentRegion == null) ? null : endStructuredDocumentRegion.getRegionAtCharacterOffset(offset);
+ if (region != null) {
+ if (region.getType() == XMLRegionContext.XML_TAG_NAME && node.getStartStructuredDocumentRegion() != null) {
+ ITextRegion startTagNameRegion = node.getStartStructuredDocumentRegion().getRegions().get(1);
+ if (region != null) {
+ group.addPosition(new LinkedPosition(document, node.getStartStructuredDocumentRegion().getStartOffset() + startTagNameRegion.getStart(), startTagNameRegion.getTextLength(), 0));
+ group.addPosition(new LinkedPosition(document, endStructuredDocumentRegion.getStartOffset() + region.getStart(), region.getTextLength(), 1));
+ }
+ } else
+ group.addPosition(new LinkedPosition(document, endStructuredDocumentRegion.getStartOffset() + region.getStart(), region.getTextLength(), 0));
+ }
+ }
+
+ // TODO CompletionProposalPopup#insertProposal() calls
+ // IRewriteTarget.beginCompoundChange()
+ // which disables redraw in ITextViewer. Workaround for now.
+ ((StructuredTextViewer) viewer).setRedraw(true);
+ }
+
+ LinkedModeModel linkedModeModel = new LinkedModeModel();
+ linkedModeModel.addGroup(group);
+ linkedModeModel.forceInstall();
+
+ LinkedModeUI ui = new EditorLinkedModeUI(linkedModeModel, viewer);
+ ui.setExitPosition(viewer, offset, 0, LinkedPositionGroup.NO_STOP);
+ ui.enter();
+
+ fSelectedRegion = ui.getSelectedRegion();
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return ResourceHandler.getString("RenameInFileQuickAssistProposal.0"); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation()
+ */
+ public IContextInformation getContextInformation() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return ResourceHandler.getString("RenameInFileQuickAssistProposal.1"); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ // return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
+ return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_LOCAL_VARIABLE);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument)
+ */
+ public Point getSelection(IDocument document) {
+ return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer,
+ * boolean)
+ */
+ public void selected(ITextViewer viewer, boolean smartToggle) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer)
+ */
+ public void unselected(ITextViewer viewer) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument,
+ * int, org.eclipse.jface.text.DocumentEvent)
+ */
+ public boolean validate(IDocument document, int offset, DocumentEvent event) {
+ return false;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/SurroundWithNewElementQuickAssistProposal.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/SurroundWithNewElementQuickAssistProposal.java
new file mode 100644
index 0000000000..07dca4d9ef
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/correction/SurroundWithNewElementQuickAssistProposal.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.correction;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
+import org.eclipse.wst.sse.core.format.IStructuredFormatProcessor;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.format.FormatProcessorXML;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+import org.w3c.dom.Node;
+
+
+public class SurroundWithNewElementQuickAssistProposal extends RenameInFileQuickAssistProposal {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer,
+ * char, int, int)
+ */
+ public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
+ try {
+ int startTagOffset = offset;
+ int endTagOffset = offset + viewer.getSelectedRange().y;
+
+ // surround the node if no selection
+ if (startTagOffset == endTagOffset) {
+ XMLNode cursorNode = (XMLNode) ContentAssistUtils.getNodeAt((StructuredTextViewer) viewer, offset);
+ // use parent node if text node is empty
+ if (cursorNode.getNodeType() == Node.TEXT_NODE && cursorNode.getNodeValue().trim().length() == 0)
+ cursorNode = (XMLNode) cursorNode.getParentNode();
+
+ startTagOffset = cursorNode.getStartOffset();
+ endTagOffset = cursorNode.getEndOffset();
+ }
+
+ // insert new element
+ MultiTextEdit multiTextEdit = new MultiTextEdit();
+ // element tag name cannot be DBCS, do not translate "<element>"
+ // and "</element>"
+ multiTextEdit.addChild(new InsertEdit(startTagOffset, "<element>")); //$NON-NLS-1$
+ multiTextEdit.addChild(new InsertEdit(endTagOffset, "</element>")); //$NON-NLS-1$
+ multiTextEdit.apply(viewer.getDocument());
+
+ // get new element node
+ XMLNode newElementNode = (XMLNode) ContentAssistUtils.getNodeAt((StructuredTextViewer) viewer, startTagOffset);
+
+ // format new element
+ IStructuredFormatProcessor formatProcessor = new FormatProcessorXML();
+ formatProcessor.formatNode(newElementNode);
+
+ // rename new element
+ super.apply(viewer, trigger, stateMask, newElementNode.getStartOffset() + 1);
+ } catch (MalformedTreeException e) {
+ throw new SourceEditingRuntimeException(e);
+ } catch (BadLocationException e) {
+ throw new SourceEditingRuntimeException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo()
+ */
+ public String getAdditionalProposalInfo() {
+ return ResourceHandler.getString("SurroundWithNewElementQuickAssistProposal.0"); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString()
+ */
+ public String getDisplayString() {
+ return ResourceHandler.getString("SurroundWithNewElementQuickAssistProposal.1"); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage()
+ */
+ public Image getImage() {
+ // return JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
+ return XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_ADD_CORRECTION);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/IHelpContextIds.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/IHelpContextIds.java
new file mode 100644
index 0000000000..e4c41c4826
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/IHelpContextIds.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.editor;
+
+import org.eclipse.wst.xml.ui.XMLEditorPlugin;
+
+/**
+ * Help context ids for the XML Source Editor.
+ * <p>
+ * This interface contains constants only; it is not intended to be
+ * implemented.
+ * </p>
+ *
+ */
+public interface IHelpContextIds {
+ // org.eclipse.wst.xml.ui.
+ public static final String PREFIX = XMLEditorPlugin.ID + "."; //$NON-NLS-1$
+
+ // XML Source page editor
+ public static final String XML_SOURCEVIEW_HELPID = PREFIX + "exml0000"; //$NON-NLS-1$
+
+ // XML Files Preference page
+ public static final String XML_PREFWEBX_FILES_HELPID = PREFIX + "webx0060"; //$NON-NLS-1$
+ // XML Source Preference page
+ public static final String XML_PREFWEBX_SOURCE_HELPID = PREFIX + "webx0061"; //$NON-NLS-1$
+ // XML Styles Preference page
+ public static final String XML_PREFWEBX_STYLES_HELPID = PREFIX + "webx0062"; //$NON-NLS-1$
+ // XML Templates Preference page
+ public static final String XML_PREFWEBX_TEMPLATES_HELPID = PREFIX + "webx0063"; //$NON-NLS-1$
+
+ // XML Cleanup dialog
+ public static final String CLEANUP_XML_HELPID = PREFIX + "xmlm1200"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImageHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImageHelper.java
new file mode 100644
index 0000000000..4fe20d3b42
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImageHelper.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.editor;
+
+import java.util.HashMap;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.xml.ui.XMLEditorPlugin;
+
+
+/**
+ * Helper class to handle images provided by this plug-in.
+ *
+ * NOTE: For internal use only. For images used externally, please use the
+ * Shared***ImageHelper class instead.
+ *
+ * @author amywu
+ */
+public class XMLEditorPluginImageHelper {
+ private static XMLEditorPluginImageHelper instance = null;
+
+ /**
+ * Gets the instance.
+ *
+ * @return Returns a XMLEditorPluginImageHelper
+ */
+ public synchronized static XMLEditorPluginImageHelper getInstance() {
+ if (instance == null)
+ instance = new XMLEditorPluginImageHelper();
+ return instance;
+ }
+
+ // save a descriptor for each image
+ private HashMap fImageDescRegistry = null;
+ private final String PLUGINID = XMLEditorPlugin.ID;
+
+ /**
+ * Creates an image from the given resource and adds the image to the
+ * image registry.
+ *
+ * @param resource
+ * @return Image
+ */
+ private Image createImage(String resource) {
+ ImageDescriptor desc = getImageDescriptor(resource);
+ Image image = null;
+
+ if (desc != null) {
+ image = desc.createImage();
+ // dont add the missing image descriptor image to the image
+ // registry
+ if (!desc.equals(ImageDescriptor.getMissingImageDescriptor()))
+ getImageRegistry().put(resource, image);
+ }
+ return image;
+ }
+
+ /**
+ * Creates an image descriptor from the given imageFilePath and adds the
+ * image descriptor to the image descriptor registry. If an image
+ * descriptor could not be created, the default "missing" image descriptor
+ * is returned but not added to the image descriptor registry.
+ *
+ * @param imageFilePath
+ * @return ImageDescriptor image descriptor for imageFilePath or default
+ * "missing" image descriptor if resource could not be found
+ */
+ private ImageDescriptor createImageDescriptor(String imageFilePath) {
+ ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(PLUGINID, imageFilePath);
+ if (imageDescriptor != null) {
+ getImageDescriptorRegistry().put(imageFilePath, imageDescriptor);
+ } else {
+ imageDescriptor = ImageDescriptor.getMissingImageDescriptor();
+ }
+
+ return imageDescriptor;
+ }
+
+ /**
+ * Retrieves the image associated with resource from the image registry.
+ * If the image cannot be retrieved, attempt to find and load the image at
+ * the location specified in resource.
+ *
+ * @param resource
+ * the image to retrieve
+ * @return Image the image associated with resource or null if one could
+ * not be found
+ */
+ public Image getImage(String resource) {
+ Image image = getImageRegistry().get(resource);
+ if (image == null) {
+ // create an image
+ image = createImage(resource);
+ }
+ return image;
+ }
+
+ /**
+ * Retrieves the image descriptor associated with resource from the image
+ * descriptor registry. If the image descriptor cannot be retrieved,
+ * attempt to find and load the image descriptor at the location specified
+ * in resource.
+ *
+ * @param resource
+ * the image descriptor to retrieve
+ * @return ImageDescriptor the image descriptor assocated with resource or
+ * the default "missing" image descriptor if one could not be
+ * found
+ */
+ public ImageDescriptor getImageDescriptor(String resource) {
+ ImageDescriptor imageDescriptor = null;
+ Object o = getImageDescriptorRegistry().get(resource);
+ if (o == null) {
+ //create a descriptor
+ imageDescriptor = createImageDescriptor(resource);
+ } else {
+ imageDescriptor = (ImageDescriptor) o;
+ }
+ return imageDescriptor;
+ }
+
+ /**
+ * Returns the image descriptor registry for this plugin.
+ *
+ * @return HashMap - image descriptor registry for this plugin
+ */
+ private HashMap getImageDescriptorRegistry() {
+ if (fImageDescRegistry == null)
+ fImageDescRegistry = new HashMap();
+ return fImageDescRegistry;
+ }
+
+ /**
+ * Returns the image registry for this plugin.
+ *
+ * @return ImageRegistry - image registry for this plugin
+ */
+ private ImageRegistry getImageRegistry() {
+ return JFaceResources.getImageRegistry();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java
new file mode 100644
index 0000000000..8160f7781c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/editor/XMLEditorPluginImages.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.editor;
+
+/**
+ * Bundle of most images used by the XML Source Editor plug-in.
+ */
+public class XMLEditorPluginImages {
+
+ public static final String IMG_DTOOL_CONSTRAINOFF = "icons/full/dtool16/constrainoff.gif"; //$NON-NLS-1$
+ public static final String IMG_DTOOL_CONSTRAINON = "icons/full/dtool16/constrainon.gif"; //$NON-NLS-1$
+ public static final String IMG_DTOOL_RLDGRMR = "icons/full/dtool16/rldgrmr.gif"; //$NON-NLS-1$
+ public static final String IMG_DTOOL_VALIDATE = "icons/full/dtool16/validate.gif"; //$NON-NLS-1$
+ public static final String IMG_ETOOL_CONSTRAINOFF = "icons/full/etool16/constrainoff.gif"; //$NON-NLS-1$
+ public static final String IMG_ETOOL_CONSTRAINON = "icons/full/etool16/constrainon.gif"; //$NON-NLS-1$
+ public static final String IMG_ETOOL_RLDGRMR = "icons/full/etool16/rldgrmr.gif"; //$NON-NLS-1$
+ public static final String IMG_ETOOL_VALIDATE = "icons/full/etool16/validate.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_ADD_CORRECTION = "icons/full/obj16/add_correction.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_ATT_REQ_OBJ = "icons/full/obj16/att_req_obj.gif"; //$NON-NLS-1$
+
+ public static final String IMG_OBJ_ATTRIBUTE = "icons/full/obj16/attribute_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_CDATASECTION = "icons/full/obj16/cdatasection.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_COMMENT = "icons/full/obj16/comment_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_CORRECTION_CHANGE = "icons/full/obj16/correction_change.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_DOCTYPE = "icons/full/obj16/doctype.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_DTDFILE = "icons/full/obj16/dtdfile.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_ELEMENT = "icons/full/obj16/element_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_ENTITY = "icons/full/obj16/entity.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_ENTITY_REFERENCE = "icons/full/obj16/entity_reference.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_ENUM = "icons/full/obj16/enum.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_LOCAL_VARIABLE = "icons/full/obj16/localvariable_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_NOTATION = "icons/full/obj16/notation.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_PROCESSINGINSTRUCTION = "icons/full/obj16/proinst_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_TAG_GENERIC = "icons/full/obj16/tag-generic.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_TAG_MACRO = "icons/full/obj16/tag-macro.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_TXTEXT = "icons/full/obj16/text.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_WARNING_OBJ = "icons/full/obj16/warning_obj.gif"; //$NON-NLS-1$
+ public static final String IMG_OBJ_XSDFILE = "icons/full/obj16/XSDFile.gif"; //$NON-NLS-1$
+
+ public static final String IMG_OVR_ERROR = "icons/full/ovr16/error_ovr.gif"; //$NON-NLS-1$
+ public static final String IMG_OVR_STALE_ERROR = "icons/full/ovr16/stale_error_ovr.gif"; //$NON-NLS-1$
+ public static final String IMG_OVR_WARN = "icons/full/ovr16/warn_ovr.gif"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesAction.java
new file mode 100644
index 0000000000..825eb9ae8d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/search/XMLFindOccurrencesAction.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.internal.search;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.ui.internal.search.BasicFindOccurrencesAction;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.eclipse.wst.xml.core.text.rules.StructuredTextPartitionerForXML;
+
+
+
+/**
+ * <p>
+ * Configures a BasicFindOccurrencesAction with XML partitions and regions
+ * </p>
+ *
+ * <p>
+ * Uses default <code>getSearchQuery()</code>.
+ * </p>
+ *
+ * @author pavery
+ */
+public class XMLFindOccurrencesAction extends BasicFindOccurrencesAction {
+
+ public XMLFindOccurrencesAction(ResourceBundle bundle, String prefix, ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.internal.search.BasicFindOccurrencesAction#getPartitionType()
+ */
+ public String[] getPartitionTypes() {
+
+ return new String[]{StructuredTextPartitionerForXML.ST_DEFAULT_XML};
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.internal.search.IFindOccurrencesAction#getRegionTypes()
+ */
+ public String[] getRegionTypes() {
+
+ return new String[]{XMLRegionContext.XML_TAG_NAME, XMLRegionContext.XML_TAG_ATTRIBUTE_NAME, XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE};
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nls/ResourceHandler.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nls/ResourceHandler.java
new file mode 100644
index 0000000000..a34ab91a25
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nls/ResourceHandler.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.nls;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class ResourceHandler {
+
+
+ private static ResourceBundle fgResourceBundle;
+
+ /**
+ * Returns the resource bundle used by all classes in this Project
+ */
+ public static ResourceBundle getResourceBundle() {
+ try {
+ return ResourceBundle.getBundle("EditingXML");//$NON-NLS-1$
+ } catch (MissingResourceException e) {
+ // does nothing - this method will return null and
+ // getString(String) will return the key
+ // it was called with
+ }
+ return null;
+ }
+
+ public static String getString(String key) {
+ if (fgResourceBundle == null) {
+ fgResourceBundle = getResourceBundle();
+ }
+
+ if (fgResourceBundle != null) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$//$NON-NLS-1$
+ }
+ } else {
+ return "!" + key + "!";//$NON-NLS-2$//$NON-NLS-1$
+ }
+ }
+
+ public static String getString(String key, Object[] args) {
+
+ try {
+ return MessageFormat.format(getString(key), args);
+ } catch (IllegalArgumentException e) {
+ return getString(key);
+ }
+
+ }
+
+ public static String getString(String key, Object[] args, int x) {
+
+ return getString(key);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonAddNamespacesControl.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonAddNamespacesControl.java
new file mode 100644
index 0000000000..be8c926e31
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonAddNamespacesControl.java
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.nsedit;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.wst.common.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.dialogs.SelectFileOrXMLCatalogIdDialog;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+import org.eclipse.wst.xml.uriresolver.util.IdResolver;
+import org.eclipse.wst.xml.uriresolver.util.IdResolverImpl;
+import org.eclipse.wst.xml.uriresolver.util.URIHelper;
+
+
+
+public class CommonAddNamespacesControl extends Composite implements SelectionListener {
+
+ class EditNamespaceControl extends Composite {
+ protected Button browseButton;
+ Text locationHintField;
+ Text prefixField;
+ Text uriField;
+
+ //protected NamespaceInfo info;
+
+ public EditNamespaceControl(Composite parent) {
+ super(parent, SWT.NONE); //BORDER);
+ setLayout(new GridLayout());
+ setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label label = new Label(this, SWT.NONE);
+ label.setText(XMLCommonResources.getInstance().getString("_UI_ENTER_REQ_PREFIX_AND_NAMESPACE")); //$NON-NLS-1$
+
+ Composite composite = new Composite(this, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.marginWidth = 0;
+ layout.verticalSpacing = 1;
+ composite.setLayout(layout);
+
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 350;
+ composite.setLayoutData(gd);
+
+ // row 1
+ //
+ Label prefixLabel = new Label(composite, SWT.NONE);
+ prefixLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_PREFIX_COLON")); //$NON-NLS-1$
+
+ prefixField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ prefixField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ //prefixField.setText(getDisplayValue(info.prefix));
+ //prefixField.addModifyListener(modifyListener);
+ //prefixField.setEnabled(info.getProperty("prefix-readOnly") ==
+ // null);
+ Label placeHolder1 = new Label(composite, SWT.NONE);
+
+ // row 2
+ //
+ Label uriLabel = new Label(composite, SWT.NONE);
+ uriLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_NAMESPACE_NAME_COLON")); //$NON-NLS-1$
+
+ uriField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ uriField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ //uriField.setText(getDisplayValue(info.uri));
+ //uriField.addModifyListener(modifyListener);
+ //uriField.setEnabled(info.getProperty("uri-readOnly") == null);
+
+ Label placeHolder2 = new Label(composite, SWT.NONE);
+
+ // row 3
+ //
+ Label locationHintLabel = new Label(composite, SWT.NONE);
+ locationHintLabel.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_LOCATION_HINT_COLON")); //$NON-NLS-1$
+
+ locationHintField = new Text(composite, SWT.SINGLE | SWT.BORDER);
+ locationHintField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ //locationHintField.setText(getDisplayValue(info.locationHint));
+ //locationHintField.addModifyListener(modifyListener);
+ //locationHintField.setEnabled(info.getProperty("locationHint-readOnly")
+ // == null);
+
+ SelectionListener selectionListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ performBrowse();
+ }
+ };
+
+ browseButton = new Button(composite, SWT.NONE);
+ browseButton.setText(XMLCommonResources.getInstance().getString("_UI_LABEL_BROWSE")); //$NON-NLS-1$
+ browseButton.addSelectionListener(selectionListener);
+ browseButton.setEnabled(locationHintField.getEnabled());
+ }
+
+ protected void performBrowse() {
+ String[] extensions = {".xsd"}; //$NON-NLS-1$
+ SelectFileOrXMLCatalogIdDialog dialog = new SelectFileOrXMLCatalogIdDialog(getShell(), extensions);
+ dialog.create();
+ dialog.getShell().setText(XMLCommonResources.getInstance().getString("_UI_LABEL_SELECT_FILE")); //$NON-NLS-1$
+ dialog.setBlockOnOpen(true);
+ dialog.open();
+
+ if (dialog.getReturnCode() == Window.OK) {
+ String grammarURI = null;
+ IFile file = dialog.getFile();
+ String id = dialog.getId();
+ if (file != null) {
+ String uri = null;
+ if (resourceLocation != null) {
+ uri = URIHelper.getRelativeURI(file.getLocation(), resourceLocation);
+ grammarURI = file.getLocation().toOSString();
+ } else {
+ uri = file.getLocation().toOSString();
+ grammarURI = uri;
+ }
+ locationHintField.setText(uri);
+ } else if (id != null) {
+ locationHintField.setText(id);
+ IdResolver resolver = new IdResolverImpl(null);
+ grammarURI = resolver.resolveId(id, id);
+ }
+
+ try {
+ //TODO CMDocument document =
+ // CMDocumentBuilderRegistry.getInstance().buildCMDocument(grammarURI);
+ // List namespaceInfoList =
+ // (List)document.getProperty("http://com.ibm.etools/cm/properties/namespaceInfo");
+ // NamespaceInfo info =
+ // (NamespaceInfo)namespaceInfoList.get(0);
+ // if (uriField.getText().trim().length() == 0 && info.uri
+ // != null)
+ // {
+ // uriField.setText(info.uri);
+ // }
+ // if (prefixField.getText().trim().length() == 0 &&
+ // info.prefix != null)
+ // {
+ // prefixField.setText(info.prefix);
+ // }
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+ protected Button deleteButton;
+ protected Button editButton;
+ protected EditNamespaceControl editNamespaceControl;
+ protected int heightHint = 250;
+ protected List namespaceInfoList = new ArrayList();
+ protected Button newButton;
+ protected PageBook pageBook;
+ protected Button radio1;
+ protected Button radio2;
+ protected IPath resourceLocation;
+ protected Composite tableSection;
+ protected CommonNamespaceInfoTable tableViewer;
+ protected int widthHint = 500;
+
+
+ public CommonAddNamespacesControl(Composite parent, int style, IPath resourceLocation) {
+ super(parent, style);
+ this.resourceLocation = resourceLocation;
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ if (widthHint != -1) {
+ gd.widthHint = widthHint;
+ }
+ if (heightHint != -1) {
+ gd.heightHint = heightHint;
+ }
+ setLayoutData(gd);
+ setLayout(new GridLayout());
+
+ radio1 = new Button(this, SWT.RADIO);
+ radio1.setText(XMLCommonResources.getInstance().getString("_UI_SELECT_REGISTERED_NAMESPACES")); //$NON-NLS-1$
+ radio1.addSelectionListener(this);
+
+ radio2 = new Button(this, SWT.RADIO);
+ radio2.setText(XMLCommonResources.getInstance().getString("_UI_SPECIFY_NEW_NAMESPACE")); //$NON-NLS-1$
+ radio2.addSelectionListener(this);
+
+ Label separator = new Label(this, SWT.SEPARATOR | SWT.HORIZONTAL);
+ separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ //Group namespaceInfoGroup = new Group(this, SWT.NONE);
+ //namespaceInfoGroup.setText("Namespace Declarations");
+ // //XMLCommonUIPlugin.getInstance().getString("_UI_LABEL_XML_SCHEMA_INFORMATION"));
+ //namespaceInfoGroup.setLayout(new GridLayout(2, false));
+ //namespaceInfoGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+ pageBook = new PageBook(this, SWT.NONE);
+ pageBook.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ tableSection = new Composite(pageBook, SWT.NONE);
+ tableSection.setLayout(new GridLayout());
+ Label label = new Label(tableSection, SWT.NONE);
+ label.setText(XMLCommonResources.getInstance().getString("_UI_SELECT_NAMESPACE_TO_ADD")); //$NON-NLS-1$
+
+ tableViewer = new CommonNamespaceInfoTable(tableSection, SWT.CHECK, 6);
+ editNamespaceControl = new EditNamespaceControl(pageBook);
+ pageBook.showPage(tableSection);
+
+ tableViewer.setInput(namespaceInfoList);
+ }
+
+
+
+ public List getNamespaceInfoList() {
+ List list = new ArrayList();
+ if (radio1.getSelection()) {
+ TableItem[] items = tableViewer.getTable().getItems();
+ for (int i = 0; i < items.length; i++) {
+ TableItem item = items[i];
+ if (item.getChecked()) {
+ list.add(item.getData());
+ }
+ }
+ } else {
+ NamespaceInfo info = new NamespaceInfo();
+ info.prefix = editNamespaceControl.prefixField.getText();
+ info.uri = editNamespaceControl.uriField.getText();
+ info.locationHint = editNamespaceControl.locationHintField.getText();
+ list.add(info);
+ }
+ return list;
+ }
+
+ public void setNamespaceInfoList(List list) {
+ namespaceInfoList = list;
+ tableViewer.setInput(namespaceInfoList);
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ if (e.widget == radio1) {
+ pageBook.showPage(tableSection);
+ } else if (e.widget == radio2) {
+ pageBook.showPage(editNamespaceControl);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonAddNamespacesDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonAddNamespacesDialog.java
new file mode 100644
index 0000000000..a1ba50f0cb
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonAddNamespacesDialog.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.nsedit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.common.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.uriresolver.XMLCatalog;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogEntry;
+import org.eclipse.wst.xml.uriresolver.XMLCatalogPlugin;
+
+
+public class CommonAddNamespacesDialog extends Dialog {
+ protected CommonAddNamespacesControl addNamespacesControl;
+ protected List existingNamespaces;
+ protected List namespaceInfoList;
+ protected Button okButton;
+ protected HashMap preferredPrefixTable = new HashMap();
+ protected IPath resourceLocation;
+ protected String title;
+
+ public CommonAddNamespacesDialog(Shell parentShell, String title, IPath resourceLocation, List existingNamespaces) {
+ super(parentShell);
+ this.resourceLocation = resourceLocation;
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ this.title = title;
+ this.existingNamespaces = existingNamespaces;
+ preferredPrefixTable.put("http://schemas.xmlsoap.org/wsdl/", "wsdl"); //$NON-NLS-1$ //$NON-NLS-2$
+ preferredPrefixTable.put("http://schemas.xmlsoap.org/wsdl/soap/", "soap"); //$NON-NLS-1$ //$NON-NLS-2$
+ preferredPrefixTable.put("http://schemas.xmlsoap.org/wsdl/http/", "http"); //$NON-NLS-1$ //$NON-NLS-2$
+ preferredPrefixTable.put("http://schemas.xmlsoap.org/wsdl/mime/", "mime"); //$NON-NLS-1$ //$NON-NLS-2$
+ preferredPrefixTable.put("http://schemas.xmlsoap.org/soap/encoding/", "soapenc"); //$NON-NLS-1$ //$NON-NLS-2$
+ preferredPrefixTable.put("http://schemas.xmlsoap.org/soap/envelope/", "soapenv"); //$NON-NLS-1$ //$NON-NLS-2$
+ preferredPrefixTable.put("http://www.w3.org/2001/XMLSchema-instance", "xsi"); //$NON-NLS-1$ //$NON-NLS-2$
+ preferredPrefixTable.put("http://www.w3.org/2001/XMLSchema", "xsd"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected void addBuiltInNamespaces(List list) {
+ String xsiNamespace = "http://www.w3.org/2001/XMLSchema-instance"; //$NON-NLS-1$
+ String xsdNamespace = "http://www.w3.org/2001/XMLSchema"; //$NON-NLS-1$
+ if (!isAlreadyDeclared(xsiNamespace)) {
+ list.add(new NamespaceInfo("http://www.w3.org/2001/XMLSchema-instance", "xsi", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (!isAlreadyDeclared(xsdNamespace)) {
+ list.add(new NamespaceInfo("http://www.w3.org/2001/XMLSchema", "xsd", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ protected void addCatalogMapToList(XMLCatalog catalog, List list) {
+ for (Iterator i = catalog.getEntries().iterator(); i.hasNext();) {
+ XMLCatalogEntry entry = (XMLCatalogEntry) i.next();
+ if (entry.getType() == XMLCatalogEntry.PUBLIC && entry.getURI().endsWith(".xsd")) { //$NON-NLS-1$
+ if (!isAlreadyDeclared(entry.getKey())) {
+ NamespaceInfo namespaceInfo = new NamespaceInfo(entry.getKey(), "xx", null); //$NON-NLS-1$
+ list.add(namespaceInfo);
+ }
+ }
+ }
+ }
+
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.OK_ID) {
+ namespaceInfoList = addNamespacesControl.getNamespaceInfoList();
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ public void computeAddablePrefixes(List addableList, List exisitingList) {
+ HashMap map = new HashMap();
+ for (Iterator i = exisitingList.iterator(); i.hasNext();) {
+ NamespaceInfo info = (NamespaceInfo) i.next();
+ if (info.prefix != null) {
+ map.put(info.prefix, info);
+ }
+ }
+ for (Iterator i = addableList.iterator(); i.hasNext();) {
+ NamespaceInfo info = (NamespaceInfo) i.next();
+ if (info.uri != null) {
+ String prefix = (String) preferredPrefixTable.get(info.uri);
+ info.prefix = getUniquePrefix(map, prefix, info.uri);
+ map.put(info.prefix, info);
+ }
+ }
+ }
+
+ public int createAndOpen() {
+ create();
+ getShell().setText(title);
+ Rectangle r = getShell().getBounds();
+ getShell().setBounds(r.x + 80, r.y + 80, r.width, r.height);
+ setBlockOnOpen(true);
+ return open();
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ return control;
+ }
+
+
+
+ protected Control createDialogArea(Composite parent) {
+ Composite dialogArea = (Composite) super.createDialogArea(parent);
+ addNamespacesControl = new CommonAddNamespacesControl(dialogArea, SWT.NONE, resourceLocation);
+ List list = new ArrayList();
+
+ addBuiltInNamespaces(list);
+ XMLCatalog catalog = XMLCatalogPlugin.getInstance().getDefaultXMLCatalog();
+ addCatalogMapToList(catalog.getChildCatalog(XMLCatalog.USER_CATALOG_ID), list);
+ addCatalogMapToList(catalog.getChildCatalog(XMLCatalog.SYSTEM_CATALOG_ID), list);
+
+ computeAddablePrefixes(list, existingNamespaces);
+
+ addNamespacesControl.setNamespaceInfoList(list);
+ return dialogArea;
+ }
+
+ public List getNamespaceInfoList() {
+ return namespaceInfoList;
+ }
+
+ protected String getPreferredPrefix(String namespaceURI) {
+ return (String) preferredPrefixTable.get(namespaceURI);
+ }
+
+ private String getUniquePrefix(HashMap prefixMap, String prefix, String uri) {
+ if (prefix == null) {
+ int lastIndex = uri.lastIndexOf('/');
+ if (lastIndex == uri.length() - 1) {
+ uri = uri.substring(0, lastIndex);
+ lastIndex = uri.lastIndexOf('/');
+ }
+ prefix = uri.substring(lastIndex + 1);
+ if (prefix.length() > 20 || prefix.indexOf(':') != -1) {
+ prefix = null;
+ }
+ }
+ if (prefix == null) {
+ prefix = "p"; //$NON-NLS-1$
+ }
+ if (prefixMap.get(prefix) != null) {
+ String base = prefix;
+ for (int count = 0; prefixMap.get(prefix) != null; count++) {
+ prefix = base + count;
+ }
+ }
+ return prefix;
+ }
+
+ protected boolean isAlreadyDeclared(String namespaceURI) {
+ boolean result = false;
+ for (Iterator i = existingNamespaces.iterator(); i.hasNext();) {
+ NamespaceInfo namespaceInfo = (NamespaceInfo) i.next();
+ if (namespaceURI.equals(namespaceInfo.uri)) {
+ result = true;
+ break;
+ }
+ }
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonEditNamespacesDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonEditNamespacesDialog.java
new file mode 100644
index 0000000000..179566735a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonEditNamespacesDialog.java
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.nsedit;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.common.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.dialogs.EditNamespaceInfoDialog;
+import org.eclipse.wst.xml.ui.dialogs.NamespaceInfoErrorHelper;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+
+
+public class CommonEditNamespacesDialog {
+ protected Composite commonComposite;
+ protected Button deleteButton;
+ protected Button editButton;
+
+ protected Label errorMessageLabel;
+ protected int heightHint = 250;
+ protected List namespaceInfoList = new ArrayList();
+
+ protected Button newButton;
+ protected IPath resourceLocation;
+
+ private boolean showLocationText = false;
+ protected String tableLabel = ""; //$NON-NLS-1$
+ protected CommonNamespaceInfoTable tableViewer;
+
+ protected Composite topComposite;
+ protected boolean useGroup;
+ protected int widthHint = 500;
+
+ public CommonEditNamespacesDialog(Composite parent, IPath resourceLocation, String stringTableLabel) {
+ this(parent, resourceLocation, stringTableLabel, false, false);
+ }
+
+ public CommonEditNamespacesDialog(Composite parent, IPath resourceLocation, String stringTableLabel, boolean useGroup, boolean showLocText) {
+ this.resourceLocation = resourceLocation;
+ tableLabel = stringTableLabel;
+ this.useGroup = useGroup;
+ showLocationText = showLocText;
+
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ if (widthHint != -1) {
+ gd.widthHint = widthHint;
+ }
+ if (heightHint != -1) {
+ gd.heightHint = heightHint;
+ }
+
+ // Set GridData and GridLayout for the parent Composite
+ parent.setLayoutData(gd);
+ parent.setLayout(new GridLayout());
+
+ // Create the top Composite
+ topComposite = new Composite(parent, SWT.NONE);
+ GridData topData = new GridData(GridData.FILL_HORIZONTAL);
+ topData.heightHint = 0;
+ topComposite.setLayoutData(topData);
+ topComposite.setLayout(new GridLayout());
+
+ // Create the 'common'/middle Composite
+ if (useGroup) {
+ commonComposite = new Group(parent, SWT.NONE);
+ } else {
+ commonComposite = new Composite(parent, SWT.NONE);
+ }
+ commonComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ commonComposite.setLayout(new GridLayout(3, false));
+
+ // Add the error Message Label
+ errorMessageLabel = new Label(parent, SWT.NONE);
+ errorMessageLabel.setLayoutData(createHorizontalFill());
+ Color color = new Color(errorMessageLabel.getDisplay(), 200, 0, 0);
+ errorMessageLabel.setForeground(color);
+
+ createControlArea();
+ }
+
+
+ protected void createButtons(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayoutData(new GridData(GridData.FILL_VERTICAL));
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ gridLayout.marginHeight = 0;
+ gridLayout.marginWidth = 0;
+ composite.setLayout(gridLayout);
+
+ SelectionListener selectionListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if (e.widget == newButton) {
+ performNew();
+ } else if (e.widget == editButton) {
+ performEdit();
+ } else if (e.widget == deleteButton) {
+ performDelete();
+ }
+ }
+ };
+
+ // create a composite to hold the three buttons
+ Composite buttonComposite = new Composite(composite, SWT.NONE);
+ buttonComposite.setLayoutData(createHorizontalFill());
+ GridLayout buttonGridLayout = new GridLayout();
+ //buttonGridLayout.numColumns = 3;
+ //buttonGridLayout.makeColumnsEqualWidth = true;
+ buttonComposite.setLayout(buttonGridLayout);
+
+ // add the New button
+ //
+ newButton = new Button(buttonComposite, SWT.NONE);
+ //newButton.setText(" " +
+ // XMLCommonUIPlugin.getInstance().getString("_UI_BUTTON_NEW") + " ");
+ newButton.setText(" " + ResourceHandler.getString("CommonEditNamespacesDialog.0") + " "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ newButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); //ViewUtility.createHorizontalFill());
+ newButton.addSelectionListener(selectionListener);
+
+ // add the Edit button
+ //
+ //gd = new GridData();
+ //gd.horizontalAlignment = gd.FILL;
+ //gd.grabExcessHorizontalSpace = true;
+
+ editButton = new Button(buttonComposite, SWT.NONE);
+ editButton.setText(XMLCommonResources.getInstance().getString("_UI_BUTTON_EDIT")); //$NON-NLS-1$
+ editButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); //ViewUtility.createHorizontalFill());
+ editButton.addSelectionListener(selectionListener);
+
+ // add the Delete button
+ //
+ //gd = new GridData();
+ //gd.horizontalAlignment = gd.FILL;
+ //gd.grabExcessHorizontalSpace = true;
+
+ deleteButton = new Button(buttonComposite, SWT.NONE);
+ deleteButton.setText(XMLCommonResources.getInstance().getString("_UI_BUTTON_DELETE")); //$NON-NLS-1$
+ deleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); //ViewUtility.createHorizontalFill());
+ deleteButton.addSelectionListener(selectionListener);
+ }
+
+ private void createControlArea() {
+ if (useGroup) {
+ ((Group) commonComposite).setText(tableLabel);
+ } else {
+ Label label = new Label(commonComposite, SWT.NONE);
+ label.setText(tableLabel);
+ label.setLayoutData(createGridData(false, 3));
+ }
+
+ tableViewer = new CommonNamespaceInfoTable(commonComposite, 6, showLocationText);
+ tableViewer.getControl().setLayoutData(createGridData(true, 2));
+ createButtons(commonComposite);
+
+ tableViewer.setInput(namespaceInfoList);
+ updateButtonEnabledState();
+ ISelectionChangedListener selectionChangedListener = new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateButtonEnabledState();
+ }
+ };
+ tableViewer.addSelectionChangedListener(selectionChangedListener);
+ }
+
+ protected GridData createGridData(boolean both, int span) {
+ GridData gd = new GridData(both ? GridData.FILL_BOTH : GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ return gd;
+ }
+
+ private GridData createHorizontalFill() {
+ GridData gd = new GridData();
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = true;
+ return gd;
+ }
+
+
+
+ public NamespaceInfo getNamespaceInfo(String namespace) {
+ NamespaceInfo result = null;
+ for (Iterator i = namespaceInfoList.iterator(); i.hasNext();) {
+ NamespaceInfo info = (NamespaceInfo) i.next();
+ if (info.uri != null && info.uri.equals(namespace)) {
+ result = info;
+ break;
+ }
+ }
+ return result;
+ }
+
+ protected Object getSelection(ISelection selection) {
+ if (selection == null) {
+ return null;
+ } // end of if ()
+
+ Object result = null;
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection es = (IStructuredSelection) selection;
+ Iterator i = es.iterator();
+ if (i.hasNext()) {
+ result = i.next();
+ }
+ }
+ return result;
+ }
+
+ /*
+ * Use the returned Composite to add content above the 'common contents'.
+ * Note: The GridData for the returned Composite has a heightHint = 0.
+ * This means when using the returned Composite, the GridData must be
+ * reset, else the Composite and it's contents will not appear.
+ */
+ protected Composite getTopComposite() {
+ return topComposite;
+ }
+
+ protected EditNamespaceInfoDialog invokeDialog(String title, NamespaceInfo info) {
+ Shell shell = XMLCommonResources.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+ EditNamespaceInfoDialog dialog = new EditNamespaceInfoDialog(shell, info);
+ dialog.create();
+ dialog.getShell().setText(title);
+ dialog.setBlockOnOpen(true);
+ dialog.setResourceLocation(resourceLocation);
+ dialog.open();
+ return dialog;
+ }
+
+ protected void performDelayedUpdate() {
+ tableViewer.refresh();
+ /*
+ * Runnable delayedUpdate = new Runnable() { public void run() {
+ * tableViewer.refresh(); } };
+ * Display.getCurrent().asyncExec(delayedUpdate);
+ */
+ //if (updateListener != null)
+ //{
+ // updateListener.updateOccured(this, namespaceInfoList);
+ //}
+ }
+
+ public void performDelete() {
+ ISelection selection = tableViewer.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ namespaceInfoList.removeAll(structuredSelection.toList());
+ updateErrorMessage(namespaceInfoList);
+ performDelayedUpdate();
+ }
+ }
+
+ public void performEdit() {
+ Object selection = getSelection(tableViewer.getSelection());
+ if (selection != null) {
+ EditNamespaceInfoDialog dialog = invokeDialog(XMLCommonResources.getInstance().getString("_UI_LABEL_NEW_NAMESPACE_INFORMATION"), (NamespaceInfo) selection); //$NON-NLS-1$
+ updateErrorMessage(namespaceInfoList);
+ performDelayedUpdate();
+ }
+ }
+
+ public void performNew() {
+ Shell shell = XMLCommonResources.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+ CommonAddNamespacesDialog dialog = new CommonAddNamespacesDialog(shell, XMLCommonResources.getInstance().getString("_UI_ADD_NAMESPACE_DECLARATIONS"), resourceLocation, namespaceInfoList); //$NON-NLS-1$
+ dialog.createAndOpen();
+ if (dialog.getReturnCode() == Window.OK) {
+ namespaceInfoList.addAll(dialog.getNamespaceInfoList());
+ updateErrorMessage(namespaceInfoList);
+ performDelayedUpdate();
+ }
+ }
+
+ public void setNamespaceInfoList(List list) {
+ namespaceInfoList = list;
+ tableViewer.setInput(namespaceInfoList);
+ }
+
+ public void updateButtonEnabledState() {
+ Object selection = getSelection(tableViewer.getSelection());
+ NamespaceInfo info = (NamespaceInfo) selection;
+ editButton.setEnabled(info != null);
+ deleteButton.setEnabled(info != null && info.getProperty("unremovable") == null); //$NON-NLS-1$
+ }
+
+ public void updateErrorMessage(List namespaceInfoList) {
+ NamespaceInfoErrorHelper helper = new NamespaceInfoErrorHelper();
+ String errorMessage = helper.computeErrorMessage(namespaceInfoList, null);
+ errorMessageLabel.setText(errorMessage != null ? errorMessage : ""); //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonEditNamespacesTargetFieldDialog.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonEditNamespacesTargetFieldDialog.java
new file mode 100644
index 0000000000..27546a5a6f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonEditNamespacesTargetFieldDialog.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.nsedit;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.common.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.dialogs.EditNamespaceInfoDialog;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+
+
+/*
+ * This class is an extension of CommonEditNamespacesDialog. This class adds
+ * the target namespaces dialog field.
+ */
+public class CommonEditNamespacesTargetFieldDialog extends CommonEditNamespacesDialog {
+
+ class TargetNamespaceModifyListener implements ModifyListener {
+ public void modifyText(ModifyEvent e) {
+ String oldTargetNamespace = targetNamespace;
+ targetNamespace = targetNamespaceField.getText();
+ updateTargetNamespaceAndNamespaceInfo(oldTargetNamespace, targetNamespace);
+ }
+ }
+
+ protected String targetNamespace;
+ protected Text targetNamespaceField;
+
+ public CommonEditNamespacesTargetFieldDialog(Composite parent, IPath resourceLocation) {
+ super(parent, resourceLocation, XMLCommonResources.getInstance().getString("_UI_NAMESPACE_DECLARATIONS")); //$NON-NLS-1$
+
+ Composite targetComp = getTopComposite();
+ targetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ Label targetNamespaceLabel = new Label(targetComp, SWT.NONE);
+ targetNamespaceLabel.setLayoutData(gd);
+ targetNamespaceLabel.setText(XMLCommonResources.getInstance().getString("_UI_TARGET_NAMESPACE")); //$NON-NLS-1$
+
+ targetNamespaceField = new Text(targetComp, SWT.BORDER);
+ targetNamespaceField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ targetNamespaceField.addModifyListener(new TargetNamespaceModifyListener());
+
+ // createControlArea();
+ }
+
+ public String getTargetNamespace() {
+ return targetNamespace;
+ }
+
+ public void performEdit() {
+ Object selection = getSelection(tableViewer.getSelection());
+ if (selection != null) {
+ boolean editTargetNamespace = false;
+ NamespaceInfo nsInfo = (NamespaceInfo) selection;
+ if (getTargetNamespace().equals(nsInfo.uri)) {
+ editTargetNamespace = true;
+ }
+
+ EditNamespaceInfoDialog dialog = invokeDialog(XMLCommonResources.getInstance().getString("_UI_LABEL_NEW_NAMESPACE_INFORMATION"), nsInfo); //$NON-NLS-1$
+ updateErrorMessage(namespaceInfoList);
+ performDelayedUpdate();
+
+ if (editTargetNamespace) {
+ targetNamespaceField.setText(nsInfo.uri);
+ }
+ }
+ }
+
+ public void setTargetNamespace(String theTargetNamespace) {
+ targetNamespace = theTargetNamespace != null ? theTargetNamespace : ""; //$NON-NLS-1$
+ targetNamespaceField.setText(targetNamespace);
+ //updateTargetNamespaceAndNamespaceInfo(targetNamespace);
+ }
+
+ private void updateTargetNamespaceAndNamespaceInfo(String oldTargetNamespace, String newTargetNamespace) {
+ NamespaceInfo info = getNamespaceInfo(newTargetNamespace);
+ if (info == null) {
+ info = getNamespaceInfo(oldTargetNamespace);
+ if (info == null) {
+ info = new NamespaceInfo(newTargetNamespace, "tns", null); //$NON-NLS-1$
+ namespaceInfoList.add(info);
+ } else {
+ info.uri = targetNamespace;
+ }
+ }
+ tableViewer.refresh();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonNamespaceInfoTable.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonNamespaceInfoTable.java
new file mode 100644
index 0000000000..ae58de57b4
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/nsedit/CommonNamespaceInfoTable.java
@@ -0,0 +1,341 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.nsedit;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.wst.common.contentmodel.util.NamespaceInfo;
+import org.eclipse.wst.xml.ui.util.XMLCommonResources;
+
+
+public class CommonNamespaceInfoTable extends TableViewer {
+
+ /**
+ * NamespaceInfoTableLabelProvider
+ */
+ protected class Provider extends LabelProvider implements ITableLabelProvider, IStructuredContentProvider {
+ Viewer viewer;
+
+ public Image getColumnImage(Object object, int columnIndex) {
+ Image result = null;
+ int columnCode = getColumnCode(columnIndex);
+ if (columnCode == COLUMN_LOCATION_HINT) {
+ NamespaceInfo info = (NamespaceInfo) object;
+ if (info.locationHint == null || info.locationHint.trim().equals("")) { //$NON-NLS-1$
+ // Comment this out until we solve the alignment/(space
+ // for image being allocated
+ // to prefix column) ......
+ // result =
+ // XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_WARNING_OBJ);
+ }
+ }
+
+ return result;
+ }
+
+ public String getColumnText(Object object, int column) {
+ NamespaceInfo info = (NamespaceInfo) object;
+ String result = null;
+ int columnCode = getColumnCode(column);
+ switch (columnCode) {
+ case COLUMN_PREFIX : {
+ result = info.prefix;
+ break;
+ }
+ case COLUMN_NAMESPACE_URI : {
+ result = info.uri;
+ break;
+ }
+ case COLUMN_CHECKBOX : {
+ result = ""; //info.locationHint; //$NON-NLS-1$
+ break;
+ }
+ case COLUMN_LOCATION_HINT : {
+ result = info.locationHint;
+ break;
+ }
+ }
+ result = result != null ? result : ""; //$NON-NLS-1$
+ if (result.equals("")) { //$NON-NLS-1$
+ switch (columnCode) {
+ case COLUMN_PREFIX : {
+ result = XMLCommonResources.getInstance().getString("_UI_NO_PREFIX"); //$NON-NLS-1$
+ break;
+ }
+ case COLUMN_NAMESPACE_URI : {
+ result = XMLCommonResources.getInstance().getString("_UI_NO_NAMESPACE_NAME"); //$NON-NLS-1$
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ public Object[] getElements(Object inputElement) {
+ List list = (List) viewer.getInput();
+ return list != null ? list.toArray() : null;
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ this.viewer = viewer;
+ }
+ }
+
+ class TableItemChecker extends MouseAdapter {
+ public void mouseDown(MouseEvent e) {
+ TableItem item = getTable().getItem(new Point(e.x, e.y));
+ if (item != null) {
+ Object obj = item.getData();
+ if (obj != null) {
+ NamespaceInfo info = (NamespaceInfo) obj;
+ TableColumn col = getTable().getColumn(0);
+ if (e.x < col.getWidth()) // if the point falls within the
+ // Select column then perform
+ // check/uncheck
+ {
+ String currentState = (String) info.getProperty("checked"); //$NON-NLS-1$
+ System.out.println("currentState" + currentState); //$NON-NLS-1$
+ if (currentState == null || currentState.equals("false")) //$NON-NLS-1$
+ {
+ info.setProperty("checked", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ info.setProperty("checked", "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ refresh();
+ }
+ }
+ }
+ }
+ }
+
+ protected static final int COLUMN_CHECKBOX = 1;
+ protected static final int COLUMN_LOCATION_HINT = 4;
+ protected static final int COLUMN_NAMESPACE_URI = 2;
+ protected static final int COLUMN_PREFIX = 3;
+
+ protected static final String LABEL_CHECKBOX = ""; //$NON-NLS-1$
+ protected static final String LABEL_LOCATION_HINT = XMLCommonResources.getInstance().getString("_UI_LABEL_LOCATION_HINT"); //$NON-NLS-1$
+ protected static final String LABEL_NAMESPACE_URI = XMLCommonResources.getInstance().getString("_UI_LABEL_NAMESPACE_NAME"); //$NON-NLS-1$
+ protected static final String LABEL_PREFIX = XMLCommonResources.getInstance().getString("_UI_LABEL_PREFIX"); //$NON-NLS-1$
+ protected List checkedList = new ArrayList();
+
+ //protected List namespaceInfoList = new ArrayList();
+ protected int[] columnIndexMap;
+ protected boolean showCheckBoxes = true;
+ private boolean showLocationText = false;
+
+ private Table table;
+ protected int visibleRows = -1;
+
+ public CommonNamespaceInfoTable(Composite parent, int visibleRows) {
+ this(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER, visibleRows, false);
+ }
+
+ //protected CellEditor getCellEditor(int column)
+ // {
+ // return (column == COLUMN_CHECKBOX) ? checkBoxCellEditor :
+ // textCellEditor;
+ // }
+
+ public CommonNamespaceInfoTable(Composite parent, int visibleRows, boolean showLocationText) {
+ this(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER, visibleRows, showLocationText);
+ }
+
+ public CommonNamespaceInfoTable(Composite parent, int style, int visibleRows) {
+ this(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER | style, visibleRows, false);
+ }
+
+ public CommonNamespaceInfoTable(Composite parent, int style, int visibleRows, boolean showLocationText) {
+ super(new Table(parent, style));
+ getTable().setLinesVisible(true);
+ this.showCheckBoxes = (style & SWT.CHECK) != 0;
+ columnIndexMap = createColumnIndexMap();
+ this.showLocationText = showLocationText;
+
+ Provider provider = new Provider();
+ setContentProvider(provider);
+ setLabelProvider(provider);
+
+ String[] columnPropertiesArray = createColumnPropertiesArray();
+ setColumnProperties(columnPropertiesArray);
+
+ table = getTable();
+ table.setHeaderVisible(true);
+ table.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ TableLayout layout = new TableLayout();
+
+ for (int i = 0; i < columnPropertiesArray.length; i++) {
+ TableColumn column = new TableColumn(table, i);
+ if ((columnPropertiesArray[i]).equals(LABEL_LOCATION_HINT)) {
+ if (showLocationText) {
+ column.setText(columnPropertiesArray[i]);
+ } else {
+ // Comment this out until we solve the alignment/(space
+ // for image being allocated
+ // to prefix column) ......
+ // column.setImage(XMLEditorPluginImageHelper.getInstance().getImage(XMLEditorPluginImages.IMG_OBJ_TXTEXT));
+ }
+ } else {
+ column.setText(columnPropertiesArray[i]);
+ }
+ column.setAlignment(SWT.LEFT);
+ layout.addColumnData(new ColumnWeightData(getColumnWidth(i), true));
+ }
+ table.setLayout(layout);
+
+ this.visibleRows = visibleRows;
+ //for (int i = 0; i < visibleRows; i++)
+ // {
+ // TableItem item = new TableItem(table, SWT.NONE);
+ // item.setText("#######");
+ //}
+ //checkBoxCellEditor = new NamespaceInfoCheckboxCellEditor(table);
+ //textCellEditor = new TextCellEditor(table);
+
+ /*
+ * CellEditor[] cellEditors = new
+ * CellEditor[columnPropertiesArray.length]; for (int i = 0; i <
+ * columnPropertiesArray.length; i++) { cellEditors[i] =
+ * getCellEditor(i); } setCellEditors(cellEditors);
+ */
+ //if (showCheckBoxes)
+ //{
+ // getTable().addMouseListener(new TableItemChecker());
+ //}
+ }
+
+ //protected CellEditor checkBoxCellEditor;
+ //protected CellEditor textCellEditor;
+
+ protected int[] createColumnIndexMap() {
+ int[] result = new int[showCheckBoxes ? 4 : 3];
+ int i = 0;
+ if (showCheckBoxes) {
+ result[i++] = COLUMN_CHECKBOX;
+ }
+ result[i++] = COLUMN_PREFIX;
+ result[i++] = COLUMN_NAMESPACE_URI;
+ if (!showCheckBoxes) {
+ result[i++] = COLUMN_LOCATION_HINT;
+ }
+ return result;
+ }
+
+ protected String[] createColumnPropertiesArray() {
+ String[] result = new String[3];
+ int i = 0;
+ if (showCheckBoxes) {
+ result[i++] = LABEL_CHECKBOX;
+ }
+ result[i++] = LABEL_PREFIX;
+ result[i++] = LABEL_NAMESPACE_URI;
+ if (!showCheckBoxes) {
+ result[i++] = LABEL_LOCATION_HINT;
+ }
+ return result;
+ }
+
+ protected int getColumnCode(int column) {
+ int result = 0;
+ if (column < columnIndexMap.length) {
+ result = columnIndexMap[column];
+ }
+ return result;
+ }
+
+ protected int getColumnWidth(int column) {
+ int result = 0;
+ switch (getColumnCode(column)) {
+ case COLUMN_PREFIX : {
+ result = 5;
+ break;
+ }
+ case COLUMN_NAMESPACE_URI : {
+ // Size columns differently when location hint text label is
+ // displayed
+ if (showLocationText) {
+ result = 10;
+ } else {
+ result = 20;
+ }
+ break;
+ }
+ case COLUMN_CHECKBOX : {
+ result = 1; //info.locationHint;
+ break;
+ }
+ case COLUMN_LOCATION_HINT : {
+ // Size columns differently when location hint text label is
+ // displayed
+ if (showLocationText) {
+ result = 10;
+ } else {
+ result = 2;
+ }
+ break;
+ }
+ }
+ return result;
+ }
+ /*
+ * protected class NamespaceInfoCellModifier implements ICellModifier {
+ * public NamespaceInfoCellModifier() { }
+ *
+ * public boolean canModify(Object element, String property) { if
+ * (property.equals(LABEL_CHECKBOX)) { return true; } else if
+ * (property.equals(LABEL_PREFIX)) { return true; } return false; }
+ *
+ * public Object getValue(Object element, String property) { int column =
+ * 0; if (property.equals(LABEL_CHECKBOX)) { column = 0; } else if
+ * (property.equals(LABEL_PREFIX)) { column = 1; } else if
+ * (property.equals(LABEL_NAMESPACE_URI)) { column = 2; }
+ *
+ * //if (element instanceof TableElement) //{ // return
+ * provider.getColumnText(element, column); //} //else //{ // return null; // }
+ * return "hello"; }
+ *
+ * public void modify(Object element, String property, Object value) { } }
+ *
+ * protected class NamespaceInfoCheckboxCellEditor extends
+ * CheckboxCellEditor implements MouseListener { public
+ * NamespaceInfoCheckboxCellEditor(Composite parent) { super(parent); }
+ *
+ * protected void doSetValue(Object value) { }
+ *
+ * public void activate() { super.activate(); deactivate();
+ * Display.getCurrent().getFocusControl().redraw(); }
+ *
+ * public void mouseDown(MouseEvent e) { if (getTable().getItem(new
+ * Point(e.x, e.y)) != null) { } } public void mouseDoubleClick(MouseEvent
+ * e) { } public void mouseUp(MouseEvent e) { } }
+ */
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/openon/DefaultOpenOnXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/openon/DefaultOpenOnXML.java
new file mode 100644
index 0000000000..878d044eda
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/openon/DefaultOpenOnXML.java
@@ -0,0 +1,342 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.openon;
+
+
+
+import java.util.StringTokenizer;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMDataType;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.sse.ui.openon.AbstractOpenOn;
+import org.eclipse.wst.uriresolver.URIResolverPlugin;
+import org.eclipse.wst.xml.core.document.XMLAttr;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+/**
+ * This action class retrieves the link/file selected by the cursor and
+ * attempts to open the link/file in the default editor or web browser
+ */
+public class DefaultOpenOnXML extends AbstractOpenOn {
+ private final String NO_NAMESPACE_SCHEMA_LOCATION = "noNamespaceSchemaLocation"; //$NON-NLS-1$
+ private final String SCHEMA_LOCATION = "schemaLocation"; //$NON-NLS-1$
+ private final String XMLNS = "xmlns"; //$NON-NLS-1$
+ private final String XSI_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance"; //$NON-NLS-1$
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.AbstractOpenOn#doGetOpenOnRegion(int)
+ */
+ protected IRegion doGetOpenOnRegion(int offset) {
+ // find the element for this node
+ Node currNode = getCurrentNode(offset);
+ if (currNode != null) {
+ // handle doc type node
+ if (currNode.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ XMLNode docNode = (XMLNode) currNode;
+ return new Region(docNode.getStartOffset(), docNode.getEndOffset());
+ }
+
+ Attr linkableAtt = getLinkableAttrFromNode(currNode, offset);
+ // found attribute to open on
+ if (linkableAtt != null) {
+ XMLAttr att = (XMLAttr) linkableAtt;
+ // do not include quotes in attribute value region
+ int regOffset = att.getValueRegionStartOffset();
+ int regLength = att.getValueRegion().getTextLength();
+ String attValue = att.getValueRegionText();
+ if (StringUtils.isQuoted(attValue)) {
+ regOffset = ++regOffset;
+ regLength = regLength - 2;
+ }
+ return new Region(regOffset, regLength);
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.AbstractOpenOn#doOpenOn(org.eclipse.jface.text.IRegion)
+ */
+ protected void doOpenOn(IRegion region) {
+ String uriString = getURIString(region.getOffset());
+ openFileInEditor(uriString);
+ }
+
+ /**
+ * Get the base location from the current model
+ *
+ * @return
+ */
+ protected String getBaseLocation() {
+ String baseLoc = null;
+
+ // get the base location from the current model
+ IStructuredModel sModel = null;
+ try {
+ sModel = getModelManager().getExistingModelForRead(getDocument());
+ if (sModel != null) {
+ baseLoc = sModel.getBaseLocation();
+ }
+ } finally {
+ if (sModel != null) {
+ sModel.releaseFromRead();
+ }
+ }
+ return baseLoc;
+ }
+
+ /**
+ * Returns the attribute node within node at offset
+ *
+ * @param node
+ * @param offset
+ * @return Node
+ */
+ private Node getCurrentAttrNode(Node node, int offset) {
+ if ((node instanceof IndexedRegion) && ((IndexedRegion) node).contains(offset) && (node.hasAttributes())) {
+ NamedNodeMap attrs = node.getAttributes();
+ // go through each attribute in node and if attribute contains
+ // offset, return that attribute
+ for (int i = 0; i < attrs.getLength(); ++i) {
+ // assumption that if parent node is of type IndexedRegion,
+ // then its attributes will also be of type IndexedRegion
+ IndexedRegion attRegion = (IndexedRegion) attrs.item(i);
+ if (attRegion.contains(offset)) {
+ return attrs.item(i);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the node the cursor is currently on in the document. null if no
+ * node is selected
+ *
+ * @param offset
+ * @return Node
+ */
+ protected Node getCurrentNode(int offset) {
+ // get the current node at the offset (returns element, doctype, text)
+ IndexedRegion inode = null;
+ IStructuredModel sModel = getModelManager().getExistingModelForRead(getDocument());
+ inode = sModel.getIndexedRegion(offset);
+ if (inode == null)
+ inode = sModel.getIndexedRegion(offset - 1);
+ sModel.releaseFromRead();
+
+ if (inode instanceof Node) {
+ return (Node) inode;
+ }
+ return null;
+ }
+
+ /**
+ * Return an attr of element that is "openOn-able" if one exists. null
+ * otherwise
+ *
+ * @param element -
+ * cannot be null
+ * @return Attr attribute that can be used for open on, null if no
+ * attribute could be found
+ */
+ protected Attr getLinkableAttr(Element element) {
+ ModelQuery mq = ModelQueryUtil.getModelQuery(element.getOwnerDocument());
+ if (mq != null) {
+ // get the list of attributes for this node
+ NamedNodeMap attrs = element.getAttributes();
+ for (int i = 0; i < attrs.getLength(); ++i) {
+ // check if this attribute is "openOn-able"
+ Attr att = (Attr) attrs.item(i);
+ if (isLinkableAttr(att, mq)) {
+ return att;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return an attr of element that is "openOn-able" if one exists. null
+ * otherwise
+ *
+ * @param node -
+ * cannot be null
+ * @return Attr attribute that can be used for open on, null if no
+ * attribute could be found
+ */
+ protected Attr getLinkableAttrFromNode(Node node, int offset) {
+ // check to see if we're already on an attribute we can work with
+ Attr currentAtt = null;
+ if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ currentAtt = (Attr) node;
+ } else {
+ Node attN = getCurrentAttrNode(node, offset);
+ if (attN != null)
+ currentAtt = (Attr) attN;
+ }
+ if ((currentAtt != null) && isLinkableAttr(currentAtt, null)) {
+ return currentAtt;
+ }
+
+ // now check the whole element tag and see if there's an attribute we
+ // can work with
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ // find an attribute that is "openOn-able"
+ return getLinkableAttr((Element) node);
+ }
+ return null;
+ }
+
+ /**
+ * Find the location hint for the given namespaceURI if it exists
+ *
+ * @param elementNode -
+ * cannot be null
+ * @param namespaceURI -
+ * cannot be null
+ * @return location hint (systemId) if it was found, null otherwise
+ */
+ private String getLocationHint(Element elementNode, String namespaceURI) {
+ Attr schemaLocNode = elementNode.getAttributeNodeNS(XSI_NAMESPACE_URI, SCHEMA_LOCATION);
+ if (schemaLocNode != null) {
+ StringTokenizer st = new StringTokenizer(schemaLocNode.getValue());
+ while (st.hasMoreTokens()) {
+ String publicId = st.hasMoreTokens() ? st.nextToken() : null;
+ String systemId = st.hasMoreTokens() ? st.nextToken() : null;
+ // found location hint
+ if (namespaceURI.equalsIgnoreCase(publicId))
+ return systemId;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the URI string
+ *
+ * @param offset
+ * @return
+ */
+ protected String getURIString(int offset) {
+ Node currNode = getCurrentNode(offset);
+ if (currNode != null) {
+ // need the base location, publicId, and systemId for URIResolver
+ String baseLoc = null;
+ String publicId = null;
+ String systemId = null;
+
+ // handle doc type node
+ if (currNode.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ baseLoc = getBaseLocation();
+ publicId = ((DocumentType) currNode).getPublicId();
+ systemId = ((DocumentType) currNode).getSystemId();
+ } else { // handle all other types of nodes
+ Attr linkableAtt = getLinkableAttrFromNode(currNode, offset);
+ // found attribute to open on
+ if (linkableAtt != null) {
+ baseLoc = getBaseLocation();
+ String attrName = linkableAtt.getName();
+ String attrValue = linkableAtt.getValue();
+ attrValue = StringUtils.strip(attrValue);
+
+ // handle schemaLocation attribute
+ String prefix = DOMNamespaceHelper.getPrefix(attrName);
+ String unprefixedName = DOMNamespaceHelper.getUnprefixedName(attrName);
+ if ((XMLNS.equals(prefix)) || (XMLNS.equals(unprefixedName))) {
+ publicId = attrValue;
+ systemId = getLocationHint(linkableAtt.getOwnerElement(), publicId);
+ } else if ((XSI_NAMESPACE_URI.equals(DOMNamespaceHelper.getNamespaceURI(linkableAtt))) && (unprefixedName.equals("schemaLocation"))) { //$NON-NLS-1$
+ // for now just use the first pair
+ // need to look into being more precise
+ StringTokenizer st = new StringTokenizer(attrValue);
+ publicId = st.hasMoreTokens() ? st.nextToken() : null;
+ systemId = st.hasMoreTokens() ? st.nextToken() : null;
+ // else check if xmlns publicId = value
+ } else {
+ systemId = attrValue;
+ }
+ }
+ }
+
+ String resolvedURI = resolveURI(baseLoc, publicId, systemId);
+ return resolvedURI;
+ }
+ return null;
+ }
+
+ /**
+ * Checks to see if the given attribute is openOn-able. Attribute is
+ * openOn-able if it is a namespace declaration attribute or if the
+ * attribute value is of type URI.
+ *
+ * @param attr
+ * cannot be null
+ * @param query
+ * ModelQuery associated with the attribute (can be null)
+ * @return true if this attribute is "openOn-able" false otherwise
+ */
+ protected boolean isLinkableAttr(Attr attr, ModelQuery query) {
+ String prefix = DOMNamespaceHelper.getPrefix(attr.getName());
+ String unprefixedName = DOMNamespaceHelper.getUnprefixedName(attr.getName());
+ // determine if attribute is namespace declaration
+ if ((XMLNS.equals(prefix)) || (XMLNS.equals(unprefixedName)))
+ return true;
+
+ // determine if attribute contains schema location
+ if ((XSI_NAMESPACE_URI.equals(DOMNamespaceHelper.getNamespaceURI(attr))) && ((SCHEMA_LOCATION.equals(unprefixedName)) || (NO_NAMESPACE_SCHEMA_LOCATION.equals(unprefixedName))))
+ return true;
+
+ // determine if attribute value is of type URI
+ if (query != null) {
+ CMAttributeDeclaration attrDecl = query.getCMAttributeDeclaration(attr);
+ if ((attrDecl != null) && (attrDecl.getAttrType() != null) && (CMDataType.URI.equals(attrDecl.getAttrType().getDataTypeName()))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Resolves the given URI information
+ *
+ * @param baseLocation
+ * @param publicId
+ * @param systemId
+ * @return String resolved uri.
+ */
+ protected String resolveURI(String baseLocation, String publicId, String systemId) {
+ // dont resolve if there's nothing to resolve
+ if ((baseLocation == null) && (publicId == null) && (systemId == null))
+ return null;
+ return URIResolverPlugin.createResolver().resolve(baseLocation, publicId, systemId);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/EncodingSettings.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/EncodingSettings.java
new file mode 100644
index 0000000000..1582d29c70
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/EncodingSettings.java
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.preferences;
+
+import java.util.Vector;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wst.common.encoding.CommonCharsetNames;
+import org.eclipse.wst.sse.ui.Logger;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+
+/**
+ * EncodingSettings is a composite that can be used to display the set of
+ * encoding values that are available to the user. The list of encoding values
+ * is based off the SupportedJavaEncoding class. As the user selects an
+ * encoding from the combo box, the readonly field below it changes to show
+ * the IANA tag for that particular encoding description. The labels for the
+ * widgets are configurable and the initial value to display to the user can
+ * be set using the setIANATag(). The currently selected entry's IANA tag can
+ * be retrieved with getIANATag(). Entries displayed to the user can be added
+ * and removed.
+ */
+public class EncodingSettings extends Composite {
+
+ private class ComboListener implements ModifyListener {
+ public void modifyText(ModifyEvent e) {
+ int i = encodingCombo.getSelectionIndex();
+ if (i >= 0 && i < ianaVector.size())
+ ianaText.setText((String) (ianaVector.elementAt(encodingCombo.getSelectionIndex())));
+ }
+ }
+
+ private static String ENCODING_LABEL = ResourceHandler.getString("EncodingSettings.1"); //$NON-NLS-1$
+
+ private static String IANA_LABEL = ResourceHandler.getString("EncodingSettings.0"); //$NON-NLS-1$
+
+ private ModifyListener comboListener = new ComboListener();
+ protected Combo encodingCombo;
+ protected Label encodingLabel, ianaLabel;
+ protected Text ianaText;
+ protected Vector ianaVector;
+
+ /**
+ * Method EncodingSettings.
+ *
+ * @param parent
+ */
+ public EncodingSettings(Composite parent) {
+ super(parent, SWT.NONE);
+ init(IANA_LABEL, ENCODING_LABEL);
+ }
+
+ /**
+ * Method EncodingSettings.
+ *
+ * @param parent
+ * @param encodingLabel -
+ * text label to use beside the locale sensitive description of
+ * the currently selected encoding
+ */
+ public EncodingSettings(Composite parent, String encodingLabel) {
+ super(parent, SWT.NONE);
+ init(IANA_LABEL, encodingLabel);
+ }
+
+ /**
+ * Method EncodingSettings.
+ *
+ * @param parent
+ * @param ianaLabel =
+ * text label to use beside the display only IANA field
+ * @param encodingLabel -
+ * text label to use beside the locale sensitive description of
+ * the currently selected encoding
+ */
+ public EncodingSettings(Composite parent, String ianaLabel, String encodingLabel) {
+ super(parent, SWT.NONE);
+ init(ianaLabel, encodingLabel);
+ }
+
+ /**
+ * Method addEntry. Add an entry to the end of the Encoding Combobox
+ *
+ * @param description -
+ * encoding description to display
+ * @param ianaTag -
+ * IANA tag for the description
+ */
+ public void addEntry(String description, String ianaTag) {
+ encodingCombo.add(description);
+ ianaVector.add(ianaTag);
+ }
+
+ /**
+ * Method addEntry. Add an entry to the Encoding Combobox at index index
+ *
+ * @param description -
+ * encoding description to display
+ * @param ianaTag -
+ * IANA tag for the description
+ * @param index -
+ * index into the combo to add to
+ */
+ public void addEntry(String description, String ianaTag, int index) {
+ if (index == ianaVector.size()) {
+ // just add to the end
+ addEntry(description, ianaTag);
+ return;
+ }
+
+ if (0 <= index && index < ianaVector.size()) {
+ encodingCombo.add(description, index);
+ ianaVector.add(index, ianaTag);
+ }
+ }
+
+ protected Combo createComboBox(Composite parent, boolean isReadOnly) {
+ int style = isReadOnly == true ? SWT.READ_ONLY : SWT.DROP_DOWN;
+
+ Combo combo = new Combo(parent, style);
+
+ GridData data = new GridData();
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ combo.setLayoutData(data);
+ return combo;
+ }
+
+ /**
+ * Helper method for creating labels.
+ */
+ protected Label createLabel(Composite parent, String text) {
+ Label label = new Label(parent, SWT.LEFT);
+ label.setText(text);
+
+ GridData data = new GridData();
+ data.horizontalAlignment = GridData.FILL;
+ label.setLayoutData(data);
+ return label;
+ }
+
+ protected Text createTextField(Composite parent, int width) {
+ Text text = new Text(parent, SWT.SINGLE | SWT.READ_ONLY);
+
+ GridData data = new GridData();
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ data.widthHint = width;
+ text.setLayoutData(data);
+
+ return text;
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets.Widget#dispose()
+ */
+ public void dispose() {
+ encodingCombo.removeModifyListener(comboListener);
+ super.dispose();
+ }
+
+ private void fillCombo() {
+ try {
+ String[] ianaTags = CommonCharsetNames.getCommonCharsetNames();
+ int totalNum = ianaTags.length;
+ for (int i = 0; i < totalNum; i++) {
+ String iana = ianaTags[i];
+ String enc = CommonCharsetNames.getDisplayString(iana);
+
+ if (enc != null) {
+ encodingCombo.add(enc);
+ } else {
+ Logger.log(Logger.WARNING, "CommonCharsetNames.getDisplayString(" + iana + ") returned null"); //$NON-NLS-1$ //$NON-NLS-2$
+ encodingCombo.add(iana);
+ }
+ ianaVector.add(iana);
+ }
+ } catch (Exception e) {
+ //e.printStackTrace();
+ //MessageDialog.openError(getShell(), "Resource exception",
+ // "Unable to obtain encoding strings. Check resource file");
+ //XMLEncodingPlugin.getPlugin().getMsgLogger().write(e.toString());
+ //XMLEncodingPlugin.getPlugin().getMsgLogger().writeCurrentThread();
+ Logger.log(Logger.ERROR, "Exception", e); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * <code>getEncoding</code> Get the descriptive encoding name that was
+ * selected.
+ *
+ * @return a <code>String</code> value
+ */
+ public String getEncoding() {
+ return encodingCombo.getText();
+ }
+
+ /**
+ * Method getEncodingCombo. Returns the combo used to display the encoding
+ * descriptions.
+ *
+ * @return Combo
+ */
+ public Combo getEncodingCombo() {
+ return encodingCombo;
+ }
+
+ /**
+ * <code>getIANATag</code> Get the IANA tag equivalent of the selected
+ * descriptive encoding name
+ *
+ * @return a <code>String</code> value
+ */
+ public String getIANATag() {
+ int i = encodingCombo.getSelectionIndex();
+ if (i >= 0) {
+ return (String) (ianaVector.elementAt(i));
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ protected void init(String ianaLabelStr, String encodingLabelStr) {
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ setLayout(layout);
+ GridData data = new GridData();
+ data.verticalAlignment = GridData.FILL;
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ setLayoutData(data);
+
+ encodingLabel = createLabel(this, encodingLabelStr);
+ encodingCombo = createComboBox(this, true);
+ ianaLabel = createLabel(this, ianaLabelStr);
+ ianaText = createTextField(this, 20);
+ ianaVector = new Vector();
+
+ fillCombo();
+ resetToDefaultEncoding();
+ encodingCombo.addModifyListener(comboListener);
+ }
+
+ /**
+ * <code>isEncodingInList</code> Checks whether the encoding name is in
+ * the combo
+ *
+ * @param enc
+ * a <code>string</code> value. The encoding name.
+ * @return a <code>boolean</code> value. TRUE if encoding is in list.
+ * FALSE if encoding is not in list.
+ */
+ public boolean isEncodingInList(String enc) {
+ int i = encodingCombo.indexOf(enc);
+ if (i >= 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <code>isIANATagInList</code> Checks whether the IANA tag is in the
+ * combo
+ *
+ * @param ianaTag
+ * a <code>string</code> value. The IANA tag.
+ * @return a <code>boolean</code> value. TRUE if tag is in list. FALSE
+ * if tag is not in list.
+ */
+ public boolean isIANATagInList(String ianaTag) {
+ int i = ianaVector.indexOf(ianaTag);
+ if (i >= 0) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Method removeEntry. Removes both the description and the IANA tag at
+ * the specified index
+ *
+ * @param index
+ */
+ public void removeEntry(int index) {
+ if (0 <= index && index < ianaVector.size()) {
+ encodingCombo.remove(index);
+ ianaVector.remove(index);
+ }
+ }
+
+ /**
+ * Method resetToDefaultEncoding. Reset the control to the default
+ * encoding. Currently UTF-8
+ */
+ public void resetToDefaultEncoding() {
+ String defaultIANATag = "UTF-8"; //$NON-NLS-1$
+ ianaText.setText(defaultIANATag);
+ setIANATag(defaultIANATag);
+ }
+
+ /**
+ * Method setEnabled. Enable/disable the EncodingSettings composite.
+ *
+ * @param enabled
+ */
+ public void setEnabled(boolean enabled) {
+ encodingCombo.setEnabled(enabled);
+ encodingLabel.setEnabled(enabled);
+ ianaLabel.setEnabled(enabled);
+ ianaText.setEnabled(enabled);
+ }
+
+ /**
+ * <code>setEncoding</code> Set the selection in the combo to the
+ * descriptive encoding name.
+ *
+ * @param enc
+ * a <code>string</code> value. Note this is not the IANA
+ * tag.
+ */
+ public void setEncoding(String enc) {
+ encodingCombo.setText(enc);
+ encodingCombo.select(encodingCombo.indexOf(enc));
+ }
+
+ /**
+ * <code>setIANATag</code> Set the IANA tag for the combo
+ *
+ * @param ianaTag
+ * a <code>string</code> value. The IANA tag.
+ */
+ public void setIANATag(String ianaTag) {
+ int i = ianaVector.indexOf(ianaTag);
+ if (i >= 0) {
+ encodingCombo.select(i);
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/WorkbenchDefaultEncodingSettings.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/WorkbenchDefaultEncodingSettings.java
new file mode 100644
index 0000000000..705f07bb6c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/WorkbenchDefaultEncodingSettings.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.preferences;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.wst.common.encoding.CommonCharsetNames;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+
+/**
+ * WorkbenchDefaultEncodingSettings is an extension of EncodingSettings. This
+ * composite contains EncodingSettings for users to select the encoding they
+ * desire as well as a checkbox for users to select to use the default
+ * workbench encoding instead.
+ *
+ * @see org.eclipse.wst.xml.ui.preferences.EncodingSettings
+ */
+public class WorkbenchDefaultEncodingSettings extends Composite {
+
+ private final static int INDENT = 15;
+ private static final String WORKBENCH_DEFAULT = ""; //$NON-NLS-1$
+ private EncodingSettings fEncodingSettings;
+ private String fNonDefaultIANA = null;
+ private Button fUseDefaultButton;
+
+ /**
+ * Constructor for WorkbenchDefaultEncodingSettings.
+ *
+ * @param parent
+ * @param style
+ */
+ public WorkbenchDefaultEncodingSettings(Composite parent) {
+ super(parent, SWT.NONE);
+ createControls();
+ }
+
+ private void createControls() {
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ layout.marginWidth = 0;
+ setLayout(layout);
+ GridData data = new GridData();
+ data.verticalAlignment = GridData.FILL;
+ data.horizontalAlignment = GridData.FILL;
+ data.grabExcessHorizontalSpace = true;
+ setLayoutData(data);
+
+ Composite defaultEncodingComposite = new Composite(this, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ data = new GridData(GridData.FILL_BOTH);
+ defaultEncodingComposite.setLayout(layout);
+ defaultEncodingComposite.setLayoutData(data);
+
+ fUseDefaultButton = new Button(defaultEncodingComposite, SWT.CHECK);
+ fUseDefaultButton.setText(ResourceHandler.getString("WorkbenchDefaultEncodingSettings.0")); //$NON-NLS-1$
+
+ fUseDefaultButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleUseDefaultButtonSelected();
+ }
+ });
+
+ fEncodingSettings = new EncodingSettings(this);
+ ((GridLayout) fEncodingSettings.getLayout()).marginWidth = 0;
+ ((GridData) fEncodingSettings.getLayoutData()).horizontalIndent = INDENT;
+
+ }
+
+ private Combo getEncodingCombo() {
+ return fEncodingSettings.getEncodingCombo();
+ }
+
+ /**
+ * <code>getIANATag</code> Get the IANA tag equivalent of the selected
+ * descriptive encoding name. Returns empty string if using workbench
+ * encoding.
+ *
+ * @return a <code>String</code> value
+ */
+ public String getIANATag() {
+ if (!isDefault())
+ return fEncodingSettings.getIANATag();
+ return WORKBENCH_DEFAULT;
+ }
+
+ private String getWorkbenchEncoding() {
+ return ResourcesPlugin.getEncoding();
+ }
+
+ private void handleUseDefaultButtonSelected() {
+ if (fUseDefaultButton.getSelection()) {
+ fNonDefaultIANA = fEncodingSettings.getIANATag();
+ String workbenchValue = getWorkbenchEncoding();
+ workbenchValue = CommonCharsetNames.getIanaPreferredCharsetName(workbenchValue);
+ fEncodingSettings.setIANATag(workbenchValue);
+ } else if (fNonDefaultIANA != null) {
+ fEncodingSettings.setIANATag(fNonDefaultIANA);
+ }
+ getEncodingCombo().setEnabled(!fUseDefaultButton.getSelection());
+ fEncodingSettings.setEnabled(!fUseDefaultButton.getSelection());
+ }
+
+ private boolean isDefault() {
+ return fUseDefaultButton.getSelection();
+ }
+
+ /**
+ * <code>setEncoding</code> Set the selection in the combo to the
+ * descriptive encoding name. Selects use workbench encoding if ianaTag is
+ * null or empty string.
+ *
+ * @param enc
+ * a <code>string</code> value. Note this is not the IANA
+ * tag.
+ */
+ public void setIANATag(String ianaTag) {
+ if (ianaTag == null || ianaTag.equals(WORKBENCH_DEFAULT)) {
+ fUseDefaultButton.setSelection(true);
+ handleUseDefaultButtonSelected();
+ } else {
+ fUseDefaultButton.setSelection(false);
+ handleUseDefaultButtonSelected();
+ if (!isDefault())
+ fEncodingSettings.setIANATag(ianaTag);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLColorPage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLColorPage.java
new file mode 100644
index 0000000000..71aef4ed0d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLColorPage.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.preferences;
+
+
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.core.IModelManager;
+import org.eclipse.wst.sse.core.IModelManagerPlugin;
+import org.eclipse.wst.sse.ui.EditorPlugin;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore;
+import org.eclipse.wst.sse.ui.internal.preferences.OverlayPreferenceStore.OverlayKey;
+import org.eclipse.wst.sse.ui.preferences.PreferenceKeyGenerator;
+import org.eclipse.wst.sse.ui.preferences.ui.AbstractColorPage;
+import org.eclipse.wst.sse.ui.preferences.ui.StyledTextColorPicker;
+import org.eclipse.wst.xml.core.internal.parser.XMLSourceParser;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.ui.style.IStyleConstantsXML;
+
+
+
+public class XMLColorPage extends AbstractColorPage {
+
+ protected Control createContents(Composite parent) {
+ Composite pageComponent = createComposite(parent, 1);
+ ((GridData) pageComponent.getLayoutData()).horizontalAlignment = GridData.HORIZONTAL_ALIGN_FILL;
+
+ super.createContents(pageComponent);
+ WorkbenchHelp.setHelp(pageComponent, IHelpContextIds.XML_PREFWEBX_STYLES_HELPID);
+ return pageComponent;
+ }
+
+ /**
+ * Set up all the style preference keys in the overlay store
+ */
+ protected OverlayKey[] createOverlayStoreKeys() {
+ ArrayList overlayKeys = new ArrayList();
+
+ ArrayList styleList = new ArrayList();
+ initStyleList(styleList);
+ Iterator i = styleList.iterator();
+ while (i.hasNext()) {
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceKeyGenerator.generateKey((String) i.next(), IContentTypeIdentifier.ContentTypeID_SSEXML)));
+ }
+
+ OverlayPreferenceStore.OverlayKey[] keys = new OverlayPreferenceStore.OverlayKey[overlayKeys.size()];
+ overlayKeys.toArray(keys);
+ return keys;
+ }
+
+ protected IPreferenceStore doGetPreferenceStore() {
+ return EditorPlugin.getDefault().getPreferenceStore();
+ }
+
+ public String getSampleText() {
+ return ResourceHandler.getString("Sample_XML_doc"); //$NON-NLS-1$ = "<?xml version=\"1.0\"?>\n<?customProcessingInstruction\n\tXML processor specific\n\tcontent ?>\n<!DOCTYPE colors\n\tPUBLIC \"//IBM/XML/COLORS/\" \"colors.dtd\">\n<colors>\n\t<!-- begin color definitions -->\n\t<color name=\"plaintext\" foreground=\"#000000\"\n\t\tbackground=\"#D4D0C8\"/>\n\t<color name=\"bold\" foreground=\"#000000\"\n\t\tbackground=\"#B3ACA0\">\n\t<![CDATA[<123456789>]]>\n\tNormal text content.\n\t<color name=\"inverse\" foreground=\"#F0F0F0\"\n\t\tbackground=\"#D4D0C8\"/>\n\n</colors>\n";
+ }
+
+ protected void initCommonContextStyleMap(Dictionary contextStyleMap) {
+
+ contextStyleMap.put(XMLRegionContext.XML_COMMENT_OPEN, IStyleConstantsXML.COMMENT_BORDER);
+ contextStyleMap.put(XMLRegionContext.XML_COMMENT_TEXT, IStyleConstantsXML.COMMENT_TEXT);
+ contextStyleMap.put(XMLRegionContext.XML_COMMENT_CLOSE, IStyleConstantsXML.COMMENT_BORDER);
+
+ contextStyleMap.put(XMLRegionContext.XML_TAG_OPEN, IStyleConstantsXML.TAG_BORDER);
+ contextStyleMap.put(XMLRegionContext.XML_END_TAG_OPEN, IStyleConstantsXML.TAG_BORDER);
+ contextStyleMap.put(XMLRegionContext.XML_TAG_NAME, IStyleConstantsXML.TAG_NAME);
+ contextStyleMap.put(XMLRegionContext.XML_TAG_ATTRIBUTE_NAME, IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+ contextStyleMap.put(XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE, IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+ contextStyleMap.put(XMLRegionContext.XML_TAG_CLOSE, IStyleConstantsXML.TAG_BORDER);
+ contextStyleMap.put(XMLRegionContext.XML_EMPTY_TAG_CLOSE, IStyleConstantsXML.TAG_BORDER);
+
+ contextStyleMap.put(XMLRegionContext.XML_DECLARATION_OPEN, IStyleConstantsXML.DECL_BORDER);
+ contextStyleMap.put(XMLRegionContext.XML_DECLARATION_CLOSE, IStyleConstantsXML.DECL_BORDER);
+ contextStyleMap.put(XMLRegionContext.XML_ELEMENT_DECLARATION, IStyleConstantsXML.DECL_BORDER);
+ contextStyleMap.put(XMLRegionContext.XML_ELEMENT_DECL_CLOSE, IStyleConstantsXML.DECL_BORDER);
+
+ contextStyleMap.put(XMLRegionContext.XML_CONTENT, IStyleConstantsXML.XML_CONTENT);
+ }
+
+ protected void initCommonDescriptions(Dictionary descriptions) {
+
+ // create descriptions for hilighting types
+ descriptions.put(IStyleConstantsXML.COMMENT_BORDER, ResourceHandler.getString("Comment_Delimiters_UI_")); //$NON-NLS-1$ = "Comment Delimiters"
+ descriptions.put(IStyleConstantsXML.COMMENT_TEXT, ResourceHandler.getString("Comment_Content_UI_")); //$NON-NLS-1$ = "Comment Content"
+ descriptions.put(IStyleConstantsXML.TAG_BORDER, ResourceHandler.getString("Tag_Delimiters_UI_")); //$NON-NLS-1$ = "Tag Delimiters"
+ descriptions.put(IStyleConstantsXML.TAG_NAME, ResourceHandler.getString("Tag_Names_UI_")); //$NON-NLS-1$ = "Tag Names"
+ descriptions.put(IStyleConstantsXML.TAG_ATTRIBUTE_NAME, ResourceHandler.getString("Attribute_Names_UI_")); //$NON-NLS-1$ = "Attribute Names"
+ descriptions.put(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE, ResourceHandler.getString("Attribute_Values_UI_")); //$NON-NLS-1$ = "Attribute Values"
+ descriptions.put(IStyleConstantsXML.DECL_BORDER, ResourceHandler.getString("Declaration_Delimiters_UI_")); //$NON-NLS-1$ = "Declaration Delimiters"
+ descriptions.put(IStyleConstantsXML.XML_CONTENT, ResourceHandler.getString("Content_UI_")); //$NON-NLS-1$ = "Content"
+ }
+
+ protected void initCommonStyleList(ArrayList list) {
+
+ //list.add(IStyleConstantsXML.CDATA_BORDER);
+ //list.add(IStyleConstantsXML.CDATA_TEXT);
+ //list.add(IStyleConstantsXML.PI_BORDER);
+ //list.add(IStyleConstantsXML.PI_CONTENT);
+
+ list.add(IStyleConstantsXML.TAG_BORDER);
+ list.add(IStyleConstantsXML.TAG_NAME);
+ list.add(IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+ list.add(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+ list.add(IStyleConstantsXML.COMMENT_BORDER);
+ list.add(IStyleConstantsXML.COMMENT_TEXT);
+ list.add(IStyleConstantsXML.DECL_BORDER);
+ list.add(IStyleConstantsXML.XML_CONTENT);
+ }
+
+ protected void initContextStyleMap(Dictionary contextStyleMap) {
+
+ initCommonContextStyleMap(contextStyleMap);
+ initDocTypeContextStyleMap(contextStyleMap);
+ contextStyleMap.put(XMLRegionContext.XML_CDATA_OPEN, IStyleConstantsXML.CDATA_BORDER);
+ contextStyleMap.put(XMLRegionContext.XML_CDATA_TEXT, IStyleConstantsXML.CDATA_TEXT);
+ contextStyleMap.put(XMLRegionContext.XML_CDATA_CLOSE, IStyleConstantsXML.CDATA_BORDER);
+
+ contextStyleMap.put(XMLRegionContext.XML_PI_OPEN, IStyleConstantsXML.PI_BORDER);
+ contextStyleMap.put(XMLRegionContext.XML_PI_CONTENT, IStyleConstantsXML.PI_CONTENT);
+ contextStyleMap.put(XMLRegionContext.XML_PI_CLOSE, IStyleConstantsXML.PI_BORDER);
+
+ }
+
+ protected void initDescriptions(Dictionary descriptions) {
+
+ initCommonDescriptions(descriptions);
+ initDocTypeDescriptions(descriptions);
+ descriptions.put(IStyleConstantsXML.CDATA_BORDER, ResourceHandler.getString("CDATA_Delimiters_UI_")); //$NON-NLS-1$ = "CDATA Delimiters"
+ descriptions.put(IStyleConstantsXML.CDATA_TEXT, ResourceHandler.getString("CDATA_Content_UI_")); //$NON-NLS-1$ = "CDATA Content"
+ descriptions.put(IStyleConstantsXML.PI_BORDER, ResourceHandler.getString("Processing_Instruction_Del_UI_")); //$NON-NLS-1$ = "Processing Instruction Delimiters"
+ descriptions.put(IStyleConstantsXML.PI_CONTENT, ResourceHandler.getString("Processing_Instruction_Con_UI__UI_")); //$NON-NLS-1$ = "Processing Instruction Content"
+ }
+
+ protected void initDocTypeContextStyleMap(Dictionary contextStyleMap) {
+
+ contextStyleMap.put(XMLRegionContext.XML_ELEMENT_DECL_NAME, IStyleConstantsXML.DOCTYPE_NAME);
+ contextStyleMap.put(XMLRegionContext.XML_DOCTYPE_DECLARATION, IStyleConstantsXML.TAG_NAME);
+ contextStyleMap.put(XMLRegionContext.XML_DOCTYPE_DECLARATION_CLOSE, IStyleConstantsXML.DECL_BORDER);
+
+ contextStyleMap.put(XMLRegionContext.XML_DOCTYPE_NAME, IStyleConstantsXML.DOCTYPE_NAME);
+ contextStyleMap.put(XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBLIC, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+ contextStyleMap.put(XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBREF, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+ contextStyleMap.put(XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSTEM, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+ contextStyleMap.put(XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSREF, IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+ }
+
+ protected void initDocTypeDescriptions(Dictionary descriptions) {
+
+ // create descriptions for hilighting types for DOCTYPE related items
+ descriptions.put(IStyleConstantsXML.DOCTYPE_NAME, ResourceHandler.getString("DOCTYPE_Name_UI_")); //$NON-NLS-1$ = "DOCTYPE Name"
+ descriptions.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID, ResourceHandler.getString("DOCTYPE_SYSTEM/PUBLIC_Keyw_UI_")); //$NON-NLS-1$ = "DOCTYPE SYSTEM/PUBLIC Keyword"
+ descriptions.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF, ResourceHandler.getString("DOCTYPE_Public_Reference_UI_")); //$NON-NLS-1$ = "DOCTYPE Public Reference"
+ descriptions.put(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF, ResourceHandler.getString("DOCTYPE_System_Reference_UI_")); //$NON-NLS-1$ = "DOCTYPE System Reference"
+ }
+
+ protected void initDocTypeStyleList(ArrayList list) {
+
+ list.add(IStyleConstantsXML.DOCTYPE_NAME);
+ list.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+ list.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+ list.add(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+ }
+
+ protected void initStyleList(ArrayList list) {
+ initCommonStyleList(list);
+ initDocTypeStyleList(list);
+ list.add(IStyleConstantsXML.CDATA_BORDER);
+ list.add(IStyleConstantsXML.CDATA_TEXT);
+ list.add(IStyleConstantsXML.PI_BORDER);
+ list.add(IStyleConstantsXML.PI_CONTENT);
+ }
+
+ public boolean performOk() {
+ // required since the superclass *removes* existing preferences before
+ // saving its own
+ super.performOk();
+
+ EditorPlugin.getDefault().savePluginPreferences();
+ return true;
+ }
+
+ protected void setupPicker(StyledTextColorPicker picker) {
+
+ IModelManagerPlugin plugin = (IModelManagerPlugin) Platform.getPlugin(IModelManagerPlugin.ID);
+ if (plugin != null) {
+ IModelManager mmanager = plugin.getModelManager();
+ picker.setParser(mmanager.createStructuredDocumentFor(IContentTypeIdentifier.ContentTypeID_SSEXML).getParser());
+ } else
+ picker.setParser(new XMLSourceParser());
+
+ Dictionary descriptions = new Hashtable();
+ initDescriptions(descriptions);
+
+ Dictionary contextStyleMap = new Hashtable();
+ initContextStyleMap(contextStyleMap);
+
+ ArrayList styleList = new ArrayList();
+ initStyleList(styleList);
+
+ picker.setContextStyleMap(contextStyleMap);
+ picker.setDescriptions(descriptions);
+ picker.setStyleList(styleList);
+
+ picker.setGeneratorKey(IContentTypeIdentifier.ContentTypeID_SSEXML);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLFilesPreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLFilesPreferencePage.java
new file mode 100644
index 0000000000..4a159c642a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLFilesPreferencePage.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.preferences;
+
+
+
+import java.util.Vector;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.wst.common.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.ui.EditorPlugin;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.sse.ui.preferences.ui.AbstractPreferencePage;
+import org.eclipse.wst.xml.core.XMLModelPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+
+
+public class XMLFilesPreferencePage extends AbstractPreferencePage {
+ protected EncodingSettings fEncodingSettings = null;
+
+ protected Combo fEndOfLineCode = null;
+ private Vector fEOLCodes = null;
+
+ protected Control createContents(Composite parent) {
+ Composite composite = (Composite) super.createContents(parent);
+ WorkbenchHelp.setHelp(composite, IHelpContextIds.XML_PREFWEBX_FILES_HELPID);
+ createContentsForCreatingOrSavingGroup(composite);
+ createContentsForCreatingGroup(composite);
+
+ setSize(composite);
+ loadPreferences();
+
+ return composite;
+ }
+
+ protected void createContentsForCreatingGroup(Composite parent) {
+ Group creatingGroup = createGroup(parent, 1);
+ creatingGroup.setText(ResourceHandler.getString("Creating_files")); //$NON-NLS-1$
+
+ Label label = createLabel(creatingGroup, ResourceHandler.getString("Encoding_desc")); //$NON-NLS-1$
+
+ fEncodingSettings = new EncodingSettings(creatingGroup, ResourceHandler.getString("Encoding")); //$NON-NLS-1$
+ }
+
+ protected void createContentsForCreatingOrSavingGroup(Composite parent) {
+ Group creatingOrSavingGroup = createGroup(parent, 2);
+ creatingOrSavingGroup.setText(ResourceHandler.getString("Creating_or_saving_files")); //$NON-NLS-1$
+
+ Label label = createLabel(creatingOrSavingGroup, ResourceHandler.getString("End-of-line_code_desc")); //$NON-NLS-1$
+ ((GridData) label.getLayoutData()).horizontalSpan = 2;
+ ((GridData) label.getLayoutData()).grabExcessHorizontalSpace = true;
+
+ createLabel(creatingOrSavingGroup, ResourceHandler.getString("End-of-line_code")); //$NON-NLS-1$
+ fEndOfLineCode = createDropDownBox(creatingOrSavingGroup);
+ populateLineDelimiters();
+ }
+
+ protected IPreferenceStore doGetPreferenceStore() {
+ return EditorPlugin.getDefault().getPreferenceStore();
+ }
+
+ protected void doSavePreferenceStore() {
+ XMLModelPlugin.getDefault().savePluginPreferences(); // model
+ }
+
+ /**
+ * Return the currently selected line delimiter preference
+ *
+ * @return a line delimiter constant from CommonEncodingPreferenceNames
+ */
+ private String getCurrentEOLCode() {
+ int i = fEndOfLineCode.getSelectionIndex();
+ if (i >= 0) {
+ return (String) (fEOLCodes.elementAt(i));
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.preferences.ui.AbstractPreferencePage#getModelPreferences()
+ */
+ protected Preferences getModelPreferences() {
+ return XMLModelPlugin.getDefault().getPluginPreferences();
+ }
+
+ protected void initializeValues() {
+ initializeValuesForCreatingOrSavingGroup();
+ initializeValuesForCreatingGroup();
+ }
+
+ protected void initializeValuesForCreatingGroup() {
+ String encoding = getModelPreferences().getString(CommonEncodingPreferenceNames.OUTPUT_CODESET);
+
+ fEncodingSettings.setIANATag(encoding);
+ }
+
+ protected void initializeValuesForCreatingOrSavingGroup() {
+ String endOfLineCode = getModelPreferences().getString(CommonEncodingPreferenceNames.END_OF_LINE_CODE);
+
+ if (endOfLineCode.length() > 0)
+ setCurrentEOLCode(endOfLineCode);
+ else
+ setCurrentEOLCode(CommonEncodingPreferenceNames.NO_TRANSLATION);
+ }
+
+ protected void performDefaults() {
+ performDefaultsForCreatingOrSavingGroup();
+ performDefaultsForCreatingGroup();
+
+ super.performDefaults();
+ }
+
+ protected void performDefaultsForCreatingGroup() {
+ String encoding = getModelPreferences().getDefaultString(CommonEncodingPreferenceNames.OUTPUT_CODESET);
+
+ fEncodingSettings.setIANATag(encoding);
+ // fEncodingSettings.resetToDefaultEncoding();
+ }
+
+ protected void performDefaultsForCreatingOrSavingGroup() {
+ String endOfLineCode = getModelPreferences().getDefaultString(CommonEncodingPreferenceNames.END_OF_LINE_CODE);
+
+ if (endOfLineCode.length() > 0)
+ setCurrentEOLCode(endOfLineCode);
+ else
+ setCurrentEOLCode(CommonEncodingPreferenceNames.NO_TRANSLATION);
+ }
+
+ public boolean performOk() {
+ boolean result = super.performOk();
+
+ doSavePreferenceStore();
+
+ return result;
+ }
+
+ /**
+ * Populates the vector containing the line delimiter to display string
+ * mapping and the combobox displaying line delimiters
+ */
+ private void populateLineDelimiters() {
+ fEOLCodes = new Vector();
+ fEndOfLineCode.add(ResourceHandler.getString("EOL_Unix")); //$NON-NLS-1$
+ fEOLCodes.add(CommonEncodingPreferenceNames.LF);
+
+ fEndOfLineCode.add(ResourceHandler.getString("EOL_Mac")); //$NON-NLS-1$
+ fEOLCodes.add(CommonEncodingPreferenceNames.CR);
+
+ fEndOfLineCode.add(ResourceHandler.getString("EOL_Windows")); //$NON-NLS-1$
+ fEOLCodes.add(CommonEncodingPreferenceNames.CRLF);
+
+ fEndOfLineCode.add(ResourceHandler.getString("EOL_NoTranslation")); //$NON-NLS-1$
+ fEOLCodes.add(CommonEncodingPreferenceNames.NO_TRANSLATION);
+ }
+
+ /**
+ * Select the line delimiter in the eol combobox
+ *
+ * @param eol
+ * a line delimiter constant from CommonEncodingPreferenceNames
+ */
+ private void setCurrentEOLCode(String eolCode) {
+ // Clear the current selection.
+ fEndOfLineCode.clearSelection();
+ fEndOfLineCode.deselectAll();
+
+ int i = fEOLCodes.indexOf(eolCode);
+ if (i >= 0) {
+ fEndOfLineCode.select(i);
+ }
+ }
+
+ protected void storeValues() {
+ storeValuesForCreatingOrSavingGroup();
+ storeValuesForCreatingGroup();
+ }
+
+ protected void storeValuesForCreatingGroup() {
+ getModelPreferences().setValue(CommonEncodingPreferenceNames.OUTPUT_CODESET, fEncodingSettings.getIANATag());
+ }
+
+ protected void storeValuesForCreatingOrSavingGroup() {
+ String eolCode = getCurrentEOLCode();
+ getModelPreferences().setValue(CommonEncodingPreferenceNames.END_OF_LINE_CODE, eolCode);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLSourcePreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLSourcePreferencePage.java
new file mode 100644
index 0000000000..25689e1503
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLSourcePreferencePage.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.preferences;
+
+
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.core.preferences.CommonModelPreferenceNames;
+import org.eclipse.wst.sse.ui.EditorPlugin;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.sse.ui.preferences.CommonEditorPreferenceNames;
+import org.eclipse.wst.sse.ui.preferences.PreferenceKeyGenerator;
+import org.eclipse.wst.sse.ui.preferences.ui.AbstractPreferencePage;
+import org.eclipse.wst.xml.core.XMLModelPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+
+
+public class XMLSourcePreferencePage extends AbstractPreferencePage implements ModifyListener, SelectionListener, IWorkbenchPreferencePage {
+ // Content Assist
+ protected Button fAutoPropose;
+ protected Label fAutoProposeLabel;
+ protected Text fAutoProposeText;
+ protected Button fClearAllBlankLines;
+ protected Button fIndentUsingTabs;
+ // Formatting
+ protected Label fLineWidthLabel;
+ protected Text fLineWidthText;
+ protected Button fSplitMultiAttrs;
+ // grammar constraints
+ protected Button fUseInferredGrammar;
+
+ protected Control createContents(Composite parent) {
+ Composite composite = (Composite) super.createContents(parent);
+ WorkbenchHelp.setHelp(composite, IHelpContextIds.XML_PREFWEBX_SOURCE_HELPID);
+
+ createContentsForFormattingGroup(composite);
+ createContentsForContentAssistGroup(composite);
+ createContentsForGrammarConstraintsGroup(composite);
+ setSize(composite);
+ loadPreferences();
+
+ return composite;
+ }
+
+ protected void createContentsForContentAssistGroup(Composite parent) {
+ Group contentAssistGroup = createGroup(parent, 2);
+ contentAssistGroup.setText(ResourceHandler.getString("Content_assist_UI_")); //$NON-NLS-1$ = "Content assist"
+
+ fAutoPropose = createCheckBox(contentAssistGroup, ResourceHandler.getString("Automatically_make_suggest_UI_")); //$NON-NLS-1$ = "Automatically make suggestions"
+ ((GridData) fAutoPropose.getLayoutData()).horizontalSpan = 2;
+ fAutoPropose.addSelectionListener(this);
+
+ fAutoProposeLabel = createLabel(contentAssistGroup, ResourceHandler.getString("Prompt_when_these_characte_UI_")); //$NON-NLS-1$ = "Prompt when these characters are inserted:"
+ fAutoProposeText = createTextField(contentAssistGroup);
+ }
+
+ protected void createContentsForFormattingGroup(Composite parent) {
+ Group formattingGroup = createGroup(parent, 2);
+ formattingGroup.setText(ResourceHandler.getString("Formatting_UI_")); //$NON-NLS-1$ = "Formatting"
+
+ fLineWidthLabel = createLabel(formattingGroup, ResourceHandler.getString("Line_width__UI_")); //$NON-NLS-1$ = "Line width:"
+ fLineWidthText = new Text(formattingGroup, SWT.SINGLE | SWT.BORDER);
+ GridData gData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.BEGINNING);
+ gData.widthHint = 25;
+ fLineWidthText.setLayoutData(gData);
+ fLineWidthText.addModifyListener(this);
+
+ fSplitMultiAttrs = createCheckBox(formattingGroup, ResourceHandler.getString("Split_&multiple_attributes_2")); //$NON-NLS-1$
+ ((GridData) fSplitMultiAttrs.getLayoutData()).horizontalSpan = 2;
+
+ fIndentUsingTabs = createCheckBox(formattingGroup, ResourceHandler.getString("&Indent_using_tabs_3")); //$NON-NLS-1$
+ ((GridData) fIndentUsingTabs.getLayoutData()).horizontalSpan = 2;
+
+ fClearAllBlankLines = createCheckBox(formattingGroup, ResourceHandler.getString("Clear_all_blank_lines_UI_")); //$NON-NLS-1$ = "Clear all blank lines"
+ ((GridData) fClearAllBlankLines.getLayoutData()).horizontalSpan = 2;
+ }
+
+ protected void createContentsForGrammarConstraintsGroup(Composite parent) {
+ Group grammarConstraintsGroup = createGroup(parent, 1);
+ grammarConstraintsGroup.setText(ResourceHandler.getString("Grammar_Constraints")); //$NON-NLS-1$
+ grammarConstraintsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
+
+ fUseInferredGrammar = createCheckBox(grammarConstraintsGroup, ResourceHandler.getString("Use_inferred_grammar_in_absence_of_DTD/Schema")); //$NON-NLS-1$
+ }
+
+ protected IPreferenceStore doGetPreferenceStore() {
+ return EditorPlugin.getDefault().getPreferenceStore();
+ }
+
+ protected void doSavePreferenceStore() {
+ EditorPlugin.getDefault().savePluginPreferences(); // editor
+ XMLModelPlugin.getDefault().savePluginPreferences(); // model
+ }
+
+ protected void enableValues() {
+ if (fAutoPropose != null) {
+ if (fAutoPropose.getSelection()) {
+ fAutoProposeLabel.setEnabled(true);
+ fAutoProposeText.setEnabled(true);
+ } else {
+ fAutoProposeLabel.setEnabled(false);
+ fAutoProposeText.setEnabled(false);
+ }
+ }
+ }
+
+ /*
+ * helper method to generate content type id specific preference keys
+ */
+ protected String getKey(String key) {
+ String contentTypeId = IContentTypeIdentifier.ContentTypeID_SSEXML;
+ return PreferenceKeyGenerator.generateKey(key, contentTypeId);
+ }
+
+ protected Preferences getModelPreferences() {
+ return XMLModelPlugin.getDefault().getPluginPreferences();
+ }
+
+ protected void initializeValues() {
+ initializeValuesForFormattingGroup();
+ initializeValuesForContentAssistGroup();
+ initializeValuesForGrammarConstraintsGroup();
+ }
+
+ protected void initializeValuesForContentAssistGroup() {
+ // Content Assist
+ fAutoPropose.setSelection(getPreferenceStore().getBoolean(getKey(CommonEditorPreferenceNames.AUTO_PROPOSE)));
+ fAutoProposeText.setText(getPreferenceStore().getString(getKey(CommonEditorPreferenceNames.AUTO_PROPOSE_CODE)));
+ }
+
+ protected void initializeValuesForFormattingGroup() {
+ // Formatting
+ fLineWidthText.setText(getModelPreferences().getString(CommonModelPreferenceNames.LINE_WIDTH));
+ fSplitMultiAttrs.setSelection(getModelPreferences().getBoolean(CommonModelPreferenceNames.SPLIT_MULTI_ATTRS));
+ fIndentUsingTabs.setSelection(getModelPreferences().getBoolean(CommonModelPreferenceNames.INDENT_USING_TABS));
+ fClearAllBlankLines.setSelection(getModelPreferences().getBoolean(CommonModelPreferenceNames.CLEAR_ALL_BLANK_LINES));
+ }
+
+ protected void initializeValuesForGrammarConstraintsGroup() {
+ fUseInferredGrammar.setSelection(getPreferenceStore().getBoolean(getKey(CommonEditorPreferenceNames.EDITOR_USE_INFERRED_GRAMMAR)));
+ }
+
+ protected void performDefaults() {
+ performDefaultsForFormattingGroup();
+ performDefaultsForContentAssistGroup();
+ performDefaultsForGrammarConstraintsGroup();
+
+ validateValues();
+ enableValues();
+
+ super.performDefaults();
+ }
+
+ protected void performDefaultsForContentAssistGroup() {
+ // Content Assist
+ fAutoPropose.setSelection(getPreferenceStore().getDefaultBoolean(getKey(CommonEditorPreferenceNames.AUTO_PROPOSE)));
+ fAutoProposeText.setText(getPreferenceStore().getDefaultString(getKey(CommonEditorPreferenceNames.AUTO_PROPOSE_CODE)));
+ }
+
+ protected void performDefaultsForFormattingGroup() {
+ // Formatting
+ fLineWidthText.setText(getModelPreferences().getDefaultString(CommonModelPreferenceNames.LINE_WIDTH));
+ fSplitMultiAttrs.setSelection(getModelPreferences().getDefaultBoolean(CommonModelPreferenceNames.SPLIT_MULTI_ATTRS));
+ fIndentUsingTabs.setSelection(getModelPreferences().getDefaultBoolean(CommonModelPreferenceNames.INDENT_USING_TABS));
+ fClearAllBlankLines.setSelection(getModelPreferences().getDefaultBoolean(CommonModelPreferenceNames.CLEAR_ALL_BLANK_LINES));
+ }
+
+ protected void performDefaultsForGrammarConstraintsGroup() {
+ fUseInferredGrammar.setSelection(getPreferenceStore().getDefaultBoolean(getKey(CommonEditorPreferenceNames.EDITOR_USE_INFERRED_GRAMMAR)));
+ }
+
+ public boolean performOk() {
+ boolean result = super.performOk();
+
+ doSavePreferenceStore();
+
+ return result;
+ }
+
+ protected void storeValues() {
+ storeValuesForFormattingGroup();
+ storeValuesForContentAssistGroup();
+ storeValuesForGrammarConstraintsGroup();
+ }
+
+ protected void storeValuesForContentAssistGroup() {
+ // Content Assist
+ getPreferenceStore().setValue(getKey(CommonEditorPreferenceNames.AUTO_PROPOSE), fAutoPropose.getSelection());
+ getPreferenceStore().setValue(getKey(CommonEditorPreferenceNames.AUTO_PROPOSE_CODE), fAutoProposeText.getText());
+ }
+
+ protected void storeValuesForFormattingGroup() {
+ // Formatting
+ getModelPreferences().setValue(CommonModelPreferenceNames.LINE_WIDTH, fLineWidthText.getText());
+ getModelPreferences().setValue(CommonModelPreferenceNames.SPLIT_MULTI_ATTRS, fSplitMultiAttrs.getSelection());
+ getModelPreferences().setValue(CommonModelPreferenceNames.INDENT_USING_TABS, fIndentUsingTabs.getSelection());
+ getModelPreferences().setValue(CommonModelPreferenceNames.CLEAR_ALL_BLANK_LINES, fClearAllBlankLines.getSelection());
+ }
+
+ protected void storeValuesForGrammarConstraintsGroup() {
+ getPreferenceStore().setValue(getKey(CommonEditorPreferenceNames.EDITOR_USE_INFERRED_GRAMMAR), fUseInferredGrammar.getSelection());
+ }
+
+ protected void validateValues() {
+ boolean isError = false;
+ String widthText = null;
+
+ if (fLineWidthText != null) {
+ try {
+ widthText = fLineWidthText.getText();
+ int formattingLineWidth = Integer.parseInt(widthText);
+ if ((formattingLineWidth < WIDTH_VALIDATION_LOWER_LIMIT) || (formattingLineWidth > WIDTH_VALIDATION_UPPER_LIMIT))
+ throw new NumberFormatException();
+ } catch (NumberFormatException nfexc) {
+ setInvalidInputMessage(widthText);
+ setValid(false);
+ isError = true;
+ }
+ }
+
+ if (!isError) {
+ setErrorMessage(null);
+ setValid(true);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLTemplatePreferencePage.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLTemplatePreferencePage.java
new file mode 100644
index 0000000000..2b05119f2c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/preferences/XMLTemplatePreferencePage.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.preferences;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.help.WorkbenchHelp;
+import org.eclipse.ui.texteditor.templates.TemplatePreferencePage;
+import org.eclipse.wst.xml.ui.XMLEditorPlugin;
+import org.eclipse.wst.xml.ui.internal.editor.IHelpContextIds;
+
+
+/**
+ * Preference page for XML templates
+ */
+public class XMLTemplatePreferencePage extends TemplatePreferencePage {
+
+ public XMLTemplatePreferencePage() {
+ XMLEditorPlugin xmlEditorPlugin = (XMLEditorPlugin) Platform.getPlugin(XMLEditorPlugin.ID);
+
+ setPreferenceStore(xmlEditorPlugin.getPreferenceStore());
+ setTemplateStore(xmlEditorPlugin.getTemplateStore());
+ setContextTypeRegistry(xmlEditorPlugin.getTemplateContextRegistry());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createContents(Composite ancestor) {
+ Control c = super.createContents(ancestor);
+ WorkbenchHelp.setHelp(c, IHelpContextIds.XML_PREFWEBX_TEMPLATES_HELPID);
+ return c;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.texteditor.templates.TemplatePreferencePage#isShowFormatterSetting()
+ */
+ protected boolean isShowFormatterSetting() {
+ // template formatting has not been implemented
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ boolean ok = super.performOk();
+ Platform.getPlugin(XMLEditorPlugin.ID).savePluginPreferences();
+ return ok;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/AbstractReconcileStepAdapter.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/AbstractReconcileStepAdapter.java
new file mode 100644
index 0000000000..46e23bf3e0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/AbstractReconcileStepAdapter.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.reconcile;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.rules.StructuredTextPartitioner;
+import org.eclipse.wst.sse.ui.Logger;
+import org.eclipse.wst.sse.ui.StructuredTextReconciler;
+import org.eclipse.wst.sse.ui.internal.reconcile.IReconcileAnnotationKey;
+import org.eclipse.wst.sse.ui.internal.reconcile.IReconcileStepAdapter;
+import org.eclipse.wst.sse.ui.internal.reconcile.IStructuredReconcileStep;
+import org.eclipse.wst.sse.ui.internal.reconcile.ReconcileAnnotationKey;
+
+
+/**
+ * This reconcile step is an adapter on the IStructuredModel. Validation is
+ * triggered from StructuredDocumentEvents
+ *
+ * @author pavery
+ */
+public class AbstractReconcileStepAdapter implements IReconcileStepAdapter {
+
+ protected static final IReconcileResult[] EMPTY_RECONCILE_RESULT_SET = new IReconcileResult[0];
+ protected List fDirtyElements = new ArrayList();
+ private IStructuredReconcileStep fParentStep = null;
+ private HashSet fPartitionTypes = null;
+
+ public AbstractReconcileStepAdapter() {
+ super();
+ fPartitionTypes = new HashSet();
+ }
+
+ public IReconcileAnnotationKey createKey(IStructuredDocumentRegion sdRegion, int scope) {
+ ITypedRegion tr = null;
+ if (!sdRegion.isDeleted()) {
+ try {
+ tr = sdRegion.getParentDocument().getPartition(sdRegion.getStartOffset());
+ } catch (BadLocationException e) {
+ // do nothing but leave tr as null
+ // probably due to changes made on another thread
+ }
+ }
+ String partitionType = (tr != null) ? tr.getType() : StructuredTextPartitioner.ST_UNKNOWN_PARTITION;
+ return createKey(partitionType, scope);
+ }
+
+ public IReconcileAnnotationKey createKey(String partitionType, int scope) {
+ fPartitionTypes.add(partitionType);
+ return new ReconcileAnnotationKey(getParentStep(), partitionType, scope);
+ }
+
+ public IStructuredReconcileStep getParentStep() {
+ return fParentStep;
+ }
+
+ public String[] getPartitionTypes() {
+ String[] results = new String[fPartitionTypes.size()];
+ System.arraycopy(fPartitionTypes.toArray(), 0, results, 0, results.length);
+ return results;
+ }
+
+ /**
+ * @see com.ibm.sed.model.INodeAdapter#isAdapterForType(java.lang.Object)
+ */
+ public boolean isAdapterForType(Object type) {
+ return type == IReconcileStepAdapter.class;
+ }
+
+ protected boolean isCanceled(IProgressMonitor monitor) {
+ return monitor != null && monitor.isCanceled();
+ }
+
+ /**
+ * @param notifier
+ */
+ public void markForReconciling(Object notifier) {
+ synchronized (fDirtyElements) {
+ // pa_TODO possible bottleneck
+ if (!fDirtyElements.contains(notifier)) {
+ Logger.trace(StructuredTextReconciler.TRACE_FILTER, "marking :" + notifier + ": for reconciling"); //$NON-NLS-1$ //$NON-NLS-2$
+ fDirtyElements.add(notifier);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.model.INodeAdapter#notifyChanged(com.ibm.sed.model.INodeNotifier,
+ * int, java.lang.Object, java.lang.Object, java.lang.Object, int)
+ */
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+ // Adapters are notified before the JFace Document events are sent to
+ // the IReconciler
+ markForReconciling(notifier);
+ }
+
+ public IReconcileResult[] reconcile(IProgressMonitor monitor, IndexedRegion xmlNode) {
+ List workingElements = null;
+ List results = new ArrayList();
+
+ IReconcileResult[] temp = EMPTY_RECONCILE_RESULT_SET;
+ synchronized (fDirtyElements) {
+ if (fDirtyElements != null && fDirtyElements.size() > 0) {
+ workingElements = new ArrayList();
+ workingElements.addAll(0, fDirtyElements);
+ fDirtyElements = new ArrayList();
+ }
+ }
+ if (workingElements != null) {
+ Iterator elements = workingElements.iterator();
+ while (elements.hasNext() && !isCanceled(monitor)) {
+ temp = reconcile(elements.next(), monitor);
+ for (int i = 0; i < temp.length; i++)
+ results.add(temp[i]);
+ }
+ }
+ temp = new IReconcileResult[results.size()];
+ System.arraycopy(results.toArray(), 0, temp, 0, results.size());
+ return temp;
+ }
+
+ protected IReconcileResult[] reconcile(Object o, IProgressMonitor monitor) {
+ return EMPTY_RECONCILE_RESULT_SET;
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.IReleasable#release()
+ */
+ public void release() {
+ // nothing to release
+ }
+
+ public void setParentStep(IStructuredReconcileStep parentStep) {
+ fParentStep = parentStep;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepAdapterForXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepAdapterForXML.java
new file mode 100644
index 0000000000..91cc0a70df
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepAdapterForXML.java
@@ -0,0 +1,720 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.reconcile;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMDocument;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.common.contentmodel.util.CMDocumentCacheListener;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.ui.IReleasable;
+import org.eclipse.wst.sse.ui.Logger;
+import org.eclipse.wst.sse.ui.StructuredTextReconciler;
+import org.eclipse.wst.sse.ui.internal.reconcile.IReconcileAnnotationKey;
+import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.core.document.XMLAttr;
+import org.eclipse.wst.xml.core.document.XMLElement;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.eclipse.wst.xml.ui.internal.correction.ProblemIDsXML;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+public class ReconcileStepAdapterForXML extends AbstractReconcileStepAdapter implements CMDocumentCacheListener, IReleasable {
+
+ /**
+ * Record of notification sent to this adapter. Will be queued up so
+ * they're not dealt with until reconciling is actually called from the
+ * reconciler thread.
+ */
+ public class NotificationEvent {
+
+ public Object changedFeature;
+
+ public int eventType;
+
+ public Object newValue;
+
+ public INodeNotifier notifier;
+
+ public Object oldValue;
+
+ public int pos;
+
+ public NotificationEvent(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+
+ this.notifier = notifier;
+ this.eventType = eventType;
+ this.changedFeature = changedFeature;
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ this.pos = pos;
+ }
+
+ // used (to see if notifications vector "contains()")
+ // so we don't queue up "duplicate" events,
+ // (indicates same eventType, notifier, and changedFeature)
+ public boolean equals(Object o) {
+
+ boolean result = false;
+ if (o instanceof NotificationEvent) {
+ NotificationEvent e2 = (NotificationEvent) o;
+ if (this.notifier == null || e2.notifier == null || this.changedFeature == null || e2.changedFeature == null) {
+ result = false;
+ }
+ result = (this.eventType == e2.eventType && this.notifier == e2.notifier && this.changedFeature == e2.changedFeature);
+ }
+ return result;
+ }
+ }
+
+ protected boolean fCaseSensitive = true;
+ protected CMDocumentCache fCMDocumentCache;
+ protected DocumentType fDocumentTypeForRefresh;
+
+ protected boolean fNeedsRefreshAll = false;
+
+ // required for thread safety
+ protected List fNotifications = new Vector();
+
+ // these are used in conjunction w/ cacheUpdated() notification
+ // in order to refresh the whole document
+ protected IProgressMonitor fProgressMonitorForRefresh;
+
+ // counter used for repeated reconcile opreations
+ // to yield the thread control to the next thread
+ // to improve workbench performance
+ protected short fReconcileCount = 0;
+
+ // will not attempt to validate attribute names starting with the
+ // following:
+ protected String[] ignoreAttributeNamesStartingWith = new String[]{"xmlns", "xsi:", "xml:"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ // changing these elements may have an impact on the current content model
+ // (which suggests to mark everything dirty)
+ protected String[] mayImpactContentModel = new String[]{"DOCTYPE", "xmlns", "xsi", "xmlns:xsi", "xmlns:xsl", "xsi:schemaLocation", "taglib"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+ protected String SEVERITY_MISSING_REQUIRED_ATTR = TemporaryAnnotation.ANNOT_WARNING;
+
+ // severities for the problems discoverable by this reconciler; possibly
+ // user configurable later
+ protected String SEVERITY_STRUCTURE = TemporaryAnnotation.ANNOT_ERROR;
+ protected String SEVERITY_UNKNOWN_ATTR = TemporaryAnnotation.ANNOT_ERROR;
+ protected String SEVERITY_UNKNOWN_ELEMENT = TemporaryAnnotation.ANNOT_ERROR;
+
+ public ReconcileStepAdapterForXML() {
+
+ super();
+ }
+
+ /**
+ * @see org.eclipse.wst.common.contentmodel.util.CMDocumentCacheListener#cacheCleared(org.eclipse.wst.common.contentmodel.utilbase.CMDocumentCache)
+ */
+ public void cacheCleared(CMDocumentCache arg0) {
+ // do nothing
+ }
+
+ /**
+ * @see org.eclipse.wst.common.contentmodel.util.CMDocumentCacheListener#cacheUpdated(org.eclipse.wst.common.contentmodel.utilbase.CMDocumentCache,
+ * java.lang.String, int, int,
+ * org.eclipse.wst.common.contentmodel.CMDocument)
+ */
+ public void cacheUpdated(CMDocumentCache arg0, String arg1, int arg2, int arg3, CMDocument arg4) {
+
+ // revalidate all
+ if (Logger.isTracing(StructuredTextReconciler.TRACE_FILTER)) {
+ String message = "[trace reconciler] > \r\n====================" + "\n cache updated:" + "\n arg0 :" + arg0 + "\n arg1 :" + arg1 + "\n arg3 :" + arg3 + "\n arg4 :" + arg4; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+ Logger.trace(StructuredTextReconciler.TRACE_FILTER, message);
+ }
+ if (arg3 == CMDocumentCache.STATUS_LOADED) {
+ Logger.trace(StructuredTextReconciler.TRACE_FILTER, "CMDocument finished loading :" + arg1); //$NON-NLS-1$
+ doRefreshAll((INodeNotifier) fDocumentTypeForRefresh, fProgressMonitorForRefresh);
+ }
+ }
+
+ protected IReconcileResult[] doRefreshAll(INodeNotifier notifier, IProgressMonitor monitor) {
+
+ Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] > refreshing all"); //$NON-NLS-1$
+
+ synchronized (fDirtyElements) {
+ fDirtyElements.clear();
+ }
+ Document doc = (((Node) notifier).getNodeType() != Node.DOCUMENT_NODE) ? ((Node) notifier).getOwnerDocument() : (Document) notifier;
+ return reconcileSubtree((INodeNotifier) doc, monitor);
+ }
+
+ protected ModelQuery getModelQuery(Node node) {
+
+ return (node.getNodeType() == Node.DOCUMENT_NODE) ? ModelQueryUtil.getModelQuery((Document) node) : ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+ }
+
+ /**
+ * returns a list of required CMAttributeDeclarations for the given
+ * element.
+ *
+ * @param elementDecl
+ * @return
+ */
+ protected List getRequiredAttributes(CMElementDeclaration elementDecl) {
+
+ CMNamedNodeMap attrMap = elementDecl.getAttributes();
+ Iterator it = attrMap.iterator();
+ CMAttributeDeclaration attr = null;
+ List result = new ArrayList();
+ while (it.hasNext()) {
+ attr = (CMAttributeDeclaration) it.next();
+ if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
+ result.add(attr);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Determine if this Document is an XML/XHTML Document and whether to be
+ * case sensitive
+ */
+ protected boolean isCaseSensitive(Node node) {
+
+ return true;
+ }
+
+ // CMVC 254838
+ /**
+ * Indicates if the element is not in the ContentModel (if it's not in the
+ * ContentModel, but its parent is)
+ *
+ * @param element
+ * @param modelQuery
+ * @return whether or not the element is unknown according to its
+ * associated ContentModel.
+ */
+ protected boolean isUnknown(Element element, ModelQuery modelQuery) {
+
+ boolean result = false;
+ CMElementDeclaration ed = modelQuery.getCMElementDeclaration(element);
+ if (ed == null) {
+ // make sure parent declaration exists, and is not inferred
+ Node parentNode = element.getParentNode();
+ if (parentNode != null && parentNode.getNodeType() == Node.ELEMENT_NODE) {
+ CMElementDeclaration parentEd = modelQuery.getCMElementDeclaration((Element) parentNode);
+ // 2/19/04 porting iFix for lax schema suppport
+ result = (parentEd != null) && !Boolean.TRUE.equals(parentEd.getProperty("isInferred")) //$NON-NLS-1$
+ && !Boolean.TRUE.equals(parentEd.getProperty("isLax")); //$NON-NLS-1$
+ }
+ // need one error for the root at least
+ // to indicate the document is wrong...
+ Document ownerDoc = element.getOwnerDocument();
+ if (ownerDoc != null && ownerDoc.getDocumentElement() == element) {
+ CMDocument cmDoc = modelQuery.getCorrespondingCMDocument(ownerDoc);
+ result = (cmDoc != null && cmDoc.getElements().getLength() > 0);
+ }
+ } else {
+ if (ed.getProperty("isInferred") != null && Boolean.TRUE.equals(ed.getProperty("isInferred")) //$NON-NLS-1$ //$NON-NLS-2$
+ || (ed.getProperty("partialContentModel") != null && Boolean.TRUE.equals(ed.getProperty("partialContentModel")))) { //$NON-NLS-1$ //$NON-NLS-2$
+ result = false;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Checks if name matches any mayImpactContentModel[] strings
+ *
+ * @param name
+ * @return if a match is found, return true, else return false
+ */
+ private boolean mayAffectContentModel(String name) {
+
+ // TODO (pa) may need to be smarter if the attribute name is broken...
+ StringTokenizer st = new StringTokenizer(name, ":", false); //$NON-NLS-1$
+ String prefix = ""; //$NON-NLS-1$
+ if (st.hasMoreTokens())
+ prefix = st.nextToken();
+ for (int i = 0; i < mayImpactContentModel.length; i++) {
+ if (mayImpactContentModel[i].indexOf(name) != -1 || mayImpactContentModel[i].startsWith(prefix))
+ return true;
+ }
+ return false;
+ }
+
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+
+ synchronized (fNotifications) {
+ NotificationEvent newEvent = new NotificationEvent(notifier, eventType, changedFeature, oldValue, newValue, pos);
+ if (!fNotifications.contains(newEvent))
+ fNotifications.add(newEvent);
+ }
+ }
+
+ /**
+ * @see com.ibm.sed.model.INodeAdapter#notifyChanged(com.ibm.sed.model.Notifier,
+ * int, java.lang.Object, java.lang.Object, java.lang.Object, int)
+ */
+ public void processNotification(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos, IProgressMonitor monitor) {
+
+ if (isCanceled(monitor))
+ return;
+
+ // (nsd) pa_TODO: we need to mark more or widen the scope affected by
+ // the next reconcile() call
+ // TODO: Handle multi-Node changes from Doctype Declarations, Taglib
+ // directives,
+ // and schema and namespace related attributes (DOCTYPE, taglib,
+ // xmlns,
+ // xsi...)
+ // ** we currently don't get a notify on changed taglib...
+
+ // we're going to validate everything again anyways after
+ // proccessNotifications() has completed (in reconcile():
+ // processNotifications() > refreshAll()),
+ // no sense to do it here if we refreshingAll
+ if (fNeedsRefreshAll)
+ return;
+ if (eventType == INodeNotifier.CHANGE || eventType == INodeNotifier.REMOVE) {
+ if (changedFeature instanceof Node && ((Node) changedFeature).getNodeType() == Node.ATTRIBUTE_NODE) {
+ if (mayAffectContentModel(((Node) changedFeature).getNodeName())) {
+ fNeedsRefreshAll = true;
+ }
+ } else if (changedFeature instanceof Node && ((Node) changedFeature).getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ fNeedsRefreshAll = true;
+ } else if (notifier instanceof Node && ((Node) notifier).getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ fNeedsRefreshAll = true;
+ } else {
+ // pa_TODO need to handle taglib definition changes...
+ //if(mayAffectContentModel(((Node)changedFeature).getNodeName()))
+ // {
+ //System.out.println("dunno what changed > " +
+ // changedFeature);
+ //fNeedsRefreshAll = true;
+ //}
+ }
+ if (isCanceled(monitor))
+ return;
+ fNeedsRefreshAll = true;
+ }
+ if (eventType == INodeNotifier.CHANGE && changedFeature instanceof Element) {
+ markForReconciling(changedFeature);
+ } else if (eventType == INodeNotifier.ADD && newValue instanceof Node) {
+ Node newNode = (Node) newValue;
+ if (newNode.getNodeType() == Node.DOCUMENT_TYPE_NODE || newNode.getNodeName().equals("jsp:directive.taglib")) { // $NON-NLS-1$
+ // //$NON-NLS-1$
+ fNeedsRefreshAll = true;
+ } else {
+ markForReconciling(newNode);
+ }
+ }
+ markForReconciling(notifier);
+ }
+
+ protected void processNotifications(IProgressMonitor monitor) {
+
+ fProgressMonitorForRefresh = monitor;
+ NotificationEvent[] events = null;
+ synchronized (fNotifications) {
+ if (fNotifications.isEmpty()) {
+ return;
+ }
+ events = (NotificationEvent[]) fNotifications.toArray(new NotificationEvent[0]);
+ fNotifications.clear();
+ }
+ for (int i = 0; i < events.length; i++) {
+ processNotification(events[i].notifier, events[i].eventType, events[i].changedFeature, events[i].oldValue, events[i].newValue, events[i].pos, monitor);
+ }
+ }
+
+ /**
+ * @see com.ibm.sed.internal.ui.text.ReconcilerAdapter#reconcile(org.eclipse.jface.text.source.IAnnotationModel,
+ * org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IReconcileResult[] reconcile(IProgressMonitor monitor, XMLNode xmlNode) {
+
+ processNotifications(monitor);
+ IReconcileResult[] results = EMPTY_RECONCILE_RESULT_SET;
+ if (fNeedsRefreshAll) {
+ results = doRefreshAll(xmlNode, monitor);
+ fNeedsRefreshAll = false;
+ } else {
+ results = super.reconcile(monitor, xmlNode);
+ }
+ return results;
+ }
+
+ /**
+ * Called by super.reconcile(IAnnotationModel) on each Notifier
+ *
+ * @see com.ibm.sed.internal.ui.text.AbstractReconcilerAdapter#reconcile(org.eclipse.jface.text.source.IAnnotationModel,
+ * java.lang.Object)
+ */
+ protected IReconcileResult[] reconcile(Object o, IProgressMonitor monitor) {
+
+ super.reconcile(o, monitor);
+ ModelQuery mq = null;
+ if (o instanceof XMLNode) {
+ XMLNode xmlNode = (XMLNode) o;
+ mq = getModelQuery(xmlNode);
+ if (mq != null) {
+ fCaseSensitive = isCaseSensitive(xmlNode);
+ return validate(mq, xmlNode);
+ }
+ }
+
+ // if we are in a large reconciling loop (like when reconciling the
+ // entire doc), this ensures
+ // that other Threads have a chance to run.
+ yieldIfNeeded();
+ return EMPTY_RECONCILE_RESULT_SET;
+ }
+
+ /**
+ * Reconcile the Node and all children of the Notifier passed in.
+ *
+ * @param notifier
+ * @param annotationModel
+ * @param monitor
+ */
+ protected IReconcileResult[] reconcileSubtree(INodeNotifier notifier, IProgressMonitor monitor) {
+
+ IReconcileResult[] temp = EMPTY_RECONCILE_RESULT_SET;
+ List results = new ArrayList();
+ if (!isCanceled(monitor)) {
+ if (notifier != null && notifier instanceof XMLNode) {
+ XMLNode current = (XMLNode) notifier;
+ // loop siblings
+ while (current != null) {
+ // mark whatever type nodes we wanna make dirty
+ if (current.getNodeType() == Node.ELEMENT_NODE || current.getNodeType() == Node.DOCUMENT_TYPE_NODE || current.getNodeType() == Node.DOCUMENT_NODE || current.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
+ temp = reconcile(current, monitor);
+ for (int i = 0; i < temp.length; i++)
+ results.add(temp[i]);
+ }
+ // drop one level deeper if necessary
+ if (current.getFirstChild() != null) {
+ temp = reconcileSubtree((INodeNotifier) current.getFirstChild(), monitor);
+ for (int i = 0; i < temp.length; i++)
+ results.add(temp[i]);
+ }
+ current = (XMLNode) current.getNextSibling();
+ }
+ }
+ temp = new IReconcileResult[results.size()];
+ System.arraycopy(results.toArray(), 0, temp, 0, results.size());
+ }
+ return temp;
+ }
+
+ /**
+ * Called from the ReconcileAdapterFactory
+ *
+ * @see com.ibm.sed.internal.ui.text.AbstractReconcilerAdapter#release()
+ */
+ public void release() {
+
+ if (fCMDocumentCache != null) {
+ fCMDocumentCache.removeListener(this);
+ fCMDocumentCache = null;
+ }
+ }
+
+ /**
+ * Determines whether the given Attr should not be validated according to
+ * the ignoreAttributeNamesStartingWith array
+ *
+ * @param attr
+ * @return
+ */
+ protected boolean shouldIgnore(Attr attr) {
+
+ boolean result = false;
+ String name = attr.getNodeName();
+ for (int i = 0; i < ignoreAttributeNamesStartingWith.length; i++) {
+ if (fCaseSensitive) {
+ if (name.startsWith(ignoreAttributeNamesStartingWith[i]))
+ result = true;
+ } else {
+ try {
+ if (name.length() >= ignoreAttributeNamesStartingWith[i].length() && ignoreAttributeNamesStartingWith[i].equalsIgnoreCase(name.substring(0, ignoreAttributeNamesStartingWith[i].length())))
+ result = true;
+ } catch (StringIndexOutOfBoundsException e) {
+ result = true;
+ }
+ }
+ }
+ return result;
+ }
+
+ private void updateCMDocumentCache(ModelQuery mq, XMLNode xmlNode) {
+
+ if (mq != null) {
+ CMDocumentManager cmDocManager = mq.getCMDocumentManager();
+ if (cmDocManager != null) {
+ CMDocumentCache newCache = cmDocManager.getCMDocumentCache();
+ if (newCache != null) {
+ if (fCMDocumentCache == null) {
+ // create fCMDocCache if necessary
+ fCMDocumentCache = newCache;
+ fCMDocumentCache.addListener(this);
+ fDocumentTypeForRefresh = (DocumentType) xmlNode;
+ } else if (fCMDocumentCache != newCache) {
+ fCMDocumentCache.removeListener(this);
+ fCMDocumentCache = newCache;
+ fCMDocumentCache.addListener(this);
+ fDocumentTypeForRefresh = (DocumentType) xmlNode;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Called by reconcile(IAnnotationModel, Object) when the Object is a
+ * Notifier
+ *
+ * @see com.ibm.sed.internal.editor.StructuredTextReconcilingStrategy#reconcile(org.eclipse.jface.text.source.IAnnotationModel,
+ * com.ibm.sed.model.IndexedRegion)
+ */
+ protected IReconcileResult[] validate(ModelQuery mq, XMLNode xmlNode) {
+
+ List results = new ArrayList();
+ if (xmlNode == null || !(xmlNode.getNodeType() == Node.ELEMENT_NODE || xmlNode.getNodeType() == Node.DOCUMENT_TYPE_NODE))
+ return EMPTY_RECONCILE_RESULT_SET;
+ // return early if the Node has gone stale
+ if (xmlNode.getParentNode() == null || xmlNode.getOwnerDocument() == null) {
+ return EMPTY_RECONCILE_RESULT_SET;
+ }
+ if (xmlNode.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ // sets CMDocumentCacheListener (this)
+ updateCMDocumentCache(mq, xmlNode);
+ }
+ CMDocument doc = mq.getCorrespondingCMDocument(xmlNode.getOwnerDocument());
+ // looks like this is a bad check to do... I thought we took it out
+ // before
+ // if(doc == null)
+ // return EMPTY_RECONCILE_RESULT_SET;
+ if (doc != null && doc.getElements().getLength() == 0) {
+ // an empty document
+ return EMPTY_RECONCILE_RESULT_SET;
+ }
+ // continue on null or FALSE; inferred grammars aren't predefined so
+ // there's no point in continuing
+ if (doc != null && doc.getProperty("isInferred") != null && Boolean.TRUE.equals(doc.getProperty("isInferred"))) { //$NON-NLS-1$ //$NON-NLS-2$
+ return EMPTY_RECONCILE_RESULT_SET;
+ }
+
+ // if xmlNode is DOCTYPE, skip to the first element
+ // if there are no elements, return (don't validate)
+ XMLNode elementNode = xmlNode;
+ if (xmlNode.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ boolean elementFound = false;
+ while ((elementNode = (XMLNode) elementNode.getNextSibling()) != null) {
+ if (elementNode.getNodeType() == Node.ELEMENT_NODE) {
+ elementFound = true;
+ break;
+ }
+ }
+ if (!elementFound)
+ return EMPTY_RECONCILE_RESULT_SET;
+ }
+ XMLElement element = (XMLElement) elementNode;
+ //boolean needsEndTag = true;
+
+ // test for a known element, if it's known, continue validating it
+ CMElementDeclaration elementDecl = mq.getCMElementDeclaration(element);
+ if (elementDecl != null) {
+ //needsEndTag = needsEndTag(elementNode, elementDecl);
+ NamedNodeMap attrs = element.getAttributes();
+ List reqAttrList = getRequiredAttributes(elementDecl);
+ for (int i = 0; i < attrs.getLength(); i++) {
+ XMLAttr attr = (XMLAttr) attrs.item(i);
+ if (!shouldIgnore(attr)) {
+
+ // iFix V511i
+ // CMVC 272647, attributes with namespace prefix get
+ // marked
+ // as error (even though they aren't)
+ //CMNode attrDecl =
+ // elementDecl.getAttributes().getNamedItem(attr.getNodeName());
+ CMNode attrDecl = elementDecl.getAttributes().getNamedItem(attr.getLocalName());
+
+ // test for a known attribute
+ if (attrDecl != null) {
+ // test for a known value (if there is an enumerated
+ // list of them)
+ String[] values = mq.getPossibleDataTypeValues(element, attrDecl);
+ String currentValue = attr.getValue();
+ boolean found = valueMatch(values, currentValue);
+ if (!found) {
+ int start = attr.getValueRegionStartOffset();
+ int length = attr.getValueRegion().getTextLength();
+ MessageFormat messageFormat = new MessageFormat(ResourceHandler.getString("Invalid_value_{0}")); //$NON-NLS-1$
+ Object[] args = {currentValue.trim()};
+ String message = messageFormat.format(args);
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(elementNode.getFirstStructuredDocumentRegion(), IReconcileAnnotationKey.PARTIAL);
+ results.add(new TemporaryAnnotation(p, SEVERITY_UNKNOWN_ATTR, message, key));
+ }
+ // remove from known required attribute list
+ reqAttrList.remove(attrDecl);
+ } else {
+ MessageFormat messageFormat = new MessageFormat(ResourceHandler.getString("Unknown_attribute_{0}")); //$NON-NLS-1$
+ Object[] args = {attr.getName()};
+ String message = messageFormat.format(args);
+ int start = attr.getNameRegionStartOffset();
+ int length = attr.getNameRegion().getTextLength();
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(elementNode.getFirstStructuredDocumentRegion(), IReconcileAnnotationKey.PARTIAL);
+ results.add(new TemporaryAnnotation(p, SEVERITY_UNKNOWN_ATTR, message, key, ProblemIDsXML.UnknownAttr));
+ }
+ } else {
+ // remove so we don't flag "ignored" attributes as missing
+ reqAttrList.remove(elementDecl.getAttributes().getNamedItem(attr.getNodeName()));
+ }
+ }
+ // if there are missing required attributes, create annotations
+ // for
+ // them
+ if (reqAttrList != null && !reqAttrList.isEmpty()) {
+ Iterator it = reqAttrList.iterator();
+ int start = 0;
+ int length = 1;
+ CMAttributeDeclaration attr = null;
+ while (it.hasNext()) {
+ attr = (CMAttributeDeclaration) it.next();
+ // sometimes getFirstStructuredDocumentRegion can return
+ // null, this is a safety
+ start = (element.getFirstStructuredDocumentRegion() != null) ? element.getFirstStructuredDocumentRegion().getStartOffset() : element.getStartOffset();
+ length = (element.getFirstStructuredDocumentRegion() != null) ? element.getFirstStructuredDocumentRegion().getLength() : 1;
+
+ MessageFormat messageFormat = new MessageFormat(ResourceHandler.getString("Missing_required_attribute_{0}")); //$NON-NLS-1$
+ Object[] args = {attr.getAttrName()};
+ String message = messageFormat.format(args);
+
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(elementNode.getFirstStructuredDocumentRegion(), IReconcileAnnotationKey.PARTIAL);
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_MISSING_REQUIRED_ATTR, message, key, ProblemIDsXML.MissingRequiredAttr);
+
+ IStructuredDocumentRegion startStructuredDocumentRegion = element.getStartStructuredDocumentRegion();
+ if (startStructuredDocumentRegion != null) {
+ String requiredAttrName = attr.getAttrName();
+ String defaultAttrValue = attr.getDefaultValue();
+ String insertString;
+ if (defaultAttrValue == null)
+ insertString = requiredAttrName + "=\"" + requiredAttrName + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+ else
+ insertString = requiredAttrName + "=\"" + defaultAttrValue + "\""; //$NON-NLS-1$ //$NON-NLS-2$
+
+ ITextRegion lastRegion = startStructuredDocumentRegion.getLastRegion();
+ int insertOffset = lastRegion.getEnd();
+ if (lastRegion.getEnd() == lastRegion.getTextEnd())
+ insertString = " " + insertString; //$NON-NLS-1$
+ if (lastRegion.getType() == XMLRegionContext.XML_TAG_CLOSE)
+ insertOffset = lastRegion.getStart();
+ Object[] additionalFixInfo = {insertString, new Integer(insertOffset)};
+ annotation.setAdditionalFixInfo(additionalFixInfo);
+ results.add(annotation);
+ }
+ }
+ }
+ } else if (isUnknown(element, mq)) { // CMVC 254838
+ int start = element.getStartOffset();
+ int length = element.getEndOffset() - element.getStartOffset();
+ if (element.getStartStructuredDocumentRegion() != null && element.getStartStructuredDocumentRegion().getNumberOfRegions() > 1) {
+ ITextRegion name = element.getStartStructuredDocumentRegion().getRegions().get(1);
+ start = element.getStartStructuredDocumentRegion().getStartOffset(name);
+ length = name.getTextLength();
+ }
+ MessageFormat messageFormat = new MessageFormat(ResourceHandler.getString("Unknown_element_{0}")); //$NON-NLS-1$
+ Object[] args = {element.getNodeName()};
+ String message = messageFormat.format(args);
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(elementNode.getFirstStructuredDocumentRegion(), IReconcileAnnotationKey.PARTIAL);
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_UNKNOWN_ELEMENT, message, key, ProblemIDsXML.UnknownElement);
+
+ // quick fix info
+ int startTagOffset = -1, startTagLength = -1, endTagOffset = -1, endTagLength = -1;
+ if (element.getStartStructuredDocumentRegion() != null) {
+ startTagOffset = element.getStartStructuredDocumentRegion().getStartOffset();
+ startTagLength = element.getStartStructuredDocumentRegion().getLength();
+ }
+ if (element.getEndStructuredDocumentRegion() != null) {
+ endTagOffset = element.getEndStructuredDocumentRegion().getStartOffset();
+ endTagLength = element.getEndStructuredDocumentRegion().getLength();
+ }
+ Object[] additionalFixInfo = {new Integer(startTagOffset), new Integer(startTagLength), new Integer(endTagOffset), new Integer(endTagLength)};
+
+ annotation.setAdditionalFixInfo(additionalFixInfo);
+ results.add(annotation);
+ }
+ IReconcileResult[] reconcileResults = new IReconcileResult[results.size()];
+ System.arraycopy(results.toArray(), 0, reconcileResults, 0, results.size());
+ return reconcileResults;
+ }
+
+ /**
+ * Determines if String value is within the values array given the current
+ * case sensitivity
+ *
+ * @param values
+ * @param value
+ * @return
+ */
+ protected boolean valueMatch(String[] values, String value) {
+
+ boolean found = (values == null || values.length == 0 || value.length() == 0);
+ for (int j = 0; j < values.length && !found; j++) {
+ if (fCaseSensitive) {
+ if (values[j].equals(value))
+ found = true;
+ } else if (values[j].equalsIgnoreCase(value))
+ found = true;
+ }
+ return found;
+ }
+
+ // CMVC 255301
+ // If we are in a large reconciling loop, this ensures
+ // that other Threads have a chance to run.
+ protected void yieldIfNeeded() {
+
+ // 100 is arbitrary, may need a better number
+ if (fReconcileCount >= 100) {
+ Thread.yield();
+ fReconcileCount = 0;
+ } else {
+ fReconcileCount++;
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepForContentModel.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepForContentModel.java
new file mode 100644
index 0000000000..2078296369
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepForContentModel.java
@@ -0,0 +1,234 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.reconcile;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.jface.text.reconciler.IReconcileStep;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.PropagatingAdapter;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.ui.Logger;
+import org.eclipse.wst.sse.ui.StructuredTextReconciler;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.reconcile.IReconcileAnnotationKey;
+import org.eclipse.wst.sse.ui.internal.reconcile.IReconcileStepAdapter;
+import org.eclipse.wst.sse.ui.internal.reconcile.StructuredReconcileStep;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+/**
+ * A reconcile step for ContentModel based documents.
+ */
+public class ReconcileStepForContentModel extends StructuredReconcileStep {
+ private HashSet fLocalPartitionTypes = null;
+
+ protected boolean fRanInitialValidate = false;
+
+ public ReconcileStepForContentModel() {
+ super();
+ fLocalPartitionTypes = new HashSet();
+ }
+
+ public ReconcileStepForContentModel(StructuredTextViewer viewer, IReconcileStep step) {
+ super(step);
+ fLocalPartitionTypes = new HashSet();
+ }
+
+ private void addPartitionTypes(String[] types) {
+ for (int i = 0; i < types.length; i++)
+ fLocalPartitionTypes.add(types[i]);
+ }
+
+ /**
+ * Need to add partition types for ReconcileStepAdapterForXML here...
+ *
+ * @see org.eclipse.wst.xml.ui.reconcile.StructuredReconcileStep#getPartitionTypes()
+ */
+ public String[] getPartitionTypes() {
+ String[] superPartitionTypes = super.getPartitionTypes();
+ String[] results = new String[superPartitionTypes.length + fLocalPartitionTypes.size()];
+ System.arraycopy(superPartitionTypes, 0, results, 0, superPartitionTypes.length);
+ System.arraycopy(fLocalPartitionTypes.toArray(), 0, results, superPartitionTypes.length, fLocalPartitionTypes.size());
+ return results;
+ }
+
+ public int getScope() {
+ return IReconcileAnnotationKey.PARTIAL;
+ }
+
+ public void initialValidate() {
+
+ // (pa) perf: add the adapter for every node here
+ XMLModel xModel = (XMLModel) getModelManager().getExistingModelForRead(getDocument());
+ XMLDocument doc = xModel.getDocument();
+ xModel.releaseFromRead();
+ PropagatingAdapter propagatingAdapter = (PropagatingAdapter) doc.getAdapterFor(PropagatingAdapter.class);
+
+ List factories = propagatingAdapter.getAdaptOnCreateFactories();
+ ReconcilerAdapterFactoryForXML rAdapterFactoryForXML = null;
+ AdapterFactory temp = null;
+ // find the ReconcileStepAdapterFactory
+ for (int i = 0; i < factories.size(); i++) {
+ temp = (AdapterFactory) factories.get(i);
+ if (temp.isFactoryForType(IReconcileStepAdapter.class)) {
+ rAdapterFactoryForXML = (ReconcilerAdapterFactoryForXML) temp;
+ break;
+ }
+ }
+
+ if (rAdapterFactoryForXML != null) {
+ rAdapterFactoryForXML.setShouldMarkForReconciling(false);
+ initialValidateTree(doc, rAdapterFactoryForXML);
+ rAdapterFactoryForXML.setShouldMarkForReconciling(true);
+ }
+ }
+
+ /**
+ * Mark the INodeNotifier (Node) and all children of the INodeNotifier
+ * passed in.
+ *
+ * @param notifier
+ */
+ protected void initialValidateTree(INodeNotifier notifier, AdapterFactory rAdapterFactoryForXML) {
+ if (isCanceled())
+ return;
+
+ if (notifier != null && notifier instanceof XMLNode) {
+ XMLNode current = (XMLNode) notifier;
+ IReconcileStepAdapter adapter = null;
+ // loop siblings
+ // pa_TODO for large XML files this loop goes for a LONG time
+ // and the progress monitor never gets canceled
+ while (current != null && !isCanceled()) {
+ // adapt this notifier
+ adapter = (IReconcileStepAdapter) rAdapterFactoryForXML.adapt(current);
+ if (adapter != null) {
+ ((AbstractReconcileStepAdapter) adapter).setParentStep(this);
+ adapter.markForReconciling(current);
+ current.addAdapter(adapter);
+ adapter.reconcile(getProgressMonitor(), current);
+ }
+ if (current.getFirstChild() != null) {
+ initialValidateTree((XMLNode) current.getFirstChild(), rAdapterFactoryForXML);
+ }
+ current = (XMLNode) current.getNextSibling();
+ }
+ }
+ }
+
+
+ // Determines whether the IStructuredDocumentRegion is a XML "end tag"
+ // since they're not allowed to have
+ // attribute ITextRegions
+ protected boolean isEndTag(IStructuredDocumentRegion structuredDocumentRegion) {
+ return structuredDocumentRegion.getFirstRegion().getType() == XMLRegionContext.XML_END_TAG_OPEN;
+ }
+
+ // Determines whether the IStructuredDocumentRegion is a XML "start tag"
+ // since they need to be
+ // checked for proper XML attribute region sequences
+ protected boolean isStartTag(IStructuredDocumentRegion structuredDocumentRegion) {
+ return structuredDocumentRegion.getFirstRegion().getType() == XMLRegionContext.XML_TAG_OPEN;
+ }
+
+ // Because we check the "proper" closing separately from attribute
+ // sequencing, we need to know what's
+ // an appropriate close.
+ protected boolean isTagCloseTextRegion(ITextRegion textRegion) {
+ return textRegion.getType() == XMLRegionContext.XML_TAG_CLOSE || textRegion.getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.internal.ui.text.StructuredReconcileStep#reconcileModel(org.eclipse.jface.text.reconciler.DirtyRegion,
+ * org.eclipse.jface.text.IRegion)
+ */
+ protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion, IRegion subRegion) {
+ if (dirtyRegion == null)
+ return EMPTY_RECONCILE_RESULT_SET;
+
+ // logging ------------------
+ Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] > reconciling model in CONTENT MODEL step w/ dirty region: [" + dirtyRegion.getOffset() + ":" + dirtyRegion.getLength() + "]" + dirtyRegion.getText()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ // --------------------------
+
+ int start = dirtyRegion.getOffset();
+ int length = dirtyRegion.getLength();
+
+ IReconcileResult[] results = validate(start, length);
+
+ // logging ------------------
+ Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] > CONTENT MODEL step done"); //$NON-NLS-1$
+ // --------------------------
+ return results;
+ }
+
+ /**
+ * Forces the IReconcilerAdapters for XMLNodes overlapping the given
+ * region to "validate" their Nodes.
+ *
+ * @param startOffset
+ * @param length
+ */
+ protected IReconcileResult[] validate(int startOffset, int length) {
+ List results = new ArrayList();
+ IReconcileResult[] temp = EMPTY_RECONCILE_RESULT_SET;
+
+ if (!fRanInitialValidate) {
+ initialValidate();
+ fRanInitialValidate = true;
+ } else {
+ XMLModel model = (XMLModel) getModelManager().getExistingModelForRead(getDocument());
+ int endOffset = startOffset + length;
+
+ IndexedRegion indexedNode = model.getIndexedRegion(startOffset);
+ IReconcileStepAdapter adapter = null;
+
+ // sometimes for single key type length can be 0 (startOffset ==
+ // endOffset)
+ for (int i = startOffset; indexedNode != null && i <= endOffset && !isCanceled(); i++) {
+
+ XMLNode xmlNode = (XMLNode) indexedNode;
+ adapter = (IReconcileStepAdapter) xmlNode.getAdapterFor(IReconcileStepAdapter.class);
+ if (adapter != null) {
+ temp = adapter.reconcile(getProgressMonitor(), xmlNode);
+ for (int j = 0; j < temp.length; j++)
+ results.add(temp[j]);
+ // this is for removal purposes later
+ addPartitionTypes(adapter.getPartitionTypes());
+ }
+ // visited.add(indexedNode);
+ if (xmlNode.getFirstStructuredDocumentRegion() != null)
+ i += xmlNode.getFirstStructuredDocumentRegion().getLength();
+ else
+ i++;
+
+ indexedNode = model.getIndexedRegion(i);
+ }
+ model.releaseFromRead();
+ }
+ return (IReconcileResult[]) results.toArray(new IReconcileResult[results.size()]);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepForMarkup.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepForMarkup.java
new file mode 100644
index 0000000000..07c8907a0d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcileStepForMarkup.java
@@ -0,0 +1,572 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.reconcile;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.jface.text.reconciler.IReconcileStep;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.sse.ui.Logger;
+import org.eclipse.wst.sse.ui.StructuredTextReconciler;
+import org.eclipse.wst.sse.ui.internal.reconcile.IReconcileAnnotationKey;
+import org.eclipse.wst.sse.ui.internal.reconcile.StructuredReconcileStep;
+import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.eclipse.wst.xml.ui.internal.correction.ProblemIDsXML;
+import org.w3c.dom.Node;
+
+
+/**
+ * Basic XML syntax checking step.
+ *
+ * @author pavery
+ */
+public class ReconcileStepForMarkup extends StructuredReconcileStep {
+ private String DQUOTE = "\""; //$NON-NLS-1$
+
+ protected String SEVERITY_ATTR_MISSING_VALUE = TemporaryAnnotation.ANNOT_ERROR;
+ protected String SEVERITY_ATTR_NO_VALUE = TemporaryAnnotation.ANNOT_ERROR;
+ // severities for the problems discoverable by this reconciler; possibly
+ // user configurable later
+ protected String SEVERITY_GENERIC_ILLFORMED_SYNTAX = TemporaryAnnotation.ANNOT_WARNING;
+ protected String SEVERITY_STRUCTURE = TemporaryAnnotation.ANNOT_ERROR;
+ protected String SEVERITY_SYNTAX_ERROR = TemporaryAnnotation.ANNOT_ERROR;
+ // used for attribute quote checking
+ private String SQUOTE = "'"; //$NON-NLS-1$
+
+ public ReconcileStepForMarkup() {
+ super();
+ }
+
+ public ReconcileStepForMarkup(IReconcileStep step) {
+ super(step);
+ }
+
+ private void addAttributeError(String message, String attributeValueText, int start, int length, int problemId, IStructuredDocumentRegion sdRegion, List results) {
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(sdRegion, getScope());
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_SYNTAX_ERROR, message, key, problemId);
+ annotation.setAdditionalFixInfo(attributeValueText);
+ results.add(annotation);
+ }
+
+ private void checkAttributesInEndTag(IStructuredDocumentRegion structuredDocumentRegion, List results) {
+ ITextRegionList textRegions = structuredDocumentRegion.getRegions();
+ int errorCount = 0;
+ int start = structuredDocumentRegion.getEndOffset();
+ int end = structuredDocumentRegion.getEndOffset();
+ for (int i = 0; i < textRegions.size() && errorCount < ELEMENT_ERROR_LIMIT; i++) {
+ ITextRegion textRegion = textRegions.get(i);
+ if (textRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME || textRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS || textRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+ if (start > structuredDocumentRegion.getStartOffset(textRegion))
+ start = structuredDocumentRegion.getStartOffset(textRegion);
+ end = structuredDocumentRegion.getEndOffset(textRegion);
+ errorCount++;
+ }
+ }
+ // create one error for all attributes in the end tag
+ if (errorCount > 0) {
+ Position p = new Position(start, end - start);
+ String message = ResourceHandler.getString("End_tag_has_attributes"); //$NON-NLS-1$
+ results.add(new TemporaryAnnotation(p, SEVERITY_GENERIC_ILLFORMED_SYNTAX, message, createKey(structuredDocumentRegion, getScope()), ProblemIDsXML.AttrsInEndTag));
+ }
+ }
+
+
+ /**
+ * @param structuredDocumentRegion
+ * @param results
+ */
+ private void checkClosingBracket(IStructuredDocumentRegion structuredDocumentRegion, List results) {
+ ITextRegionList regions = structuredDocumentRegion.getRegions();
+ ITextRegion r = null;
+ boolean closed = false;
+ for (int i = 0; i < regions.size(); i++) {
+ r = regions.get(i);
+ if (r.getType() == XMLRegionContext.XML_TAG_CLOSE || r.getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE)
+ closed = true;
+ }
+ if (!closed) {
+
+ String message = ResourceHandler.getString("ReconcileStepForMarkup.6"); //$NON-NLS-1$
+
+ int start = structuredDocumentRegion.getStartOffset();
+ int length = structuredDocumentRegion.getText().trim().length();
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(structuredDocumentRegion, getScope());
+
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_SYNTAX_ERROR, message, key, ProblemIDsXML.MissingClosingBracket);
+ results.add(annotation);
+ }
+ }
+
+ /**
+ * @param annotationModel
+ * @param structuredDocumentRegion
+ */
+ private void checkEmptyTag(IStructuredDocumentRegion structuredDocumentRegion, List results) {
+ // navigate to name
+ ITextRegionList regions = structuredDocumentRegion.getRegions();
+ if (regions.size() == 2) {
+ // missing name region
+ if (regions.get(0).getType() == XMLRegionContext.XML_TAG_OPEN && regions.get(1).getType() == XMLRegionContext.XML_TAG_CLOSE) {
+ String message = ResourceHandler.getString("ReconcileStepForMarkup.3"); //$NON-NLS-1$
+ int start = structuredDocumentRegion.getStartOffset();
+ int length = structuredDocumentRegion.getLength();
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(structuredDocumentRegion, getScope());
+
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_SYNTAX_ERROR, message, key, ProblemIDsXML.EmptyTag);
+ results.add(annotation);
+ }
+ }
+ }
+
+ private void checkForAttributeValue(IStructuredDocumentRegion structuredDocumentRegion, List results) {
+ // check for attributes without a value
+
+ // track the attribute/equals/value sequence using a state of 0, 1 ,2
+ // representing the name, =, and value, respectively
+ int attrState = 0;
+ ITextRegionList textRegions = structuredDocumentRegion.getRegions();
+ IReconcileAnnotationKey key = createKey(structuredDocumentRegion, getScope());
+ int errorCount = 0;
+ for (int i = 0; i < textRegions.size() && errorCount < ELEMENT_ERROR_LIMIT; i++) {
+ ITextRegion textRegion = textRegions.get(i);
+ if (textRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME || isTagCloseTextRegion(textRegion)) {
+ // dangling name and '='
+ if (attrState == 2 && i >= 2) {
+ // create annotation
+ ITextRegion nameRegion = textRegions.get(i - 2);
+ MessageFormat messageFormat = new MessageFormat(ResourceHandler.getString("Attribute_{0}_is_missing_a_value")); //$NON-NLS-1$
+ Object[] args = {structuredDocumentRegion.getText(nameRegion)};
+ String message = messageFormat.format(args);
+ int start = structuredDocumentRegion.getStartOffset(nameRegion);
+ int end = structuredDocumentRegion.getTextEndOffset(nameRegion);
+ Position p = new Position(start, end - start);
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_ATTR_MISSING_VALUE, message, key, ProblemIDsXML.MissingAttrValue);
+
+ // quick fix info
+ ITextRegion equalsRegion = textRegions.get(i - 2 + 1);
+ int insertOffset = structuredDocumentRegion.getTextEndOffset(equalsRegion) - end;
+ Object[] additionalFixInfo = {structuredDocumentRegion.getText(nameRegion), new Integer(insertOffset)};
+ annotation.setAdditionalFixInfo(additionalFixInfo);
+
+ results.add(annotation);
+ errorCount++;
+ }
+ // name but no '=' (XML only)
+ else if (attrState == 1 && i >= 1) {
+ // create annotation
+ ITextRegion previousRegion = textRegions.get(i - 1);
+ MessageFormat messageFormat = new MessageFormat(ResourceHandler.getString("Attribute_{0}_has_no_value")); //$NON-NLS-1$
+ Object[] args = {structuredDocumentRegion.getText(previousRegion)};
+ String message = messageFormat.format(args);
+ int start = structuredDocumentRegion.getStartOffset(previousRegion);
+ int end = structuredDocumentRegion.getTextEndOffset(previousRegion);
+ Position p = new Position(start, end - start);
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_ATTR_NO_VALUE, message, key, ProblemIDsXML.NoAttrValue);
+
+ // quick fix info
+ annotation.setAdditionalFixInfo(structuredDocumentRegion.getText(previousRegion));
+
+ results.add(annotation);
+ errorCount++;
+ }
+ attrState = 1;
+ } else if (textRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+ attrState = 2;
+ } else if (textRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
+ attrState = 0;
+ }
+ }
+
+ }
+
+ /**
+ * @param annotationModel
+ * @param structuredDocumentRegion
+ */
+ private void checkForSpaceBeforeName(IStructuredDocumentRegion structuredDocumentRegion, List results) {
+ String sdRegionText = structuredDocumentRegion.getFullText();
+ if (sdRegionText.startsWith(" ")) { //$NON-NLS-1$
+ IStructuredDocumentRegion prev = structuredDocumentRegion.getPrevious();
+ if (prev != null) {
+ // this is possibly the case of "< tag"
+ if (prev.getRegions().size() == 1 && isStartTag(prev)) {
+ // add the error for preceding space in tag name
+ String message = ResourceHandler.getString("ReconcileStepForMarkup.2"); //$NON-NLS-1$
+ int start = structuredDocumentRegion.getStartOffset();
+ // find length of whitespace
+ int length = sdRegionText.trim().equals("") ? sdRegionText.length() : sdRegionText.indexOf(sdRegionText.trim()); //$NON-NLS-1$
+
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(structuredDocumentRegion, getScope());
+
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_SYNTAX_ERROR, message, key, ProblemIDsXML.SpacesBeforeTagName);
+ results.add(annotation);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param annotationModel
+ * @param structuredDocumentRegion
+ */
+ private void checkNoNamespaceInPI(IStructuredDocumentRegion structuredDocumentRegion, List results) {
+ // navigate to name
+ ITextRegionList regions = structuredDocumentRegion.getRegions();
+ ITextRegion r = null;
+ int errorCount = 0;
+ for (int i = 0; i < regions.size() && errorCount < ELEMENT_ERROR_LIMIT; i++) {
+ r = regions.get(i);
+ if (r.getType() == XMLRegionContext.XML_TAG_NAME) {
+ String piText = structuredDocumentRegion.getText(r);
+ int index = piText.indexOf(":"); //$NON-NLS-1$
+ if (index != -1) {
+ String message = ResourceHandler.getString("ReconcileStepForMarkup.4"); //$NON-NLS-1$
+ int start = structuredDocumentRegion.getStartOffset(r) + index;
+ int length = piText.trim().length() - index;
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(structuredDocumentRegion, getScope());
+
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_SYNTAX_ERROR, message, key, ProblemIDsXML.NamespaceInPI);
+ results.add(annotation);
+ errorCount++;
+ }
+ }
+ }
+ }
+
+ /**
+ * @param structuredDocumentRegion
+ * @param results
+ */
+ private void checkQuotesForAttributeValues(IStructuredDocumentRegion structuredDocumentRegion, List results) {
+ ITextRegionList regions = structuredDocumentRegion.getRegions();
+ ITextRegion r = null;
+ String attrValueText = ""; //$NON-NLS-1$
+ int errorCount = 0;
+ for (int i = 0; i < regions.size() && errorCount < ELEMENT_ERROR_LIMIT; i++) {
+ r = regions.get(i);
+ if (r.getType() != XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+ continue;
+
+ attrValueText = structuredDocumentRegion.getText(r);
+ // attribute value includes quotes in the string
+ // split up attribute value on quotes
+ StringTokenizer st = new StringTokenizer(attrValueText, "\"'", true); //$NON-NLS-1$
+ int size = st.countTokens();
+ // get the pieces of the attribute value
+ String one = "", two = ""; //$NON-NLS-1$ //$NON-NLS-2$
+ if (size > 0)
+ one = st.nextToken();
+ if (size > 1)
+ two = st.nextToken();
+ if (size > 2) {
+ // should be handled by parsing...
+ // as in we can't have an attribute value like: <element
+ // attr="a"b"c"/>
+ // and <element attr='a"b"c' /> is legal
+ continue;
+ }
+
+
+ if (size == 1) {
+ if (one.equals(DQUOTE) || one.equals(SQUOTE)) {
+ // missing closing quote
+ String message = ResourceHandler.getString("ReconcileStepForMarkup.0"); //$NON-NLS-1$
+ addAttributeError(message, attrValueText, structuredDocumentRegion.getStartOffset(r), attrValueText.trim().length(), ProblemIDsXML.Unclassified, structuredDocumentRegion, results);
+ errorCount++;
+ } else {
+ // missing both
+ String message = ResourceHandler.getString("ReconcileStepForMarkup.1"); //$NON-NLS-1$
+ addAttributeError(message, attrValueText, structuredDocumentRegion.getStartOffset(r), attrValueText.trim().length(), ProblemIDsXML.AttrValueNotQuoted, structuredDocumentRegion, results);
+ errorCount++;
+ }
+ } else if (size == 2) {
+ if (one.equals(SQUOTE) && !two.equals(SQUOTE) || one.equals(DQUOTE) && !two.equals(DQUOTE)) {
+ // missing closing quote
+ String message = ResourceHandler.getString("ReconcileStepForMarkup.0"); //$NON-NLS-1$
+ addAttributeError(message, attrValueText, structuredDocumentRegion.getStartOffset(r), attrValueText.trim().length(), ProblemIDsXML.Unclassified, structuredDocumentRegion, results);
+ errorCount++;
+ }
+ }
+ }
+ // end of region for loop
+ }
+
+ private void checkStartEndTagPairs(IStructuredDocumentRegion sdRegion, List results) {
+ // check start/end tag pairs
+ XMLNode xmlNode = getXMLNode(sdRegion);
+ boolean selfClosed = false;
+ String tagName = null;
+ int length = 0;
+
+ if (xmlNode.isContainer()) {
+ IStructuredDocumentRegion endNode = xmlNode.getEndStructuredDocumentRegion();
+ if (endNode == null) {
+ // analyze the tag (check self closing)
+ ITextRegionList regions = xmlNode.getStartStructuredDocumentRegion().getRegions();
+ ITextRegion r = null;
+ for (int i = 0; i < regions.size(); i++) {
+ r = regions.get(i);
+ if (r.getType() == XMLRegionContext.XML_TAG_OPEN || r.getType() == XMLRegionContext.XML_TAG_CLOSE) {
+ length++;
+ } else if (r.getType() == XMLRegionContext.XML_TAG_NAME) {
+ tagName = sdRegion.getText(r);
+ length += tagName.length();
+ } else if (r.getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE) {
+ selfClosed = true;
+ }
+ }
+
+ if (!selfClosed && tagName != null) {
+ MessageFormat messageFormat = new MessageFormat(ResourceHandler.getString("Missing_end_tag_{0}")); //$NON-NLS-1$
+ Object[] args = {tagName};
+ String message = messageFormat.format(args);
+
+ int start = sdRegion.getStart();
+ Position p = new Position(start, length);
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_STRUCTURE, message, createKey(sdRegion, getScope()), ProblemIDsXML.MissingEndTag);
+
+ // quick fix info
+ String tagClose = "/>"; //$NON-NLS-1$
+ int tagCloseOffset = xmlNode.getFirstStructuredDocumentRegion().getEndOffset();
+ if (r != null && r.getType() == XMLRegionContext.XML_TAG_CLOSE) {
+ tagClose = "/"; //$NON-NLS-1$
+ tagCloseOffset--;
+ }
+ XMLNode firstChild = (XMLNode) xmlNode.getFirstChild();
+ while (firstChild != null && firstChild.getNodeType() == Node.TEXT_NODE) {
+ firstChild = (XMLNode) firstChild.getNextSibling();
+ }
+ int endOffset = xmlNode.getEndOffset();
+ int firstChildStartOffset = firstChild == null ? endOffset : firstChild.getStartOffset();
+ Object[] additionalFixInfo = {tagName, tagClose, new Integer(tagCloseOffset), new Integer(xmlNode.getFirstStructuredDocumentRegion().getEndOffset()), // startTagEndOffset
+ new Integer(firstChildStartOffset), // firstChildStartOffset
+ new Integer(endOffset)}; // endOffset
+ annotation.setAdditionalFixInfo(additionalFixInfo);
+
+ results.add(annotation);
+ }
+ }
+
+ }
+ }
+
+ /**
+ * @param annotationModel
+ * @param structuredDocumentRegion
+ */
+ private void checkStartingSpaceForPI(IStructuredDocumentRegion structuredDocumentRegion, List results) {
+ IStructuredDocumentRegion prev = structuredDocumentRegion.getPrevious();
+ if (prev != null) {
+ String prevText = prev.getFullText();
+ if (prev.getType() == XMLRegionContext.XML_CONTENT && prevText.endsWith(" ")) { //$NON-NLS-1$
+ String message = ResourceHandler.getString("ReconcileStepForMarkup.5"); //$NON-NLS-1$
+ int start = prev.getStartOffset();
+ int length = prev.getLength();
+ Position p = new Position(start, length);
+ IReconcileAnnotationKey key = createKey(structuredDocumentRegion, getScope());
+
+ TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_SYNTAX_ERROR, message, key, ProblemIDsXML.SpacesBeforePI);
+ results.add(annotation);
+ }
+ }
+ }
+
+ public int getScope() {
+ return IReconcileAnnotationKey.PARTIAL;
+ }
+
+ /**
+ * A DirtyRegion can span multiple StructuredDocumentRegions. This method
+ * returns the StructuredDocumentRegions in a given dirty region.
+ *
+ * @param dirtyRegion
+ */
+ private IStructuredDocumentRegion[] getStructuredDocumentRegions(DirtyRegion dirtyRegion) {
+ List regions = new ArrayList();
+ IStructuredDocumentRegion sdRegion = getStructuredDocument().getRegionAtCharacterOffset(dirtyRegion.getOffset());
+ if (sdRegion != null) {
+ if (!sdRegion.isDeleted())
+ regions.add(sdRegion);
+ while ((sdRegion = sdRegion.getNext()) != null && sdRegion.getEndOffset() <= getXMLNode(sdRegion).getEndOffset()) {
+ if (!sdRegion.isDeleted())
+ regions.add(sdRegion);
+ }
+ }
+ return (IStructuredDocumentRegion[]) regions.toArray(new IStructuredDocumentRegion[regions.size()]);
+ }
+
+ private XMLNode getXMLNode(IStructuredDocumentRegion sdRegion) {
+ XMLModel xModel = null;
+ XMLNode xmlNode = null;
+ // get/release models should always be in a try/finally block
+ try {
+ xModel = (XMLModel) getModelManager().getExistingModelForRead(getDocument());
+ // xModel is sometime null, when closing editor, for example
+ if (xModel != null) {
+ xmlNode = (XMLNode) xModel.getIndexedRegion(sdRegion.getStart());
+ }
+ } finally {
+ if (xModel != null) {
+ xModel.releaseFromRead();
+ }
+ }
+ return xmlNode;
+ }
+
+ /**
+ * Determines whether the IStructuredDocumentRegion is a XML "end tag"
+ * since they're not allowed to have attribute ITextRegions
+ *
+ * @param structuredDocumentRegion
+ * @return
+ */
+ private boolean isEndTag(IStructuredDocumentRegion structuredDocumentRegion) {
+ if (structuredDocumentRegion == null)
+ return false;
+ return structuredDocumentRegion.getFirstRegion().getType() == XMLRegionContext.XML_END_TAG_OPEN;
+ }
+
+ /**
+ * Determines if the IStructuredDocumentRegion is an XML Processing
+ * Instruction
+ *
+ * @param structuredDocumentRegion
+ * @return
+ */
+ private boolean isPI(IStructuredDocumentRegion structuredDocumentRegion) {
+ return structuredDocumentRegion.getFirstRegion().getType() == XMLRegionContext.XML_PI_OPEN;
+ }
+
+ /**
+ * Determines whether the IStructuredDocumentRegion is a XML "start tag"
+ * since they need to be checked for proper XML attribute region sequences
+ *
+ * @param structuredDocumentRegion
+ * @return
+ */
+ private boolean isStartTag(IStructuredDocumentRegion structuredDocumentRegion) {
+ if (structuredDocumentRegion == null)
+ return false;
+ return structuredDocumentRegion.getFirstRegion().getType() == XMLRegionContext.XML_TAG_OPEN;
+ }
+
+ // Because we check the "proper" closing separately from attribute
+ // sequencing, we need to know what's
+ // an appropriate close.
+ private boolean isTagCloseTextRegion(ITextRegion textRegion) {
+ return textRegion.getType() == XMLRegionContext.XML_TAG_CLOSE || textRegion.getType() == XMLRegionContext.XML_EMPTY_TAG_CLOSE;
+ }
+
+ /**
+ * Determines if the IStructuredDocumentRegion is XML Content
+ *
+ * @param structuredDocumentRegion
+ * @return
+ */
+ private boolean isXMLContent(IStructuredDocumentRegion structuredDocumentRegion) {
+ return structuredDocumentRegion.getFirstRegion().getType() == XMLRegionContext.XML_CONTENT;
+ }
+
+ /*
+ * check syntax of dirty region
+ */
+ protected IReconcileResult[] reconcile(IStructuredDocumentRegion structuredDocumentRegion) {
+ List results = new ArrayList();
+
+ // fix for https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=1939
+ // not sure why this was being done before
+ // if (structuredDocumentRegion.getType() ==
+ // XMLRegionContext.XML_CONTENT) {
+ // // rollback to an open tag
+ // // ** can this be bad? removal region must exactly match add region
+ // // or else we may get duplicates
+ // while ((structuredDocumentRegion =
+ // structuredDocumentRegion.getPrevious()) != null &&
+ // !isStartTag(structuredDocumentRegion)) {
+ // continue;
+ // }
+ // }
+ if (structuredDocumentRegion == null)
+ return EMPTY_RECONCILE_RESULT_SET;
+
+ if (isStartTag(structuredDocumentRegion)) {
+ // check for attributes without a value
+ checkForAttributeValue(structuredDocumentRegion, results);
+ // check if started tag is ended
+ checkStartEndTagPairs(structuredDocumentRegion, results);
+ // check empty tag <>
+ checkEmptyTag(structuredDocumentRegion, results);
+ // check that each attribute has quotes
+ checkQuotesForAttributeValues(structuredDocumentRegion, results);
+ // check that the closing '>' is there
+ checkClosingBracket(structuredDocumentRegion, results);
+ } else if (isEndTag(structuredDocumentRegion)) {
+ checkAttributesInEndTag(structuredDocumentRegion, results);
+ // check that the closing '>' is there
+ checkClosingBracket(structuredDocumentRegion, results);
+ } else if (isPI(structuredDocumentRegion)) {
+ // check validity of processing instruction
+ checkStartingSpaceForPI(structuredDocumentRegion, results);
+ checkNoNamespaceInPI(structuredDocumentRegion, results);
+ } else if (isXMLContent(structuredDocumentRegion)) {
+ checkForSpaceBeforeName(structuredDocumentRegion, results);
+ }
+
+ return (IReconcileResult[]) results.toArray(new IReconcileResult[results.size()]);
+ }
+
+ /*
+ * @see org.eclipse.text.reconcilerpipe.AbstractReconcilePipeParticipant#reconcileModel(org.eclipse.jface.text.reconciler.DirtyRegion,
+ * org.eclipse.jface.text.IRegion)
+ */
+ protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion, IRegion subRegion) {
+ if (dirtyRegion == null)
+ return EMPTY_RECONCILE_RESULT_SET;
+ Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] > reconcile model in MARKUP step w/ dirty region: [" + dirtyRegion.getOffset() + ":" + dirtyRegion.getLength() + "]" + (dirtyRegion == null ? "null" : dirtyRegion.getText())); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ IReconcileResult[] results = EMPTY_RECONCILE_RESULT_SET;
+
+ // TODO: may need to add back some synch(doc) and/or synch(region[i])
+ // to
+ // be thread safe
+ IStructuredDocumentRegion[] regions = getStructuredDocumentRegions(dirtyRegion);
+ for (int i = 0; i < regions.length; i++) {
+ // the region may be irrelevant at this point
+ // if the user has deleted it
+ if (!regions[i].isDeleted()) {
+ results = merge(results, reconcile(regions[i]));
+ }
+ }
+
+ Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] > MARKUP step done"); //$NON-NLS-1$
+ return results;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcilerAdapterFactoryForXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcilerAdapterFactoryForXML.java
new file mode 100644
index 0000000000..9bb05141fc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/ReconcilerAdapterFactoryForXML.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.reconcile;
+
+import org.eclipse.wst.sse.core.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.ui.internal.reconcile.IReconcileStepAdapter;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class ReconcilerAdapterFactoryForXML extends AbstractAdapterFactory {
+
+ /**
+ * This flag governs whether or not this ReconcilerFactory is responsible
+ * for marking nodes "dirty" when an adapter is created for them. This is
+ * true on startup, then set to false thereafter.
+ */
+ protected boolean fShouldMarkForReconciling = false;
+
+ protected AbstractReconcileStepAdapter singleton = null;
+
+ public ReconcilerAdapterFactoryForXML() {
+ this(IReconcileStepAdapter.class, true);
+ }
+
+ /**
+ * @param adapterKey
+ * @param registerAdapters
+ */
+ public ReconcilerAdapterFactoryForXML(Object adapterKey, boolean registerAdapters) {
+ super(adapterKey, registerAdapters);
+ }
+
+ protected void adaptAll(Node top) {
+ int length = top.getChildNodes().getLength();
+ NodeList children = top.getChildNodes();
+ for (int i = 0; i < length; i++) {
+ adaptAll(children.item(i));
+ }
+ ((INodeNotifier) top).getAdapterFor(adapterKey);
+ }
+
+ public void adaptAll(XMLModel model) {
+ if (adapterKey != null)
+ adaptAll(model.getDocument());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.ibm.sed.model.AbstractAdapterFactory#createAdapter(com.ibm.sed.model.INodeNotifier)
+ */
+ protected INodeAdapter createAdapter(INodeNotifier target) {
+ if (target instanceof Node) {
+ Node nodeTarget = (Node) target;
+ if (nodeTarget.getNodeType() == Node.ELEMENT_NODE || nodeTarget.getNodeType() == Node.DOCUMENT_NODE || nodeTarget.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
+ if (singleton == null) {
+ this.singleton = new ReconcileStepAdapterForXML();
+ }
+ // (pa) perf: don't do this on initial startup
+ if (shouldMarkForReconciling())
+ singleton.markForReconciling(target);
+ return singleton;
+ }
+ }
+ return null;
+ }
+
+ public void release() {
+ if (this.singleton != null)
+ this.singleton.release();
+ }
+
+ public void setShouldMarkForReconciling(boolean should) {
+ fShouldMarkForReconciling = should;
+ }
+
+ public boolean shouldMarkForReconciling() {
+ return fShouldMarkForReconciling;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/StructuredTextReconcilingStrategyForContentModel.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/StructuredTextReconcilingStrategyForContentModel.java
new file mode 100644
index 0000000000..de6c0660c2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/StructuredTextReconcilingStrategyForContentModel.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.reconcile;
+
+import org.eclipse.jface.text.reconciler.IReconcileStep;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.ui.internal.reconcile.AbstractStructuredTextReconcilingStrategy;
+
+
+/**
+ *
+ * @author pavery
+ */
+public class StructuredTextReconcilingStrategyForContentModel extends AbstractStructuredTextReconcilingStrategy {
+
+ public StructuredTextReconcilingStrategyForContentModel(ITextEditor editor) {
+ super(editor);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.internal.ui.text.AbstractStructuredTextReconcilingStrategy#createReconcileSteps()
+ */
+ public void createReconcileSteps() {
+
+ IReconcileStep cmStep = new ReconcileStepForContentModel();
+ fFirstStep = new ReconcileStepForMarkup(cmStep);
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/StructuredTextReconcilingStrategyForMarkup.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/StructuredTextReconcilingStrategyForMarkup.java
new file mode 100644
index 0000000000..e4c0c2701a
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/reconcile/StructuredTextReconcilingStrategyForMarkup.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.reconcile;
+
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.wst.sse.ui.internal.reconcile.AbstractStructuredTextReconcilingStrategy;
+
+
+/**
+ *
+ * @author pavery
+ *
+ */
+public class StructuredTextReconcilingStrategyForMarkup extends AbstractStructuredTextReconcilingStrategy {
+
+ public StructuredTextReconcilingStrategyForMarkup(ITextEditor editor) {
+ super(editor);
+ }
+
+ public void createReconcileSteps() {
+ // only one step, to check syntax
+ fFirstStep = new ReconcileStepForMarkup();
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/registry/AdapterFactoryProviderForEmbeddedXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/registry/AdapterFactoryProviderForEmbeddedXML.java
new file mode 100644
index 0000000000..690355de54
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/registry/AdapterFactoryProviderForEmbeddedXML.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.registry;
+
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.ui.registry.embedded.EmbeddedAdapterFactoryProvider;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.modelhandler.EmbeddedXML;
+
+
+public class AdapterFactoryProviderForEmbeddedXML implements EmbeddedAdapterFactoryProvider {
+
+ /*
+ * @see AdapterFactoryProvider#addAdapterFactories(IStructuredModel)
+ */
+ public void addAdapterFactories(IStructuredModel structuredModel) {
+ if (structuredModel instanceof XMLModel) {
+ XMLDocument doc = ((XMLModel) structuredModel).getDocument();
+ }
+ }
+
+ /*
+ * @see AdapterFactoryProvider#isFor(ContentTypeDescription)
+ */
+ public boolean isFor(EmbeddedTypeHandler contentTypeDescription) {
+ return (contentTypeDescription instanceof EmbeddedXML);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/registry/AdapterFactoryProviderForXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/registry/AdapterFactoryProviderForXML.java
new file mode 100644
index 0000000000..18858c10c1
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/registry/AdapterFactoryProviderForXML.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.registry;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.IFactoryRegistry;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.PropagatingAdapter;
+import org.eclipse.wst.sse.core.modelhandler.IDocumentTypeHandler;
+import org.eclipse.wst.sse.core.util.Assert;
+import org.eclipse.wst.sse.ui.preferences.CommonEditorPreferenceNames;
+import org.eclipse.wst.sse.ui.preferences.PreferenceKeyGenerator;
+import org.eclipse.wst.sse.ui.registry.AdapterFactoryProvider;
+import org.eclipse.wst.sse.ui.views.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.xml.core.document.XMLDocument;
+import org.eclipse.wst.xml.core.document.XMLModel;
+import org.eclipse.wst.xml.core.modelhandler.ModelHandlerForXML;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.DOMObserver;
+import org.eclipse.wst.xml.ui.reconcile.ReconcilerAdapterFactoryForXML;
+import org.eclipse.wst.xml.ui.views.contentoutline.JFaceNodeAdapterFactory;
+import org.eclipse.wst.xml.ui.views.properties.XMLPropertySourceAdapterFactory;
+
+
+/**
+ *
+ */
+public class AdapterFactoryProviderForXML implements AdapterFactoryProvider {
+
+ private final String EDITOR_PLUGIN_ID = "org.eclipse.wst.sse.ui"; // $NON-NLS-1$
+
+ // //$NON-NLS-1$
+
+ /*
+ * @see AdapterFactoryProvider#addAdapterFactories(IStructuredModel)
+ */
+ public void addAdapterFactories(IStructuredModel structuredModel) {
+
+ // add the normal content based factories to model's registry
+ addContentBasedFactories(structuredModel);
+ // Must update/add to propagating adapter here too
+
+ if (structuredModel instanceof XMLModel) {
+ addPropagatingAdapters(structuredModel);
+ }
+ }
+
+ protected void addContentBasedFactories(IStructuredModel structuredModel) {
+ IFactoryRegistry factoryRegistry = structuredModel.getFactoryRegistry();
+ Assert.isNotNull(factoryRegistry, "Program Error: client caller must ensure model has factory registry"); //$NON-NLS-1$
+ AdapterFactory factory = null;
+ // == this list came from the previous "XML only" list
+
+ // what was this still here? (6/4/03)
+ // I commented out on 6/4/03) but may have been something "extra"
+ // initializing
+ // old content assist adapter unnecessarily?
+ //factory =
+ // factoryRegistry.getFactoryFor(com.ibm.sed.edit.adapters.ContentAssistAdapter.class);
+
+ factory = factoryRegistry.getFactoryFor(IPropertySource.class);
+ if (factory == null) {
+ factory = new XMLPropertySourceAdapterFactory();
+ factoryRegistry.addFactory(factory);
+ }
+ factory = factoryRegistry.getFactoryFor(IJFaceNodeAdapter.class);
+ if (factory == null) {
+ factory = new JFaceNodeAdapterFactory();
+ factoryRegistry.addFactory(factory);
+ }
+
+ // cs... added for inferred grammar support
+ //
+ if (structuredModel != null) {
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(structuredModel);
+ if (modelQuery != null) {
+ CMDocumentManager documentManager = modelQuery.getCMDocumentManager();
+ if (documentManager != null) {
+ IPreferenceStore store = ((AbstractUIPlugin) Platform.getPlugin(EDITOR_PLUGIN_ID)).getPreferenceStore();
+ boolean useInferredGrammar = (store != null) ? store.getBoolean(PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.EDITOR_USE_INFERRED_GRAMMAR, IContentTypeIdentifier.ContentTypeID_SSEXML)) : true;
+
+ documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, true);
+ documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, false);
+ documentManager.setPropertyEnabled(CMDocumentManager.PROPERTY_USE_CACHED_RESOLVED_URI, true);
+ DOMObserver domObserver = new DOMObserver(structuredModel);
+ domObserver.setGrammarInferenceEnabled(useInferredGrammar);
+ domObserver.init();
+ }
+ }
+ }
+ }
+
+ protected void addPropagatingAdapters(IStructuredModel structuredModel) {
+ AdapterFactory factory;
+ XMLModel xmlModel = (XMLModel) structuredModel;
+ XMLDocument document = xmlModel.getDocument();
+ PropagatingAdapter propagatingAdapter = (PropagatingAdapter) document.getAdapterFor(PropagatingAdapter.class);
+ if (propagatingAdapter != null) {
+ // checking if we should bother adding this factory
+ // if the preference says not to check validity, we don't bother
+ // creating this factory
+ // to improve performance...
+ String contentTypeId = IContentTypeIdentifier.ContentTypeID_SSEXML;
+ IPreferenceStore store = ((AbstractUIPlugin) Platform.getPlugin(EDITOR_PLUGIN_ID)).getPreferenceStore();
+ if (store.getString(PreferenceKeyGenerator.generateKey(CommonEditorPreferenceNames.EDITOR_VALIDATION_METHOD, contentTypeId)).equals(CommonEditorPreferenceNames.EDITOR_VALIDATION_CONTENT_MODEL)) {
+ factory = new ReconcilerAdapterFactoryForXML();
+ propagatingAdapter.addAdaptOnCreateFactory(factory);
+ // (pa) perf:
+ //propagatingAdapter.initializeForFactory(factory,
+ // xmlModel.getDocument());
+ }
+ }
+ }
+
+
+ /*
+ * @see AdapterFactoryProvider#isFor(ContentTypeDescription)
+ */
+ public boolean isFor(IDocumentTypeHandler contentTypeDescription) {
+ return (contentTypeDescription instanceof ModelHandlerForXML);
+ }
+
+ public void reinitializeFactories(IStructuredModel structuredModel) {
+ // nothing to do, since no embedded type
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/style/IStyleConstantsXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/style/IStyleConstantsXML.java
new file mode 100644
index 0000000000..1164ca609d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/style/IStyleConstantsXML.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.style;
+
+/**
+ * Contains the symbolic name of styles used by LineStyleProvider,
+ * ColorManager, and any others who may be interested
+ */
+public interface IStyleConstantsXML {
+ public static final String BACKGROUND = "background"; //$NON-NLS-1$
+ public static final String CDATA_BORDER = "cdataBorder";//$NON-NLS-1$
+ public static final String CDATA_TEXT = "cdataText";//$NON-NLS-1$
+ public static final String COMMENT_BORDER = "commentBorder";//$NON-NLS-1$
+ public static final String COMMENT_TEXT = "commentText";//$NON-NLS-1$
+ public static final String DECL_BORDER = "declBoder";//$NON-NLS-1$
+ public static final String DOCTYPE_EXTERNAL_ID = "doctypeExternalId";//$NON-NLS-1$
+ public static final String DOCTYPE_EXTERNAL_ID_PUBREF = "doctypeExternalPubref";//$NON-NLS-1$
+ public static final String DOCTYPE_EXTERNAL_ID_SYSREF = "doctypeExtrenalSysref";//$NON-NLS-1$
+ public static final String DOCTYPE_NAME = "doctypeName";//$NON-NLS-1$
+
+ public static final String FOREGROUND = "foreground"; //$NON-NLS-1$
+ public static final String PI_BORDER = "piBorder";//$NON-NLS-1$
+ public static final String PI_CONTENT = "piContent";//$NON-NLS-1$
+
+ public static final String TAG_ATTRIBUTE_EQUALS = "tagAttributeEquals"; //$NON-NLS-1$
+ public static final String TAG_ATTRIBUTE_NAME = "tagAttributeName";//$NON-NLS-1$
+ public static final String TAG_ATTRIBUTE_VALUE = "tagAttributeValue";//$NON-NLS-1$
+ public static final String TAG_BORDER = "tagBorder";//$NON-NLS-1$
+ public static final String TAG_NAME = "tagName";//$NON-NLS-1$
+ public static final String XML_CONTENT = "xmlContent";//$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/style/LineStyleProviderForXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/style/LineStyleProviderForXML.java
new file mode 100644
index 0000000000..96c2b15f64
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/style/LineStyleProviderForXML.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.style;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.wst.common.encoding.content.IContentTypeIdentifier;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.ui.EditorPlugin;
+import org.eclipse.wst.sse.ui.preferences.PreferenceKeyGenerator;
+import org.eclipse.wst.sse.ui.style.AbstractLineStyleProvider;
+import org.eclipse.wst.sse.ui.style.LineStyleProvider;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class LineStyleProviderForXML extends AbstractLineStyleProvider implements LineStyleProvider {
+ public LineStyleProviderForXML() {
+ super();
+ loadColors();
+ }
+
+ protected void clearColors() {
+ getTextAttributes().clear();
+ }
+
+ protected TextAttribute getAttributeFor(ITextRegion region) {
+ /**
+ * a method to centralize all the "format rules" for regions
+ * specifically associated for how to "open" the region.
+ */
+ // not sure why this is coming through null, but just to catch it
+ if (region == null) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.CDATA_TEXT);
+ }
+ String type = region.getType();
+ if ((type == XMLRegionContext.XML_CONTENT) || (type == XMLRegionContext.XML_DOCTYPE_INTERNAL_SUBSET)) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.XML_CONTENT);
+ } else if ((type == XMLRegionContext.XML_TAG_OPEN) || (type == XMLRegionContext.XML_END_TAG_OPEN) || (type == XMLRegionContext.XML_TAG_CLOSE) || (type == XMLRegionContext.XML_EMPTY_TAG_CLOSE)) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_BORDER);
+ } else if ((type == XMLRegionContext.XML_CDATA_OPEN) || (type == XMLRegionContext.XML_CDATA_CLOSE)) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.CDATA_BORDER);
+ } else if (type == XMLRegionContext.XML_CDATA_TEXT) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.CDATA_TEXT);
+ } else if (type == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+ } else if (type == XMLRegionContext.XML_DOCTYPE_DECLARATION) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_NAME);
+ } else if (type == XMLRegionContext.XML_TAG_NAME) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_NAME);
+ } else if ((type == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+ } else if (type == XMLRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS);
+ } else if ((type == XMLRegionContext.XML_COMMENT_OPEN) || (type == XMLRegionContext.XML_COMMENT_CLOSE)) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.COMMENT_BORDER);
+ } else if (type == XMLRegionContext.XML_COMMENT_TEXT) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.COMMENT_TEXT);
+ } else if (type == XMLRegionContext.XML_DOCTYPE_NAME) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DOCTYPE_NAME);
+ } else if (type == XMLRegionContext.XML_PI_CONTENT) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.PI_CONTENT);
+ } else if ((type == XMLRegionContext.XML_PI_OPEN) || (type == XMLRegionContext.XML_PI_CLOSE)) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.PI_BORDER);
+ } else if ((type == XMLRegionContext.XML_DECLARATION_OPEN) || (type == XMLRegionContext.XML_DECLARATION_CLOSE)) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DECL_BORDER);
+ } else if (type == XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSREF) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+ } else if (type == XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBREF) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+ } else if (type == XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_PUBLIC || type == XMLRegionContext.XML_DOCTYPE_EXTERNAL_ID_SYSTEM) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+ } else if (type == XMLRegionContext.UNDEFINED) {
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.CDATA_TEXT);
+ } else if (type == XMLRegionContext.WHITE_SPACE) {
+ // white space is normall not on its own ... but when it is, we'll
+ // treat as content
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.XML_CONTENT);
+ } else if ((type == XMLRegionContext.XML_CHAR_REFERENCE) || (type == XMLRegionContext.XML_ENTITY_REFERENCE) || (type == XMLRegionContext.XML_PE_REFERENCE)) {
+ // we may want to character and entity references to have it own
+ // color in future,
+ // but for now, we'll make attribute value
+ return (TextAttribute) getTextAttributes().get(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+ } else {
+ // default, return null to signal "not handled"
+ // in which case, other factories should be tried
+ return null;
+ }
+ }
+
+ protected IPreferenceStore getColorPreferences() {
+ return EditorPlugin.getDefault().getPreferenceStore();
+ }
+
+ protected String getPreferenceKey(String key) {
+ String contentTypeId = IContentTypeIdentifier.ContentTypeID_SSEXML;
+ return PreferenceKeyGenerator.generateKey(key, contentTypeId);
+ }
+
+ protected void handlePropertyChange(PropertyChangeEvent event) {
+ String styleKey = null;
+
+ if (event != null) {
+ String prefKey = event.getProperty();
+ // check if preference changed is a style preference
+ if (getPreferenceKey(IStyleConstantsXML.TAG_NAME).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.TAG_NAME;
+ } else if (getPreferenceKey(IStyleConstantsXML.TAG_BORDER).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.TAG_BORDER;
+ } else if (getPreferenceKey(IStyleConstantsXML.TAG_ATTRIBUTE_NAME).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.TAG_ATTRIBUTE_NAME;
+ } else if (getPreferenceKey(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.TAG_ATTRIBUTE_VALUE;
+ } else if (getPreferenceKey(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS;
+ } else if (getPreferenceKey(IStyleConstantsXML.COMMENT_BORDER).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.COMMENT_BORDER;
+ } else if (getPreferenceKey(IStyleConstantsXML.COMMENT_TEXT).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.COMMENT_TEXT;
+ } else if (getPreferenceKey(IStyleConstantsXML.CDATA_BORDER).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.CDATA_BORDER;
+ } else if (getPreferenceKey(IStyleConstantsXML.CDATA_TEXT).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.CDATA_TEXT;
+ } else if (getPreferenceKey(IStyleConstantsXML.DECL_BORDER).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.DECL_BORDER;
+ } else if (getPreferenceKey(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.DOCTYPE_EXTERNAL_ID;
+ } else if (getPreferenceKey(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF;
+ } else if (getPreferenceKey(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF;
+ } else if (getPreferenceKey(IStyleConstantsXML.DOCTYPE_NAME).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.DOCTYPE_NAME;
+ } else if (getPreferenceKey(IStyleConstantsXML.PI_CONTENT).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.PI_CONTENT;
+ } else if (getPreferenceKey(IStyleConstantsXML.PI_BORDER).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.PI_BORDER;
+ } else if (getPreferenceKey(IStyleConstantsXML.XML_CONTENT).equals(prefKey)) {
+ styleKey = IStyleConstantsXML.XML_CONTENT;
+ }
+ }
+
+ if (styleKey != null) {
+ // overwrite style preference with new value
+ addTextAttribute(styleKey);
+ super.handlePropertyChange(event);
+ }
+ }
+
+ protected void loadColors() {
+ clearColors();
+
+ addTextAttribute(IStyleConstantsXML.TAG_NAME);
+ addTextAttribute(IStyleConstantsXML.TAG_BORDER);
+ addTextAttribute(IStyleConstantsXML.TAG_ATTRIBUTE_NAME);
+ addTextAttribute(IStyleConstantsXML.TAG_ATTRIBUTE_VALUE);
+ addTextAttribute(IStyleConstantsXML.TAG_ATTRIBUTE_EQUALS);
+ addTextAttribute(IStyleConstantsXML.COMMENT_BORDER);
+ addTextAttribute(IStyleConstantsXML.COMMENT_TEXT);
+ addTextAttribute(IStyleConstantsXML.CDATA_BORDER);
+ addTextAttribute(IStyleConstantsXML.CDATA_TEXT);
+ addTextAttribute(IStyleConstantsXML.DECL_BORDER);
+ addTextAttribute(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID);
+ addTextAttribute(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_PUBREF);
+ addTextAttribute(IStyleConstantsXML.DOCTYPE_EXTERNAL_ID_SYSREF);
+ addTextAttribute(IStyleConstantsXML.DOCTYPE_NAME);
+ addTextAttribute(IStyleConstantsXML.PI_CONTENT);
+ addTextAttribute(IStyleConstantsXML.PI_BORDER);
+ addTextAttribute(IStyleConstantsXML.XML_CONTENT);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/MarkupTagInfoProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/MarkupTagInfoProvider.java
new file mode 100644
index 0000000000..4409635fd0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/MarkupTagInfoProvider.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.taginfo;
+
+
+
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMDataType;
+import org.eclipse.wst.common.contentmodel.CMDocumentation;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.CMNodeList;
+import org.eclipse.wst.common.contentmodel.util.CMDescriptionBuilder;
+import org.eclipse.wst.sse.ui.nls.ResourceHandler;
+
+
+/**
+ * Provides basic tag information such as element/attribute name, data type,
+ * and tag info/documentation for CMNodes. Uses HTML to enhance presentation.
+ */
+public class MarkupTagInfoProvider {
+ protected final static String BOLD_END = "</b>"; //$NON-NLS-1$
+ protected final static String BOLD_START = "<b>"; //$NON-NLS-1$
+ protected final static String HEADING_END = "</h5>"; //$NON-NLS-1$
+ protected final static String HEADING_START = "<h5>"; //$NON-NLS-1$
+ protected final static String LIST_BEGIN = "<ul>"; //$NON-NLS-1$
+ protected final static String LIST_ELEMENT = "<li>"; //$NON-NLS-1$
+ protected final static String NEW_LINE = "<dl>"; //$NON-NLS-1$
+ protected final static String PARAGRAPH_END = "</p>"; //$NON-NLS-1$
+ protected final static String PARAGRAPH_START = "<p>"; //$NON-NLS-1$
+ protected final static String SPACE = " "; //$NON-NLS-1$
+
+ /**
+ * Returns basic tag information for display given a CMNode
+ *
+ * @param CMNode
+ * node - node to display information for
+ *
+ * @return String
+ */
+ public String getInfo(CMNode node) {
+ if (node == null)
+ return null;
+ StringBuffer sb = new StringBuffer();
+ // we assume that if there is tagInfo present, only display tagInfo
+ printTagInfo(sb, node);
+
+ // no tagInfo present, so try to display tag description
+ if (sb.length() == 0) {
+ printDescription(sb, node);
+ }
+
+ // no tag description present either, so display default info
+ if (sb.length() == 0) {
+ printDefaultInfo(node, sb);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Adds dataType's data type information, including enumerated type values
+ * to string buffer, sb
+ *
+ * @param StringBuffer
+ * sb - string to place data type info into
+ * @param CMDataType
+ * dataType - data type object to get info from (should not be
+ * null)
+ */
+ protected void printDataTypeInfo(StringBuffer sb, CMDataType dataType) {
+ String dataTypeName = dataType.getNodeName();
+ if ((dataTypeName != null) && (dataTypeName.length() > 0)) {
+ sb.append(PARAGRAPH_START + BOLD_START + ResourceHandler.getString("Data_Type____4") + SPACE + BOLD_END); //$NON-NLS-1$
+ sb.append(dataTypeName);
+ sb.append(PARAGRAPH_END);
+ }
+ String[] enumeratedValue = dataType.getEnumeratedValues();
+ if (enumeratedValue != null && enumeratedValue.length > 0) {
+ sb.append(PARAGRAPH_START + BOLD_START + ResourceHandler.getString("Enumerated_Values____5") + SPACE + BOLD_END); //$NON-NLS-1$
+ sb.append(LIST_BEGIN);
+ for (int i = 0; i < enumeratedValue.length; i++) {
+ sb.append(LIST_ELEMENT + enumeratedValue[i]);
+ }
+ sb.append(PARAGRAPH_END);
+ }
+ }
+
+ /**
+ * Adds the default info (element name, content model, data type) of
+ * CMNode to the string buffer, sb
+ *
+ * @param StringBuffer
+ * sb - string to place display info into
+ * @param CMNode
+ * node - node to get tag info from
+ */
+ protected void printDefaultInfo(CMNode node, StringBuffer sb) {
+ {
+
+ if (node.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+ CMElementDeclaration ed = (CMElementDeclaration) node;
+ sb.append(PARAGRAPH_START + BOLD_START + ResourceHandler.getString("Element____1") + SPACE + BOLD_END); //$NON-NLS-1$
+ sb.append(node.getNodeName());
+ sb.append(PARAGRAPH_END);
+ if (ed.getContentType() == CMElementDeclaration.PCDATA) {
+ CMDataType dataType = ed.getDataType();
+ if (dataType != null) {
+ printDataTypeInfo(sb, dataType);
+ }
+ } else {
+ CMDescriptionBuilder builder = new CMDescriptionBuilder();
+ String description = builder.buildDescription(node);
+ if ((description != null) && (description.length() > 0)) {
+ sb.append(PARAGRAPH_START + BOLD_START + ResourceHandler.getString("Content_Model____2") + SPACE + BOLD_END); //$NON-NLS-1$
+ sb.append(description + PARAGRAPH_END);
+ }
+ }
+ printDocumentation(sb, node);
+ } else if (node.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
+ CMAttributeDeclaration ad = (CMAttributeDeclaration) node;
+ sb.append(PARAGRAPH_START + BOLD_START + ResourceHandler.getString("Attribute____3") + SPACE + BOLD_END); //$NON-NLS-1$
+ sb.append(node.getNodeName());
+ sb.append(PARAGRAPH_END);
+ CMDataType dataType = ad.getAttrType();
+ if (dataType != null) {
+ printDataTypeInfo(sb, dataType);
+ }
+ printDocumentation(sb, node);
+ } else if (node.getNodeType() == CMNode.DATA_TYPE) {
+ sb.append(PARAGRAPH_START + BOLD_START + ResourceHandler.getString("Data_Type____4") + SPACE + BOLD_END); //$NON-NLS-1$
+ sb.append(node.getNodeName());
+ sb.append(PARAGRAPH_END);
+ printDocumentation(sb, node);
+ }
+ }
+ }
+
+ /**
+ * Adds the description property of the CMNode to the string buffer, sb
+ *
+ * @param StringBuffer
+ * sb - string to place display info into
+ * @param CMNode
+ * node - node to get tag description from
+ */
+ protected void printDescription(StringBuffer sb, CMNode node) {
+ String tagInfo = (String) node.getProperty("description"); //$NON-NLS-1$
+ if (tagInfo != null) {
+ sb.append(PARAGRAPH_START + tagInfo.trim() + PARAGRAPH_END);
+ }
+ }
+
+ /**
+ * Adds the tag documentation property of the CMNode to the string buffer,
+ * sb
+ *
+ * @param StringBuffer
+ * sb - string to place display info into
+ * @param CMNode
+ * node - node to get tag documentation from
+ */
+ protected void printDocumentation(StringBuffer sb, CMNode node) {
+ CMNodeList nodeList = (CMNodeList) node.getProperty("documentation"); //$NON-NLS-1$
+ if ((nodeList != null) && (nodeList.getLength() > 0)) {
+ sb.append(NEW_LINE);
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ CMDocumentation documentation = (CMDocumentation) nodeList.item(i);
+ String doc = documentation.getValue();
+ if (doc != null) {
+ sb.append(PARAGRAPH_START + doc.trim() + PARAGRAPH_END);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds the tag info property of the CMNode to the string buffer, sb
+ *
+ * @param StringBuffer
+ * sb - string to place display info into
+ * @param CMNode
+ * node - node to get tag info from
+ */
+ protected void printTagInfo(StringBuffer sb, CMNode node) {
+ String tagInfo = (String) node.getProperty("tagInfo"); //$NON-NLS-1$
+ if (tagInfo != null) {
+ sb.append(PARAGRAPH_START + tagInfo.trim() + PARAGRAPH_END);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLBestMatchHoverProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLBestMatchHoverProcessor.java
new file mode 100644
index 0000000000..fb93c7e348
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLBestMatchHoverProcessor.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.taginfo;
+
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.wst.sse.ui.taginfo.AbstractBestMatchHoverProcessor;
+
+
+/**
+ * Provides the best xml hover help documentation (by using other hover help
+ * processors) Priority of hover help processors is: ProblemHoverProcessor,
+ * XMLTagInfoHoverProcessor, AnnotationHoverProcessor
+ */
+public class XMLBestMatchHoverProcessor extends AbstractBestMatchHoverProcessor {
+ XMLTagInfoHoverProcessor fTagInfoHover;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.structured.taginfo.AbstractBestMatchHoverProcessor#getTagInfoHover()
+ */
+ protected ITextHover getTagInfoHover() {
+ if (fTagInfoHover == null) {
+ fTagInfoHover = new XMLTagInfoHoverProcessor();
+ }
+ return fTagInfoHover;
+ }
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLInformationProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLInformationProvider.java
new file mode 100644
index 0000000000..ae52fe9fe0
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLInformationProvider.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.taginfo;
+
+
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.IInformationProviderExtension;
+
+/**
+ * Provides context information for XML tags (Shows tooltip description)
+ *
+ * @author amywu
+ */
+public class XMLInformationProvider implements IInformationProvider, IInformationProviderExtension {
+
+ private XMLBestMatchHoverProcessor fTextHover = null;
+
+ public XMLInformationProvider() {
+ fTextHover = new XMLBestMatchHoverProcessor();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer,
+ * org.eclipse.jface.text.IRegion)
+ */
+ public String getInformation(ITextViewer textViewer, IRegion subject) {
+ return (String) getInformation2(textViewer, subject);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.information.IInformationProviderExtension#getInformation2(org.eclipse.jface.text.ITextViewer,
+ * org.eclipse.jface.text.IRegion)
+ */
+ public Object getInformation2(ITextViewer textViewer, IRegion subject) {
+ return fTextHover.getHoverInfo(textViewer, subject);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer,
+ * int)
+ */
+ public IRegion getSubject(ITextViewer textViewer, int offset) {
+ return fTextHover.getHoverRegion(textViewer, offset);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLTagInfoHoverProcessor.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLTagInfoHoverProcessor.java
new file mode 100644
index 0000000000..7638c93698
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/taginfo/XMLTagInfoHoverProcessor.java
@@ -0,0 +1,343 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.taginfo;
+
+
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.common.contentmodel.CMNode;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.common.contentmodel.util.DOMNamespaceHelper;
+import org.eclipse.wst.sse.core.IndexedRegion;
+import org.eclipse.wst.sse.core.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.sse.core.util.Debug;
+import org.eclipse.wst.sse.ui.Logger;
+import org.eclipse.wst.sse.ui.StructuredTextViewer;
+import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * Provides hover help documentation for xml tags
+ *
+ * @author amywu
+ * @see org.eclipse.jface.text.ITextHover
+ */
+public class XMLTagInfoHoverProcessor implements ITextHover {
+ protected MarkupTagInfoProvider fInfoProvider = null;
+
+ /**
+ * Constructor for XMLTextHoverProcessor.
+ */
+ public XMLTagInfoHoverProcessor() {
+ }
+
+ /**
+ * Retreives documentation to display in the hover help popup.
+ *
+ * @return String any documentation information to display
+ * <code>null</code> if there is nothing to display.
+ *
+ */
+ protected String computeHoverHelp(ITextViewer textViewer, int documentPosition) {
+ String result = null;
+
+ IndexedRegion treeNode = ContentAssistUtils.getNodeAt((StructuredTextViewer) textViewer, documentPosition);
+ if (treeNode == null)
+ return null;
+ Node node = (Node) treeNode;
+
+ while (node != null && node.getNodeType() == Node.TEXT_NODE && node.getParentNode() != null)
+ node = node.getParentNode();
+ XMLNode parentNode = (XMLNode) node;
+
+ IStructuredDocumentRegion flatNode = ((IStructuredDocument) textViewer.getDocument()).getRegionAtCharacterOffset(documentPosition);
+ if (flatNode != null) {
+ ITextRegion region = flatNode.getRegionAtCharacterOffset(documentPosition);
+ if (region != null) {
+ result = computeRegionHelp(treeNode, parentNode, flatNode, region);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Computes the hoverhelp based on region
+ *
+ * @return String hoverhelp
+ */
+ protected String computeRegionHelp(IndexedRegion treeNode, XMLNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) {
+ String result = null;
+ if (region == null)
+ return null;
+ String regionType = region.getType();
+ if (regionType == XMLRegionContext.XML_TAG_NAME)
+ result = computeTagNameHelp((XMLNode) treeNode, parentNode, flatNode, region);
+ else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME)
+ result = computeTagAttNameHelp((XMLNode) treeNode, parentNode, flatNode, region);
+ else if (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)
+ result = computeTagAttValueHelp((XMLNode) treeNode, parentNode, flatNode, region);
+ return result;
+ }
+
+ /**
+ * Computes the hover help for the attribute name
+ */
+ protected String computeTagAttNameHelp(XMLNode xmlnode, XMLNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) {
+ CMElementDeclaration elementDecl = getCMElementDeclaration(xmlnode);
+ String attName = flatNode.getText(region);
+ CMAttributeDeclaration attDecl = getCMAttributeDeclaration(elementDecl, attName);
+ return getAdditionalInfo(elementDecl, attDecl);
+ }
+
+ /**
+ * Computes the hover help for the attribute value (this is the same as
+ * the attribute name's help)
+ */
+ protected String computeTagAttValueHelp(XMLNode xmlnode, XMLNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) {
+ CMElementDeclaration elementDecl = getCMElementDeclaration(xmlnode);
+ ITextRegion attrNameRegion = getAttrNameRegion(xmlnode, region);
+
+ String attName = flatNode.getText(attrNameRegion);
+ CMAttributeDeclaration attDecl = getCMAttributeDeclaration(elementDecl, attName);
+ return getAdditionalInfo(elementDecl, attDecl);
+ }
+
+ /**
+ * Computes the hover help for the tag name
+ */
+ protected String computeTagNameHelp(XMLNode xmlnode, XMLNode parentNode, IStructuredDocumentRegion flatNode, ITextRegion region) {
+ CMElementDeclaration elementDecl = getCMElementDeclaration(xmlnode);
+ CMElementDeclaration pelementDecl = getCMElementDeclaration(parentNode);
+ return getAdditionalInfo(pelementDecl, elementDecl);
+ }
+
+ /**
+ * Retreives cmnode's documentation to display in the hover help popup. If
+ * no documentation exists for cmnode, try displaying parentOrOwner's
+ * documentation
+ *
+ * @return String any documentation information to display for cmnode.
+ * <code>null</code> if there is nothing to display.
+ */
+ protected String getAdditionalInfo(CMNode parentOrOwner, CMNode cmnode) {
+ String addlInfo = null;
+
+ if (cmnode == null) {
+ if (Debug.displayWarnings) {
+ new IllegalArgumentException("Null declaration!").printStackTrace(); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ addlInfo = getInfoProvider().getInfo(cmnode);
+ if (addlInfo == null && parentOrOwner != null)
+ addlInfo = getInfoProvider().getInfo(parentOrOwner);
+ return addlInfo;
+ }
+
+ /**
+ * Find the region of the attribute name for the given attribute value
+ * region
+ *
+ * @param XMLNode
+ * node - parent node
+ * @param ITextRegion
+ * region - region of attribute value
+ *
+ * @return region - attribute name region for given region
+ */
+ protected ITextRegion getAttrNameRegion(XMLNode node, ITextRegion region) {
+ // Find the attribute name for which this position should have a value
+ IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion();
+ ITextRegionList openRegions = open.getRegions();
+ int i = openRegions.indexOf(region);
+ if (i < 0)
+ return null;
+ ITextRegion nameRegion = null;
+ while (i >= 0) {
+ nameRegion = openRegions.get(i--);
+ if (nameRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME)
+ break;
+ }
+ return nameRegion;
+ }
+
+ /**
+ * Retreives CMAttributeDeclaration indicated by attribute name within
+ * elementDecl
+ */
+ protected CMAttributeDeclaration getCMAttributeDeclaration(CMElementDeclaration elementDecl, String attName) {
+ CMAttributeDeclaration attrDecl = null;
+
+ if (elementDecl != null) {
+ CMNamedNodeMap attributes = elementDecl.getAttributes();
+ String noprefixName = DOMNamespaceHelper.getUnprefixedName(attName);
+ if (attributes != null) {
+ attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(noprefixName);
+ if (attrDecl == null) {
+ attrDecl = (CMAttributeDeclaration) attributes.getNamedItem(attName);
+ }
+ }
+ }
+ return attrDecl;
+ }
+
+ /**
+ * Retreives CMElementDeclaration for given node
+ *
+ * @param Node
+ * node
+ *
+ * @return CMElementDeclaration - CMElementDeclaration of node or
+ * <code>null</code> if not possible
+ */
+ protected CMElementDeclaration getCMElementDeclaration(Node node) {
+ CMElementDeclaration result = null;
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(node.getOwnerDocument());
+ if (modelQuery != null)
+ result = modelQuery.getCMElementDeclaration((Element) node);
+ }
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer,
+ * org.eclipse.jface.text.IRegion)
+ */
+ public String getHoverInfo(ITextViewer viewer, IRegion hoverRegion) {
+ if ((hoverRegion == null) || (viewer == null) || (viewer.getDocument() == null))
+ return null;
+
+ String displayText = null;
+ int documentOffset = hoverRegion.getOffset();
+ displayText = computeHoverHelp(viewer, documentOffset);
+
+ return displayText;
+ }
+
+ /**
+ * Returns the region to hover the text over based on the offset.
+ *
+ * @param textViewer
+ * @param offset
+ *
+ * @return IRegion region to hover over if offset is within tag name,
+ * attribute name, or attribute value and if offset is not over
+ * invalid whitespace. otherwise, returns <code>null</code>
+ *
+ * @see ITextHover#getHoverRegion(ITextViewer, int)
+ */
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+ if ((textViewer == null) || (textViewer.getDocument() == null))
+ return null;
+
+ IStructuredDocumentRegion flatNode = ((IStructuredDocument) textViewer.getDocument()).getRegionAtCharacterOffset(offset);
+ ITextRegion region = null;
+
+ if (flatNode != null) {
+ region = flatNode.getRegionAtCharacterOffset(offset);
+ }
+
+ if (region != null) {
+ // only supply hoverhelp for tag name, attribute name, or
+ // attribute value
+ String regionType = region.getType();
+ if ((regionType == XMLRegionContext.XML_TAG_NAME) || (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) || (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+ try {
+ // check if we are at whitespace before or after line
+ IRegion line = textViewer.getDocument().getLineInformationOfOffset(offset);
+ if ((offset > (line.getOffset())) && (offset < (line.getOffset() + line.getLength()))) {
+ // check if we are in region's trailing whitespace
+ // (whitespace after relevant info)
+ if (offset < flatNode.getTextEndOffset(region)) {
+ return new Region(flatNode.getStartOffset(region), region.getTextLength());
+ }
+ }
+ } catch (BadLocationException e) {
+ Logger.logException(e);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @deprecated if enabled flag is false, dont call getHoverRegion in the
+ * first place if true, use getHoverRegion(ITextViewer, int)
+ */
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset, boolean enabled) {
+ if ((!enabled) || (textViewer == null) || (textViewer.getDocument() == null))
+ return null;
+
+ IStructuredDocumentRegion flatNode = ((IStructuredDocument) textViewer.getDocument()).getRegionAtCharacterOffset(offset);
+ ITextRegion region = null;
+
+ if (flatNode != null) {
+ region = flatNode.getRegionAtCharacterOffset(offset);
+ }
+
+ if (region != null) {
+ // only supply hoverhelp for tag name, attribute name, or
+ // attribute value
+ String regionType = region.getType();
+ if ((regionType == XMLRegionContext.XML_TAG_NAME) || (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) || (regionType == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE)) {
+ try {
+ // check if we are at whitespace before or after line
+ IRegion line = textViewer.getDocument().getLineInformationOfOffset(offset);
+ if ((offset > (line.getOffset())) && (offset < (line.getOffset() + line.getLength()))) {
+ // check if we are in region's trailing whitespace
+ // (whitespace after relevant info)
+ if (offset < flatNode.getTextEndOffset(region)) {
+ return new Region(flatNode.getStartOffset(region), region.getTextLength());
+ }
+ }
+ } catch (BadLocationException e) {
+ Logger.logException(e);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the infoProvider.
+ *
+ * @return Returns fInfoProvider and if fInfoProvider was
+ * <code>null</code> set fInfoProvider to DefaultInfoProvider
+ */
+ public MarkupTagInfoProvider getInfoProvider() {
+ if (fInfoProvider == null) {
+ fInfoProvider = new MarkupTagInfoProvider();
+ }
+ return fInfoProvider;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeIds.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeIds.java
new file mode 100644
index 0000000000..38e9db7cd2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeIds.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.templates;
+
+/**
+ * Contains a list of template context type ids
+ */
+public class TemplateContextTypeIds {
+ public static final String ALL = "all"; //$NON-NLS-1$
+ public static final String ATTRIBUTE = "attribute"; //$NON-NLS-1$
+ public static final String ATTRIBUTEVALUE = "attribute_value"; //$NON-NLS-1$
+ public static final String TAG = "tag"; //$NON-NLS-1$
+
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXML.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXML.java
new file mode 100644
index 0000000000..2174956774
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXML.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.templates;
+
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+
+/**
+ * Base class for XML template context types. Templates of this context type
+ * apply to any place within XML content type.
+ */
+public class TemplateContextTypeXML extends TemplateContextType {
+ public static final String XML_PREFIX = "xml_"; //$NON-NLS-1$
+
+ /**
+ * Generate a context type id that includes content type
+ *
+ * @param base_contextTypeId
+ * @return String
+ */
+ public static String generateContextTypeId(String base_contextTypeId) {
+ return XML_PREFIX + base_contextTypeId;
+ }
+
+ public TemplateContextTypeXML() {
+ this(generateContextTypeId(TemplateContextTypeIds.ALL), ResourceHandler.getString("TemplateContextTypeXML.0")); //$NON-NLS-1$
+ }
+
+ /**
+ * @param id
+ * @param name
+ */
+ public TemplateContextTypeXML(String id, String name) {
+ super(id, name);
+ addResolver(new GlobalTemplateVariables.Cursor());
+ addResolver(new GlobalTemplateVariables.Date());
+ addResolver(new GlobalTemplateVariables.Dollar());
+ addResolver(new GlobalTemplateVariables.LineSelection());
+ addResolver(new GlobalTemplateVariables.Time());
+ addResolver(new GlobalTemplateVariables.User());
+ addResolver(new GlobalTemplateVariables.WordSelection());
+ addResolver(new GlobalTemplateVariables.Year());
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLAttribute.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLAttribute.java
new file mode 100644
index 0000000000..faf4b6ef83
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLAttribute.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.templates;
+
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+/**
+ * Templates of this context type apply to any attributes within XML content
+ * type.
+ */
+public class TemplateContextTypeXMLAttribute extends TemplateContextTypeXML {
+
+ public TemplateContextTypeXMLAttribute() {
+ super(generateContextTypeId(TemplateContextTypeIds.ATTRIBUTE), ResourceHandler.getString("TemplateContextTypeXMLAttribute.0")); //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLAttributeValue.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLAttributeValue.java
new file mode 100644
index 0000000000..05d0708358
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLAttributeValue.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.templates;
+
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+/**
+ * Templates of this context type apply to any attribute values within XML
+ * content type.
+ */
+public class TemplateContextTypeXMLAttributeValue extends TemplateContextTypeXML {
+
+ public TemplateContextTypeXMLAttributeValue() {
+ super(generateContextTypeId(TemplateContextTypeIds.ATTRIBUTEVALUE), ResourceHandler.getString("TemplateContextTypeXMLAttributeValue.0")); //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLTag.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLTag.java
new file mode 100644
index 0000000000..4f6dbb9698
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/templates/TemplateContextTypeXMLTag.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.templates;
+
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+
+/**
+ * Templates of this context type apply to any tags within XML content type.
+ */
+public class TemplateContextTypeXMLTag extends TemplateContextTypeXML {
+
+ public TemplateContextTypeXMLTag() {
+ super(generateContextTypeId(TemplateContextTypeIds.TAG), ResourceHandler.getString("TemplateContextTypeXMLTag.0")); //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/text/XMLDocumentRegionEdgeMatcher.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/text/XMLDocumentRegionEdgeMatcher.java
new file mode 100644
index 0000000000..bad82e93fc
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/text/XMLDocumentRegionEdgeMatcher.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.text;
+
+import org.eclipse.wst.sse.ui.text.DocumentRegionEdgeMatcher;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+
+
+public class XMLDocumentRegionEdgeMatcher extends DocumentRegionEdgeMatcher {
+
+ /**
+ * @param validContexts
+ * @param nextMatcher
+ */
+ public XMLDocumentRegionEdgeMatcher() {
+ super(new String[]{XMLRegionContext.XML_TAG_NAME, XMLRegionContext.XML_COMMENT_TEXT, XMLRegionContext.XML_CDATA_TEXT, XMLRegionContext.XML_PI_OPEN, XMLRegionContext.XML_PI_CONTENT}, null);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/SharedXMLEditorPluginImageHelper.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/SharedXMLEditorPluginImageHelper.java
new file mode 100644
index 0000000000..81c8a4440c
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/SharedXMLEditorPluginImageHelper.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.util;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+
+
+public class SharedXMLEditorPluginImageHelper {
+ public static final String IMG_DTOOL_CONSTRAINOFF = XMLEditorPluginImages.IMG_DTOOL_CONSTRAINOFF;
+ public static final String IMG_DTOOL_CONSTRAINON = XMLEditorPluginImages.IMG_DTOOL_CONSTRAINON;
+ public static final String IMG_DTOOL_RLDGRMR = XMLEditorPluginImages.IMG_DTOOL_RLDGRMR;
+ public static final String IMG_DTOOL_VALIDATE = XMLEditorPluginImages.IMG_DTOOL_VALIDATE;
+ public static final String IMG_ETOOL_CONSTRAINOFF = XMLEditorPluginImages.IMG_ETOOL_CONSTRAINOFF;
+ public static final String IMG_ETOOL_CONSTRAINON = XMLEditorPluginImages.IMG_ETOOL_CONSTRAINON;
+ public static final String IMG_ETOOL_RLDGRMR = XMLEditorPluginImages.IMG_ETOOL_RLDGRMR;
+ public static final String IMG_ETOOL_VALIDATE = XMLEditorPluginImages.IMG_ETOOL_VALIDATE;
+ public static final String IMG_OBJ_ATTRIBUTE = XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE;
+ public static final String IMG_OBJ_CDATASECTION = XMLEditorPluginImages.IMG_OBJ_CDATASECTION;
+ public static final String IMG_OBJ_COMMENT = XMLEditorPluginImages.IMG_OBJ_COMMENT;
+ public static final String IMG_OBJ_DOCTYPE = XMLEditorPluginImages.IMG_OBJ_DOCTYPE;
+ public static final String IMG_OBJ_ELEMENT = XMLEditorPluginImages.IMG_OBJ_ELEMENT;
+ public static final String IMG_OBJ_ENTITY = XMLEditorPluginImages.IMG_OBJ_ENTITY;
+ public static final String IMG_OBJ_ENTITY_REFERENCE = XMLEditorPluginImages.IMG_OBJ_ENTITY_REFERENCE;
+ public static final String IMG_OBJ_NOTATION = XMLEditorPluginImages.IMG_OBJ_NOTATION;
+ public static final String IMG_OBJ_PROCESSINGINSTRUCTION = XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION;
+ public static final String IMG_OBJ_TAG_GENERIC = XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC;
+ public static final String IMG_OBJ_TAG_MACRO = XMLEditorPluginImages.IMG_OBJ_TAG_MACRO;
+ public static final String IMG_OBJ_TXTEXT = XMLEditorPluginImages.IMG_OBJ_TXTEXT;
+
+ /**
+ * Retrieves the specified image from the xml source editor plugin's image
+ * registry. Note: The returned <code>Image</code> is managed by the
+ * workbench; clients must <b>not </b> dispose of the returned image.
+ *
+ * @param symbolicName
+ * the symbolic name of the image; there are constants declared
+ * in this class for build-in images that come with the xml
+ * source editor
+ * @return the image, or <code>null</code> if not found
+ */
+ public static Image getImage(String symbolicName) {
+ return XMLEditorPluginImageHelper.getInstance().getImage(symbolicName);
+ }
+
+ /**
+ * Retrieves the image descriptor for specified image from the xml source
+ * editor plugin's image registry. Unlike <code>Image</code>s, image
+ * descriptors themselves do not need to be disposed.
+ *
+ * @param symbolicName
+ * the symbolic name of the image; there are constants declared
+ * in this interface for build-in images that come with the xml
+ * source editor
+ * @return the image descriptor, or <code>null</code> if not found
+ */
+ public static ImageDescriptor getImageDescriptor(String symbolicName) {
+ return XMLEditorPluginImageHelper.getInstance().getImageDescriptor(symbolicName);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/XMLCommonResources.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/XMLCommonResources.java
new file mode 100644
index 0000000000..4cb406d196
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/XMLCommonResources.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.util;
+
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.ui.views.markers.internal.ImageFactory;
+import org.eclipse.wst.xml.ui.XMLEditorPlugin;
+
+
+
+/**
+ * This class exists temporarily until the properties files can be
+ * re-organized and the various resource references can be updated
+ */
+public class XMLCommonResources {
+ protected static XMLCommonResources instance;
+
+ public synchronized static XMLCommonResources getInstance() {
+ if (instance == null)
+ instance = new XMLCommonResources(XMLEditorPlugin.getDefault());
+ return instance;
+ }
+
+ private XMLEditorPlugin editorPlugin;
+
+ protected ImageFactory imageFactory;
+ private ResourceBundle resourceBundle;
+
+ public XMLCommonResources(XMLEditorPlugin editorPlugin) {
+ instance = this;
+ this.editorPlugin = editorPlugin;
+ //imageFactory = new ImageFactory();
+ try {
+ resourceBundle = ResourceBundle.getBundle("EditingXML"); //$NON-NLS-1$
+ imageFactory = new ImageFactory();
+ } catch (java.util.MissingResourceException exception) {
+ //TODO... log an error message
+ //B2BUtilPlugin.getPlugin().getMsgLogger().write(B2BUtilPlugin.getGUIString("_WARN_PLUGIN_PROPERTIES_MISSING")
+ // + descriptor.getLabel());
+ resourceBundle = null;
+ }
+ }
+
+ ImageDescriptor _getImageDescriptor(String iconName) {
+ return AbstractUIPlugin.imageDescriptorFromPlugin(XMLEditorPlugin.ID, iconName);
+ }
+
+
+ public ResourceBundle getResourceBundle() {
+ return resourceBundle;
+ }
+
+ /**
+ * This gets the string resource.
+ */
+ public String getString(String key) {
+ return getResourceBundle().getString(key);
+ }
+
+ /**
+ * This gets the string resource and does one substitution.
+ */
+ public String getString(String key, Object s1) {
+ return MessageFormat.format(getString(key), new Object[]{s1});
+ }
+
+ /**
+ * This gets the string resource and does two substitutions.
+ */
+ public String getString(String key, Object s1, Object s2) {
+ return MessageFormat.format(getString(key), new Object[]{s1, s2});
+ }
+
+ public IWorkbench getWorkbench() {
+ return editorPlugin.getWorkbench();
+ }
+ /*
+ * public ImageFactory getImageFactory() { return imageFactory; }
+ */
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/XMLCommonUIContextIds.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/XMLCommonUIContextIds.java
new file mode 100644
index 0000000000..e421f2289b
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/util/XMLCommonUIContextIds.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+
+
+package org.eclipse.wst.xml.ui.util;
+
+/**
+ * Context help id constants.
+ */
+public interface XMLCommonUIContextIds {
+ public static final String PLUGIN_NAME = "com.ibm.etools.xml.common.ui"; //$NON-NLS-1$
+
+
+ /* CONTEXT_IDs for "Assign an XSL Stylesheet To The XML File" dialog */
+ /* CONTEXT_ID comn0010 for the dropdown menu. Follow comnxxxx */
+ public static final String XCUI_ASSIGN_XSL_TO_XML_DROPDOWN = PLUGIN_NAME + ".xcui1000"; //$NON-NLS-1$
+ /* CONTEXT_ID comn0030 for the import button. Follow comnxxxx */
+ public static final String XCUI_ASSIGN_XSL_TO_XML_IMPORT = PLUGIN_NAME + ".xcui3000"; //$NON-NLS-1$
+ /* CONTEXT_ID comn0020 for the workbench button. Follow comnxxxx */
+ public static final String XCUI_ASSIGN_XSL_TO_XML_WORKBENCH = PLUGIN_NAME + ".xcui2000"; //$NON-NLS-1$
+
+ /* CONTEXT_ID xcui0500 for Edit Attribute Instruction Dialog */
+ public static final String XCUI_ATTRIBUTE_DIALOG = PLUGIN_NAME + ".xcui0500"; //$NON-NLS-1$
+
+ /* CONTEXT_ID xcui0400 for Select XML Catalog ID Dialog */
+ public static final String XCUI_CATALOG_DIALOG = PLUGIN_NAME + ".xcui0400"; //$NON-NLS-1$
+
+ /* CONTEXT_IDs for XML Common UI use xcuixxx context IDs */
+
+ /* CONTEXT_ID xcui0010 for Edit Doctype Dialog */
+ public static final String XCUI_DOCTYPE_DIALOG = PLUGIN_NAME + ".xcui0010"; //$NON-NLS-1$
+ /* CONTEXT_ID xcui0030 for Public ID Text Edit */
+ public static final String XCUI_DOCTYPE_PUBLIC = PLUGIN_NAME + ".xcui0030"; //$NON-NLS-1$
+ /* CONTEXT_ID xcui0030 for Public ID Browse Button */
+ public static final String XCUI_DOCTYPE_PUBLIC_BROWSE = PLUGIN_NAME + ".xcui0040"; //$NON-NLS-1$
+ /* CONTEXT_ID xcui0020 for Root Element Name Text Edit */
+ public static final String XCUI_DOCTYPE_ROOT = PLUGIN_NAME + ".xcui0020"; //$NON-NLS-1$
+ /* CONTEXT_ID xcui0040 for System ID Text Edit */
+ public static final String XCUI_DOCTYPE_SYSTEM = PLUGIN_NAME + ".xcui0050"; //$NON-NLS-1$
+ /* CONTEXT_ID xcui0030 for System ID Browse Button */
+ public static final String XCUI_DOCTYPE_SYSTEM_BROWSE = PLUGIN_NAME + ".xcui0060"; //$NON-NLS-1$
+
+ /* CONTEXT_ID xcui0300 for Edit Element Instruction Dialog */
+ public static final String XCUI_ELEMENT_DIALOG = PLUGIN_NAME + ".xcui0600"; //$NON-NLS-1$
+
+ /* CONTEXT_ID xcui0200 for Edit Namespace Dialog */
+ public static final String XCUI_NAMESPACE_DIALOG = PLUGIN_NAME + ".xcui0200"; //$NON-NLS-1$
+
+ /* CONTEXT_ID xcui0300 for Edit Processing Instruction Dialog */
+ public static final String XCUI_PROCESSING_DIALOG = PLUGIN_NAME + ".xcui0300"; //$NON-NLS-1$
+
+ /* CONTEXT_ID xcui0100 for Edit Schema Information Dialog */
+ public static final String XCUI_SCHEMA_INFO_DIALOG = PLUGIN_NAME + ".xcui0100"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeAdapter.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeAdapter.java
new file mode 100644
index 0000000000..b98a918459
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeAdapter.java
@@ -0,0 +1,345 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.views.properties.PropertySheetPage;
+import org.eclipse.wst.common.contentmodel.CMDocument;
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManagerListener;
+import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.ui.views.contentoutline.BufferedOutlineUpdater;
+import org.eclipse.wst.sse.ui.views.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.sse.ui.views.contentoutline.IJFaceNodeAdapterFactory;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
+import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+import org.w3c.dom.Node;
+
+
+/**
+ * Adapts a DOM node to a JFace viewer.
+ */
+public class JFaceNodeAdapter implements IJFaceNodeAdapter {
+
+ public class CMDocumentManagerListenerImpl implements CMDocumentManagerListener {
+
+ List beingRefreshed = Collections.synchronizedList(new ArrayList());
+
+ public void cacheCleared(org.eclipse.wst.common.contentmodel.util.CMDocumentCache cache) {
+
+ }
+
+ public void cacheUpdated(CMDocumentCache cache, final String uri, int oldStatus, int newStatus, CMDocument cmDocument) {
+
+ if (newStatus == CMDocumentCache.STATUS_LOADED || newStatus == CMDocumentCache.STATUS_ERROR) {
+ refreshViewers();
+ }
+ }
+
+ private Display getDisplay() {
+
+ return PlatformUI.getWorkbench().getDisplay();
+ }
+
+ public void propertyChanged(CMDocumentManager cmDocumentManager, String propertyName) {
+
+ if (cmDocumentManager.getPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD)) {
+ refreshViewers();
+ }
+ }
+
+ protected void refreshViewers() {
+
+ // we're counting on getListers returning a "copy" of the
+ // listeners, so we'll be thread safe.
+ Collection listeners = ((IJFaceNodeAdapterFactory) adapterFactory).getListeners();
+ Iterator iterator = listeners.iterator();
+ while (iterator.hasNext()) {
+ Object listener = iterator.next();
+ // now that we use aynchExec, we ourselves have to gaurd
+ // against
+ // agains adding some refreshes when its already being
+ // refreshed.
+ if (listener instanceof PropertySheetPage && (!beingRefreshed.contains(listener))) {
+ final PropertySheetPage propertySheetPage = (PropertySheetPage) listener;
+ beingRefreshed.add(propertySheetPage);
+ getDisplay().asyncExec(new Runnable() {
+
+ public void run() {
+
+ if (getDisplay().isDisposed()) {
+ return;
+ }
+ if (propertySheetPage.getControl() != null && !propertySheetPage.getControl().isDisposed()) {
+ propertySheetPage.refresh();
+ beingRefreshed.remove(propertySheetPage);
+ }
+ }
+ });
+ }
+ }
+ }
+ }
+
+ final static Class ADAPTER_KEY = IJFaceNodeAdapter.class;
+
+ // for debugging
+ private static final boolean DEBUG;
+ static {
+ String value = Platform.getDebugOption("org.eclipse.wst.sse.ui/debug/outline"); //$NON-NLS-1$
+ DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+ }
+
+ protected AdapterFactory adapterFactory;
+ protected CMDocumentManagerListener cmDocumentManagerListener;
+ private BufferedOutlineUpdater fUpdater = null;
+
+ public JFaceNodeAdapter(AdapterFactory adapterFactory) {
+
+ super();
+ this.adapterFactory = adapterFactory;
+ }
+
+ protected Image createImage(Object object) {
+
+ Image image = null;
+ Node node = (Node) object;
+ switch (node.getNodeType()) {
+ case Node.ELEMENT_NODE : {
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ELEMENT);
+ break;
+ }
+ case Node.ATTRIBUTE_NODE : {
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE);
+ break;
+ }
+ case Node.TEXT_NODE : { // actually, TEXT should never be seen in
+ // the tree
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ELEMENT);
+ break;
+ }
+ case Node.CDATA_SECTION_NODE : {
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_CDATASECTION);
+ break;
+ }
+ case Node.ENTITY_REFERENCE_NODE :
+ case Node.ENTITY_NODE : {
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ENTITY);
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE : {
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_PROCESSINGINSTRUCTION);
+ break;
+ }
+ case Node.COMMENT_NODE : {
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_COMMENT);
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE : {
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_DOCTYPE);
+ break;
+ }
+ case Node.NOTATION_NODE : {
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_NOTATION);
+ break;
+ }
+ default : {
+ image = createXMLImageDescriptor(XMLEditorPluginImages.IMG_OBJ_ELEMENT);
+ break;
+ }
+ }
+ return image;
+ }
+
+ protected Image createXMLImageDescriptor(String imageResourceName) {
+ return XMLEditorPluginImageHelper.getInstance().getImage(imageResourceName);
+ }
+
+ public Object[] getChildren(Object object) {
+
+ // (pa) 20021217
+ // cmvc defect 235554
+ // performance enhancement: using child.getNextSibling() rather than
+ // nodeList(item) for O(n) vs. O(n*n)
+ //
+ Node node = (Node) object;
+ ArrayList v = new ArrayList(node.getChildNodes().getLength());
+ for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ Node n = child;
+ if (n.getNodeType() != Node.TEXT_NODE)
+ v.add(n);
+ }
+ return v.toArray();
+ }
+
+ /**
+ * Returns a CMDocumentManagerListener that can update JFace views when
+ * notified of CMDocumentManager events
+ */
+ public org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManagerListener getCMDocumentManagerListener() {
+
+ if (cmDocumentManagerListener == null)
+ cmDocumentManagerListener = new CMDocumentManagerListenerImpl();
+ return cmDocumentManagerListener;
+ }
+
+ Display getDisplay() {
+
+ // Note: the workbench should always have a display
+ // (unless running headless), whereas Display.getCurrent()
+ // only returns the display if the currently executing thread
+ // has one.
+ if (PlatformUI.isWorkbenchRunning())
+ return PlatformUI.getWorkbench().getDisplay();
+ else
+ return null;
+ }
+
+ /**
+ * Returns an enumeration with the elements belonging to the passed
+ * element. These are the top level items in a list, tree, table, etc...
+ */
+ public Object[] getElements(Object node) {
+
+ return getChildren(node);
+ }
+
+ /**
+ * Fetches the label image specific to this object instance.
+ */
+ public Image getLabelImage(Object node) {
+
+ Image image = null;
+ if (JFaceResources.getImageRegistry() != null) {
+ ImageRegistry imageRegistry = JFaceResources.getImageRegistry();
+ String nodeName = getNodeName(node);
+ image = imageRegistry.get(nodeName);
+ if (image == null) {
+ image = createImage(node);
+ if (image != null)
+ imageRegistry.put(nodeName, image);
+ }
+ }
+ return image;
+ }
+
+ /**
+ * Fetches the label text specific to this object instance.
+ */
+ public String getLabelText(Object node) {
+
+ return getNodeName(node);
+ }
+
+ private String getNodeName(Object object) {
+
+ Node node = (Node) object;
+ String nodeName = node.getNodeName();
+ if (node.getNodeType() == Node.DOCUMENT_TYPE_NODE)
+ nodeName = "DOCTYPE:" + nodeName; //$NON-NLS-1$
+ return nodeName;
+ }
+
+ private BufferedOutlineUpdater getOutlineUpdater() {
+ if (fUpdater == null)
+ fUpdater = new BufferedOutlineUpdater();
+ return fUpdater;
+ }
+
+ public Object getParent(Object object) {
+
+ Node node = (Node) object;
+ return node.getParentNode();
+ }
+
+ public boolean hasChildren(Object object) {
+
+ // (pa) 20021217
+ // cmvc defect 235554 > use child.getNextSibling() instead of
+ // nodeList(item) for O(n) vs. O(n*n)
+ Node node = (Node) object;
+ for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child.getNodeType() != Node.TEXT_NODE)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allowing the INodeAdapter to compare itself against the type allows it
+ * to return true in more than one case.
+ */
+ public boolean isAdapterForType(Object type) {
+
+ return type.equals(ADAPTER_KEY);
+ }
+
+ /**
+ * Called by the object being adapter (the notifier) when something has
+ * changed.
+ */
+ public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+
+ // future_TODO: the 'uijobs' used in this method were added to solve
+ // threading problems when the dom
+ // is updated in the background while the editor is open. They may be
+ // a bit overkill and not that useful.
+ // (That is, may be be worthy of job manager management). If they are
+ // found to be important enough to leave in,
+ // there's probably some optimization that can be done.
+ Collection listeners = ((JFaceNodeAdapterFactory) adapterFactory).getListeners();
+ Iterator iterator = listeners.iterator();
+
+ while (iterator.hasNext()) {
+ Object listener = iterator.next();
+ if (notifier instanceof Node && (listener instanceof StructuredViewer) && (eventType == INodeNotifier.STRUCTURE_CHANGED || (eventType == INodeNotifier.CHANGE && changedFeature == null))) {
+
+ if (DEBUG)
+ System.out.println("JFaceNodeAdapter notified on event type > " + eventType);
+
+ // refresh on structural and "unknown" changes
+ StructuredViewer structuredViewer = (StructuredViewer) listener;
+ // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=5230
+ if (structuredViewer.getControl() != null /*
+ * &&
+ * structuredViewer.getControl().isVisible()
+ */)
+ getOutlineUpdater().processNode(structuredViewer, (Node) notifier);
+ } else if ((listener instanceof PropertySheetPage) && ((eventType == INodeNotifier.CHANGE) || (eventType == INodeNotifier.STRUCTURE_CHANGED))) {
+ PropertySheetPage propertySheetPage = (PropertySheetPage) listener;
+ if (propertySheetPage.getControl() != null /*
+ * &&
+ * !propertySheetPage.getControl().isDisposed()
+ */) {
+ RefreshPropertySheetJob refreshPropertySheetJob = new RefreshPropertySheetJob(getDisplay(), ResourceHandler.getString("JFaceNodeAdapter.1"), propertySheetPage); //$NON-NLS-1$
+ refreshPropertySheetJob.schedule();
+ }
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeAdapterFactory.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeAdapterFactory.java
new file mode 100644
index 0000000000..c13860683e
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeAdapterFactory.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.core.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.modelquery.ModelQueryAdapter;
+import org.eclipse.wst.sse.ui.views.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.sse.ui.views.contentoutline.IJFaceNodeAdapterFactory;
+
+
+/**
+ * An adapter factory to create JFaceNodeAdapters. Use this adapter factory
+ * with a JFaceAdapterContentProvider to display DOM nodes in a tree.
+ */
+public class JFaceNodeAdapterFactory extends AbstractAdapterFactory implements IJFaceNodeAdapterFactory {
+ protected CMDocumentManager cmDocumentManager;
+ /**
+ * This keeps track of all the listeners.
+ */
+ protected ArrayList fListeners = new ArrayList();
+
+ protected INodeAdapter singletonAdapter;
+
+ public JFaceNodeAdapterFactory() {
+ this(IJFaceNodeAdapter.class, true);
+ }
+
+ public JFaceNodeAdapterFactory(Object adapterKey, boolean registerAdapters) {
+ super(adapterKey, registerAdapters);
+ }
+
+ public synchronized void addListener(Object listener) {
+ fListeners.add(listener);
+ }
+
+ public AdapterFactory copy() {
+
+ return new JFaceNodeAdapterFactory(this.adapterKey, this.shouldRegisterAdapter);
+ }
+
+ /**
+ * Create a new JFace adapter for the DOM node passed in
+ */
+ protected INodeAdapter createAdapter(INodeNotifier node) {
+ if (singletonAdapter == null) {
+ // create the JFaceNodeAdapter
+ singletonAdapter = new JFaceNodeAdapter(this);
+ initAdapter(singletonAdapter, node);
+ }
+ return singletonAdapter;
+ }
+
+ /**
+ * returns "copy" so no one can modify our list. Its is a shallow copy.
+ */
+ public synchronized Collection getListeners() {
+ return (Collection) fListeners.clone();
+ }
+
+ protected void initAdapter(INodeAdapter adapter, INodeNotifier node) {
+ // register for CMDocumentManager events
+ if (((JFaceNodeAdapter) adapter).getCMDocumentManagerListener() != null) {
+ ModelQueryAdapter mqadapter = (ModelQueryAdapter) node.getAdapterFor(ModelQueryAdapter.class);
+ if (mqadapter != null) {
+ ModelQuery mquery = mqadapter.getModelQuery();
+ if (mquery != null && mquery.getCMDocumentManager() != null) {
+ cmDocumentManager = mquery.getCMDocumentManager();
+ cmDocumentManager.addListener(((JFaceNodeAdapter) adapter).getCMDocumentManagerListener());
+ }
+ }
+ }
+ }
+
+ public void release() {
+ // deregister from CMDocumentManager events
+ if (cmDocumentManager != null && singletonAdapter != null && ((JFaceNodeAdapter) singletonAdapter).getCMDocumentManagerListener() != null) {
+ cmDocumentManager.removeListener(((JFaceNodeAdapter) singletonAdapter).getCMDocumentManagerListener());
+ }
+ }
+
+ public synchronized void removeListener(Object listener) {
+ fListeners.remove(listener);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeContentProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeContentProvider.java
new file mode 100644
index 0000000000..d6a121215f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeContentProvider.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.ui.views.contentoutline.IJFaceNodeAdapter;
+import org.eclipse.wst.xml.core.document.XMLModel;
+
+
+/**
+ * An ITreeContentProvider for a TreeViewers used to display DOM nodes. This
+ * content provider takes an adapter factory to create JFace adapters for the
+ * nodes in the tree.
+ */
+public class JFaceNodeContentProvider implements ITreeContentProvider {
+ protected AdapterFactory adapterFactory;
+
+ public JFaceNodeContentProvider(AdapterFactory jfaceAdapterFactory) {
+ super();
+ this.adapterFactory = jfaceAdapterFactory;
+ }
+
+ /**
+ * The visual part that is using this content provider is about to be
+ * disposed. Deallocate all allocated SWT resources.
+ */
+ public void dispose() {
+ }
+
+ /**
+ * Returns the JFace adapter for the specified object.
+ *
+ * @return com.ibm.sed.view.tree.DOMJFaceAdapter The JFace adapter
+ * @param adaptable
+ * java.lang.Object The object to get the adapter for
+ */
+ protected IJFaceNodeAdapter getAdapter(Object adaptable) {
+ if (adaptable instanceof INodeNotifier) {
+ INodeAdapter adapter = adapterFactory.adapt((INodeNotifier) adaptable);
+ if (adapter instanceof IJFaceNodeAdapter)
+ return (IJFaceNodeAdapter) adapter;
+ }
+ return null;
+ }
+
+ public Object[] getChildren(Object object) {
+ IJFaceNodeAdapter adapter = getAdapter(object);
+
+ if (adapter != null)
+ return adapter.getChildren(object);
+
+ return new Object[0];
+ }
+
+ public Object[] getElements(Object object) {
+ // The root is usually an instance of an XMLStructuredModel in
+ // which case we want to extract the document.
+ Object topNode = object;
+ if (object instanceof XMLModel)
+ topNode = ((XMLModel) object).getDocument();
+
+ IJFaceNodeAdapter adapter = getAdapter(topNode);
+
+ if (adapter != null)
+ return adapter.getElements(topNode);
+
+ return new Object[0];
+ }
+
+ public Object getParent(Object object) {
+ IJFaceNodeAdapter adapter = getAdapter(object);
+
+ if (adapter != null)
+ return adapter.getParent(object);
+
+ return null;
+ }
+
+ public boolean hasChildren(Object object) {
+ IJFaceNodeAdapter adapter = getAdapter(object);
+
+ if (adapter != null)
+ return adapter.hasChildren(object);
+
+ return false;
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeLabelProvider.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeLabelProvider.java
new file mode 100644
index 0000000000..bd94407b49
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/JFaceNodeLabelProvider.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.ui.views.contentoutline.IJFaceNodeAdapter;
+
+
+/**
+ * A class that uses a JFaceNodeAdapterFactory to provide adapters to provide
+ * the labels and images for DOM nodes.
+ */
+public class JFaceNodeLabelProvider implements ILabelProvider {
+
+ protected AdapterFactory adapterFactory;
+
+ /**
+ * JFaceNodeLabelProvider constructor comment.
+ */
+ public JFaceNodeLabelProvider(AdapterFactory adapterFactory) {
+ super();
+ this.adapterFactory = adapterFactory;
+ }
+
+ /**
+ * Adds a listener to the label provider. A label provider should inform
+ * its listener about state changes that enforces rendering of the visual
+ * part that uses this label provider.
+ */
+ public void addListener(ILabelProviderListener listener) {
+ // The label provider state never changes so we do not have
+ // to implement this method.
+ }
+
+ /**
+ * The visual part that is using this label provider is about to be
+ * disposed. Deallocate all allocated SWT resources.
+ */
+ public void dispose() {
+ // Nothing to dispose
+ }
+
+ /**
+ * Returns the JFace adapter for the specified object.
+ *
+ * @return com.ibm.sed.view.tree.DOMJFaceAdapter The JFace adapter
+ * @param adaptable
+ * java.lang.Object The object to get the adapter for
+ */
+ protected IJFaceNodeAdapter getAdapter(Object adaptable) {
+ return (IJFaceNodeAdapter) adapterFactory.adapt((INodeNotifier) adaptable);
+ }
+
+ /**
+ * Returns the image for the label of the given element, for use in the
+ * given viewer.
+ *
+ * @param viewer
+ * The viewer that displays the element.
+ * @param element
+ * The element for which to provide the label image. Element
+ * can be <code>null</code> indicating no input object is set
+ * to the viewer.
+ */
+ public Image getImage(Object element) {
+ return getAdapter(element).getLabelImage(element);
+ }
+
+ /**
+ * Returns the text for the label of the given element, for use in the
+ * given viewer.
+ *
+ * @param viewer
+ * The viewer that displays the element.
+ * @param element
+ * The element for which to provide the label text. Element can
+ * be <code>null</code> indicating no input object is set to
+ * the viewer.
+ */
+ public java.lang.String getText(Object element) {
+ // This was returning null, on occasion ... probably should not be,
+ // but
+ // took the quick and easy way out for now. (dmw 3/8/01)
+ String result = getAdapter(element).getLabelText(element);
+ if (result == null)
+ result = "";//$NON-NLS-1$
+ return result;
+ }
+
+ /**
+ * Checks whether this label provider is affected by the given domain
+ * event.
+ */
+ public boolean isAffected(Object dummy) {//DomainEvent event) {
+ //return event.isModifier(DomainEvent.NON_STRUCTURE_CHANGE);
+ return true;
+
+ }
+
+ /**
+ * Returns whether the label would be affected by a change to the given
+ * property of the given element. This can be used to optimize a
+ * non-structural viewer update. If the property mentioned in the update
+ * does not affect the label, then the viewer need not update the label.
+ *
+ * @param element
+ * the element
+ * @param property
+ * the property
+ * @return <code>true</code> if the label would be affected, and
+ * <code>false</code> if it would be unaffected
+ */
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ /**
+ * Removes a listener from the label provider.
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ // The label provider state never changes so we do not have
+ // to implement this method.
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/RefreshOutlineJob.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/RefreshOutlineJob.java
new file mode 100644
index 0000000000..570949a8ba
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/RefreshOutlineJob.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.w3c.dom.Node;
+
+
+
+public class RefreshOutlineJob extends UIJob {
+
+
+ private INodeNotifier fNodeNotifier;
+ private StructuredViewer fStructuredViewer;
+
+ /**
+ * @param jobDisplay
+ * @param name
+ */
+ public RefreshOutlineJob(Display jobDisplay, String name, StructuredViewer structuredViewer, INodeNotifier nodeNotifier) {
+ super(jobDisplay, name);
+ setPriority(Job.SHORT);
+
+ setStructuredViewer(structuredViewer);
+ setNodeNotifier(nodeNotifier);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ IStatus result = Status.OK_STATUS;
+ try {
+ Control control = fStructuredViewer.getControl();
+ // we should have check before even scheduling this, but even if
+ // ok then, need to check again, right before executing.
+ if (control != null && !control.isDisposed()) {
+
+ if ((fNodeNotifier instanceof Node) && (((Node) fNodeNotifier).getParentNode() == null)) {
+ // refresh whole document
+ fStructuredViewer.refresh();
+ } else {
+ // refresh only the node that's changed
+ fStructuredViewer.refresh(fNodeNotifier);
+ }
+ }
+ } catch (Exception e) {
+ result = errorStatus(e);
+ } finally {
+ monitor.done();
+ }
+ return result;
+ }
+
+ /**
+ * @param nodeNotifier
+ */
+ private void setNodeNotifier(INodeNotifier nodeNotifier) {
+ fNodeNotifier = nodeNotifier;
+
+ }
+
+ /**
+ * @param structuredViewer
+ */
+ private void setStructuredViewer(StructuredViewer structuredViewer) {
+ fStructuredViewer = structuredViewer;
+
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/RefreshPropertySheetJob.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/RefreshPropertySheetJob.java
new file mode 100644
index 0000000000..e20a28bd33
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/RefreshPropertySheetJob.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.ui.views.properties.PropertySheetPage;
+
+
+public class RefreshPropertySheetJob extends UIJob {
+
+
+ private PropertySheetPage fPropertySheetPage;
+
+ /**
+ * @param jobDisplay
+ * @param name
+ */
+ public RefreshPropertySheetJob(Display jobDisplay, String name, PropertySheetPage propertySheetPage) {
+ super(jobDisplay, name);
+ setPriority(Job.SHORT);
+ fPropertySheetPage = propertySheetPage;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ IStatus result = Status.OK_STATUS;
+ try {
+ Control control = fPropertySheetPage.getControl();
+ // we should have check before even scheduling this, but even if
+ // ok then, need to check again, right before executing.
+ if (control != null && !control.isDisposed()) {
+ fPropertySheetPage.refresh();
+ }
+ } catch (Exception e) {
+ result = errorStatus(e);
+ } finally {
+ monitor.done();
+ }
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java
new file mode 100644
index 0000000000..123732f597
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLContentOutlineConfiguration.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.util.TransferDragSourceListener;
+import org.eclipse.jface.util.TransferDropTargetListener;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.ui.IReleasable;
+import org.eclipse.wst.sse.ui.view.events.NodeSelectionChangedEvent;
+import org.eclipse.wst.sse.ui.views.contentoutline.StructuredContentOutlineConfiguration;
+import org.eclipse.wst.ui.dnd.ObjectTransfer;
+import org.eclipse.wst.ui.dnd.ViewerDragAdapter;
+import org.eclipse.wst.ui.dnd.ViewerDropAdapter;
+import org.eclipse.wst.xml.ui.dnd.XMLDragAndDropManager;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+public class XMLContentOutlineConfiguration extends StructuredContentOutlineConfiguration {
+
+ protected class ActionManagerMenuListener implements IMenuListener, IReleasable {
+ private XMLNodeActionManager fActionManager;
+ private TreeViewer fTreeViewer;
+
+ public ActionManagerMenuListener(TreeViewer viewer) {
+ fTreeViewer = viewer;
+ fActionManager = createNodeActionManager(fTreeViewer);
+ }
+
+ public void menuAboutToShow(IMenuManager manager) {
+ if (fActionManager != null)
+ fActionManager.fillContextMenu(manager, fTreeViewer.getSelection());
+ }
+
+ public void release() {
+ fTreeViewer = null;
+ fActionManager.setModel(null);
+ }
+ }
+
+ protected ActionManagerMenuListener fContextMenuFiller = null;
+
+ private TransferDragSourceListener[] fTransferDragSourceListeners;
+ private TransferDropTargetListener[] fTransferDropTargetListeners;
+
+ public XMLContentOutlineConfiguration() {
+ super();
+ }
+
+ protected XMLNodeActionManager createNodeActionManager(TreeViewer treeViewer) {
+ return new XMLNodeActionManager(getEditor().getModel(), treeViewer);
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getTreeContentProvider(org.eclipse.jface.viewers.TreeViewer)
+ */
+ public IContentProvider getContentProvider(TreeViewer viewer) {
+ if (fContentProvider == null) {
+ if (getFactory() != null) {
+ fContentProvider = new JFaceNodeContentProvider((AdapterFactory) getFactory());
+ } else {
+ fContentProvider = super.getContentProvider(viewer);
+ }
+ }
+ return fContentProvider;
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getLabelProvider(org.eclipse.jface.viewers.TreeViewer)
+ */
+ public ILabelProvider getLabelProvider(TreeViewer viewer) {
+ if (fLabelProvider == null) {
+ if (getFactory() != null) {
+ fLabelProvider = new JFaceNodeLabelProvider((AdapterFactory) getFactory());
+ } else {
+ fLabelProvider = super.getLabelProvider(viewer);
+ }
+ }
+ return fLabelProvider;
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getMenuListener(org.eclipse.jface.viewers.TreeViewer)
+ */
+ public IMenuListener getMenuListener(TreeViewer viewer) {
+ if (fContextMenuFiller == null) {
+ fContextMenuFiller = new ActionManagerMenuListener(viewer);
+ }
+ return fContextMenuFiller;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getNodes(java.util.List)
+ */
+ public List getNodes(List nodes) {
+ List filteredNodes = new ArrayList(super.getNodes(nodes));
+ for (int i = 0; i < filteredNodes.size(); i++) {
+ Object selectedNode = filteredNodes.get(i);
+ if (selectedNode instanceof Node) {
+ Node eachNode = (Node) selectedNode;
+ // replace attribute node in selection with its parent
+ if (eachNode.getNodeType() == Node.ATTRIBUTE_NODE)
+ filteredNodes.set(i, ((Attr) eachNode).getOwnerElement());
+ // replace TextNode in selection with its parent
+ else if (eachNode.getNodeType() == Node.TEXT_NODE)
+ filteredNodes.set(i, eachNode.getParentNode());
+ }
+ }
+ return filteredNodes;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getSelectedNodes(org.eclipse.wst.sse.ui.view.events.NodeSelectionChangedEvent)
+ */
+ public List getSelectedNodes(NodeSelectionChangedEvent event) {
+ return getNodes(super.getSelectedNodes(event));
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getTransferDragSourceListeners(org.eclipse.jface.viewers.TreeViewer)
+ */
+ public TransferDragSourceListener[] getTransferDragSourceListeners(TreeViewer treeViewer) {
+ if (fTransferDragSourceListeners == null) {
+ // emulate the XMLDragAndDropManager
+ final ViewerDragAdapter dragAdapter = new ViewerDragAdapter(treeViewer);
+ fTransferDragSourceListeners = new TransferDragSourceListener[]{new TransferDragSourceListener() {
+ public void dragFinished(DragSourceEvent event) {
+ dragAdapter.dragFinished(event);
+ }
+
+ public void dragSetData(DragSourceEvent event) {
+ dragAdapter.dragSetData(event);
+ }
+
+ public void dragStart(DragSourceEvent event) {
+ dragAdapter.dragStart(event);
+ }
+
+ public Transfer getTransfer() {
+ return ObjectTransfer.getInstance();
+ }
+ }};
+ }
+
+ return fTransferDragSourceListeners;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration#getTransferDropTargetListeners(org.eclipse.jface.viewers.TreeViewer)
+ */
+ public TransferDropTargetListener[] getTransferDropTargetListeners(TreeViewer treeViewer) {
+ if (fTransferDropTargetListeners == null) {
+ // emulate the XMLDragAnDropManager
+ final ViewerDropAdapter dropAdapter = new ViewerDropAdapter(treeViewer, new XMLDragAndDropManager());
+ fTransferDropTargetListeners = new TransferDropTargetListener[]{new TransferDropTargetListener() {
+ public void dragEnter(DropTargetEvent event) {
+ dropAdapter.dragEnter(event);
+ }
+
+ public void dragLeave(DropTargetEvent event) {
+ dropAdapter.dragLeave(event);
+ }
+
+ public void dragOperationChanged(DropTargetEvent event) {
+ dropAdapter.dragOperationChanged(event);
+ }
+
+ public void dragOver(DropTargetEvent event) {
+ dropAdapter.dragOver(event);
+ }
+
+ public void drop(DropTargetEvent event) {
+ dropAdapter.drop(event);
+ }
+
+ public void dropAccept(DropTargetEvent event) {
+ dropAdapter.dropAccept(event);
+ }
+
+ public Transfer getTransfer() {
+ return ObjectTransfer.getInstance();
+ }
+
+ public boolean isEnabled(DropTargetEvent event) {
+ return getTransfer().isSupportedType(event.currentDataType);
+ }
+ }};
+ }
+ return fTransferDropTargetListeners;
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.views.contentoutline.StructuredContentOutlineConfiguration#unconfigure()
+ */
+ public void unconfigure(TreeViewer viewer) {
+ super.unconfigure(viewer);
+ fTransferDragSourceListeners = null;
+ fTransferDropTargetListeners = null;
+ if (fContextMenuFiller != null) {
+ fContextMenuFiller.release();
+ fContextMenuFiller = null;
+ }
+ // TODO: Add DnD support
+ // XMLDragAndDropManager.addDragAndDropSupport(fTreeViewer);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLNodeActionManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLNodeActionManager.java
new file mode 100644
index 0000000000..9fe7c36c70
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/contentoutline/XMLNodeActionManager.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.contentoutline;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.core.IStructuredModel;
+import org.eclipse.wst.sse.core.format.IStructuredFormatProcessor;
+import org.eclipse.wst.xml.core.format.FormatProcessorXML;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.actions.AbstractNodeActionManager;
+import org.w3c.dom.Node;
+
+
+public class XMLNodeActionManager extends AbstractNodeActionManager {
+ public XMLNodeActionManager(IStructuredModel model, Viewer viewer) {
+ super(model, ModelQueryUtil.getModelQuery(model), viewer);
+ }
+
+ public void reformat(Node newElement, boolean deep) {
+ try {
+ // tell the model that we are about to make a big model change
+ model.aboutToChangeModel();
+
+ // format selected node
+ IStructuredFormatProcessor formatProcessor = new FormatProcessorXML();
+ formatProcessor.formatNode(newElement);
+ } finally {
+ // tell the model that we are done with the big model change
+ model.changedModel();
+ }
+ }
+
+ public void setModel(IStructuredModel newModel) {
+ model = newModel;
+ setModelQuery(ModelQueryUtil.getModelQuery(newModel));
+ }
+
+ protected void setModelQuery(ModelQuery newModelQuery) {
+ modelQuery = newModelQuery;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/ProcessingInstructionPropertySourceAdapter.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/ProcessingInstructionPropertySourceAdapter.java
new file mode 100644
index 0000000000..de4b996498
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/ProcessingInstructionPropertySourceAdapter.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.properties;
+
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.text.ITextRegion;
+import org.eclipse.wst.sse.core.text.ITextRegionList;
+import org.eclipse.wst.sse.core.util.StringUtils;
+import org.eclipse.wst.sse.ui.util.Assert;
+import org.eclipse.wst.sse.ui.views.properties.CustomPropertyDescriptor;
+import org.eclipse.wst.sse.ui.views.properties.IPropertySourceExtension;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.parser.XMLRegionContext;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+
+
+/**
+ * An IPropertySource implementation for a JFace viewer used to display
+ * properties of DOM nodes. Requires an adapter factory to create JFace
+ * adapters for the nodes in the tree.
+ */
+public class ProcessingInstructionPropertySourceAdapter implements INodeAdapter, IPropertySource, IPropertySourceExtension {
+ protected final static String CATEGORY_ATTRIBUTES = "Instructions"; //$NON-NLS-1$
+
+ protected IPropertyDescriptor[] fDescriptors = null;
+ protected Node fNode = null;
+
+ public ProcessingInstructionPropertySourceAdapter(INodeNotifier target) {
+ super();
+ fNode = (Node) target;
+ Assert.isTrue(target instanceof XMLNode);
+ Assert.isTrue(fNode.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE);
+ }
+
+ /**
+ * Returns the current collection of property descriptors.
+ *
+ * @return all valid descriptors.
+ */
+ protected IPropertyDescriptor[] createPropertyDescriptors() {
+ boolean isXML = ((ProcessingInstruction) fNode).getTarget().equalsIgnoreCase("xml"); //$NON-NLS-1$
+ if (!isXML)
+ return new IPropertyDescriptor[0];
+ CustomPropertyDescriptor[] descriptors = new CustomPropertyDescriptor[2];
+ descriptors[0] = new CustomPropertyDescriptor("version", "version", null); //$NON-NLS-1$ //$NON-NLS-2$
+ descriptors[0].setCategory(CATEGORY_ATTRIBUTES);
+ descriptors[1] = new CustomPropertyDescriptor("encoding", "encoding", null); //$NON-NLS-1$ //$NON-NLS-2$
+ descriptors[1].setCategory(CATEGORY_ATTRIBUTES);
+ return descriptors;
+ }
+
+ /**
+ * Returns a value for this Node that can be editted in a property sheet.
+ *
+ * @return a value that can be editted
+ */
+ public Object getEditableValue() {
+ return null;
+ }
+
+ /**
+ * Returns the current collection of property descriptors.
+ *
+ * @return all valid descriptors.
+ */
+ public IPropertyDescriptor[] getPropertyDescriptors() {
+ if (fDescriptors == null) {
+ fDescriptors = createPropertyDescriptors();
+ }
+ return fDescriptors;
+ }
+
+ /**
+ * Returns the current value for the named property.
+ *
+ * @param name
+ * the name of the property as named by its property descriptor
+ * @return the current value of the property
+ */
+ public Object getPropertyValue(Object nameObject) {
+ XMLNode node = (XMLNode) fNode;
+ String value = null;
+ String name = null;
+ IStructuredDocumentRegion docRegion = node.getFirstStructuredDocumentRegion();
+ if (docRegion == null)
+ return null;
+ ITextRegionList regions = docRegion.getRegions();
+ ITextRegion region = null;
+ int i = 2;
+ while (value == null && i < regions.size()) {
+ region = regions.get(i);
+ if (region.getType().equals(XMLRegionContext.XML_TAG_ATTRIBUTE_NAME))
+ name = docRegion.getText(region);
+ else if (region.getType().equals(XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) && name != null && name.equals(nameObject))
+ value = docRegion.getText(region);
+ i++;
+ }
+ if (value != null)
+ value = StringUtils.strip(value);
+ return value;
+ }
+
+ /**
+ * Allowing the INodeAdapter to compare itself against the type allows it
+ * to return true in more than one case.
+ */
+ public boolean isAdapterForType(Object type) {
+ return type == IPropertySource.class;
+ }
+
+ /**
+ * Returns whether the property value has changed from the default.
+ *
+ * @return <code>true</code> if the value of the specified property has
+ * changed from its original default value; <code>false</code>
+ * otherwise.
+ */
+ public boolean isPropertySet(Object propertyObject) {
+ return false;
+ }
+
+ public void notifyChanged(INodeNotifier notifier, int eventType, java.lang.Object changedFeature, java.lang.Object oldValue, java.lang.Object newValue, int pos) {
+ }
+
+ /**
+ * Remove the given attribute from the Node
+ *
+ * @param propertyObject
+ */
+ public void removeProperty(Object propertyObject) {
+ }
+
+ /**
+ * Resets the specified property's value to its default value.
+ *
+ * @param property
+ * the property to reset
+ */
+ public void resetPropertyValue(Object propertyObject) {
+ }
+
+ /**
+ * Sets the named property to the given value.
+ *
+ * @param name
+ * the name of the property being set
+ * @param value
+ * the new value for the property
+ */
+ public void setPropertyValue(Object nameObject, Object value) {
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySheetConfiguration.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySheetConfiguration.java
new file mode 100644
index 0000000000..7ce0ff08a2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySheetConfiguration.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.wst.sse.ui.views.properties.StructuredPropertySheetConfiguration;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+
+public class XMLPropertySheetConfiguration extends StructuredPropertySheetConfiguration {
+
+ /**
+ *
+ */
+ public XMLPropertySheetConfiguration() {
+ super();
+ }
+
+ /**
+ * @see org.eclipse.wst.sse.ui.views.properties.PropertySheetConfiguration#getSelection(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public ISelection getSelection(IWorkbenchPart selectingPart, ISelection selection) {
+ // On Attr nodes, select the owner Element. On Text nodes, select the
+ // parent Element.
+ ISelection preferredSelection = selection;
+ if (selection instanceof ITextSelection) {
+ // on text selection, find the appropriate Node
+ ITextSelection textSel = (ITextSelection) selection;
+ if (getModel() != null) {
+ Object inode = getModel().getIndexedRegion(textSel.getOffset());
+ if (inode instanceof Node) {
+ Node node = (Node) inode;
+ // replace Attribute Node with its owner
+ if (node.getNodeType() == Node.ATTRIBUTE_NODE)
+ inode = ((Attr) node).getOwnerElement();
+ // replace Text Node with its parent
+ else if ((node.getNodeType() == Node.TEXT_NODE || (node.getNodeType() == Node.CDATA_SECTION_NODE)) && node.getParentNode() != null) {
+ inode = node.getParentNode();
+ }
+ }
+ if (inode != null) {
+ List inputList = new ArrayList(1);
+ inputList.add(inode);
+ preferredSelection = new StructuredSelection(inputList);
+ }
+ }
+ } else if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSel = (IStructuredSelection) selection;
+ if (getModel() != null) {
+ List inputList = new ArrayList(structuredSel.toList());
+ for (int i = 0; i < inputList.size(); i++) {
+ Object inode = inputList.get(i);
+ if (inode instanceof Node) {
+ Node node = (Node) inputList.get(i);
+ // replace Attribute Node with its owner
+ if (node.getNodeType() == Node.ATTRIBUTE_NODE)
+ inputList.set(i, ((Attr) node).getOwnerElement());
+ // replace Text Node with its parent
+ else if ((node.getNodeType() == Node.TEXT_NODE || (node.getNodeType() == Node.CDATA_SECTION_NODE)) && node.getParentNode() != null) {
+ inputList.set(i, node.getParentNode());
+ }
+ }
+ }
+ preferredSelection = new StructuredSelection(inputList);
+ }
+ }
+ return preferredSelection;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySourceAdapter.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySourceAdapter.java
new file mode 100644
index 0000000000..b71904126f
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySourceAdapter.java
@@ -0,0 +1,680 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.properties;
+
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Stack;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.IPropertySheetEntry;
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.ui.views.properties.TextPropertyDescriptor;
+import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
+import org.eclipse.wst.common.contentmodel.CMDataType;
+import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
+import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
+import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.eclipse.wst.sse.ui.Logger;
+import org.eclipse.wst.sse.ui.views.properties.EnumeratedStringPropertyDescriptor;
+import org.eclipse.wst.sse.ui.views.properties.IPropertySourceExtension;
+import org.eclipse.wst.xml.core.document.DocumentTypeAdapter;
+import org.eclipse.wst.xml.core.document.XMLNode;
+import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
+import org.eclipse.wst.xml.ui.nls.ResourceHandler;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+
+/**
+ * An IPropertySource implementation for a JFace viewer used to display
+ * properties of DOM nodes. Requires an adapter factory to create JFace
+ * adapters for the nodes in the tree.
+ */
+public class XMLPropertySourceAdapter implements INodeAdapter, IPropertySource, IPropertySourceExtension {
+ protected final static String CATEGORY_ATTRIBUTES = ResourceHandler.getString("XMLPropertySourceAdapter.0"); //$NON-NLS-1$
+
+ private static final boolean fSetExpertFilter = false;
+
+ // derive categories from CMDataTypes; disabled until display strings can
+ // be planned
+ private final static boolean fShouldDeriveCategories = false;
+
+ private final static boolean fSortEnumeratedValues = true;
+ protected boolean fCaseSensitive = true;
+ protected IPropertyDescriptor[] fDescriptors = null;
+ protected Node fNode = null;
+
+ protected Stack fValuesBeingSet = new Stack();
+
+ public XMLPropertySourceAdapter(INodeNotifier target) {
+ super();
+ fNode = (Node) target;
+ if (fNode instanceof XMLNode) {
+ Document ownerDocument = fNode.getOwnerDocument();
+ if (ownerDocument == null) {
+ // if ownerDocument is null, then it must be the Document Node
+ ownerDocument = (Document) fNode;
+ }
+ DocumentTypeAdapter adapter = (DocumentTypeAdapter) ((INodeNotifier) ownerDocument).getAdapterFor(DocumentTypeAdapter.class);
+ if (adapter != null)
+ fCaseSensitive = adapter.getTagNameCase() == DocumentTypeAdapter.STRICT_CASE;
+ }
+ }
+
+ private String[] _getValidFixedStrings(CMAttributeDeclaration attrDecl, CMDataType helper) {
+ String attributeName = attrDecl.getAttrName();
+ List values = new ArrayList(1);
+ String impliedValue = helper.getImpliedValue();
+ if (impliedValue != null)
+ values.add(impliedValue);
+ boolean checkIfCurrentValueIsIncluded = (fNode.getAttributes() != null && fNode.getAttributes().getNamedItem(attributeName) != null && fNode.getAttributes().getNamedItem(attributeName).getNodeValue() != null);
+ if (checkIfCurrentValueIsIncluded) {
+ String currentValue = null;
+ currentValue = fNode.getAttributes().getNamedItem(attributeName).getNodeValue();
+ if (!currentValue.equals(impliedValue))
+ values.add(currentValue);
+ }
+ String[] validStrings = new String[values.size()];
+ validStrings = (String[]) values.toArray(validStrings);
+ return validStrings;
+ }
+
+ private String[] _getValidStrings(CMAttributeDeclaration attrDecl, CMDataType valuesHelper) {
+ String attributeName = attrDecl.getAttrName();
+ List values = new ArrayList(1);
+ boolean currentValueKnown = false;
+ boolean checkIfCurrentValueIsKnown = (fNode.getAttributes() != null && fNode.getAttributes().getNamedItem(attributeName) != null && fNode.getAttributes().getNamedItem(attributeName).getNodeValue() != null);
+ String currentValue = null;
+ if (checkIfCurrentValueIsKnown)
+ currentValue = fNode.getAttributes().getNamedItem(attributeName).getNodeValue();
+
+ if (valuesHelper.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED && valuesHelper.getImpliedValue() != null) {
+ // FIXED value
+ currentValueKnown = currentValue != null && valuesHelper.getImpliedValue().equals(currentValue);
+ values.add(valuesHelper.getImpliedValue());
+ } else {
+ // ENUMERATED values
+ String[] valueStrings = null;
+ // valueStrings = valuesHelper.getEnumeratedValues();
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument());
+ if (modelQuery != null && fNode.getNodeType() == Node.ELEMENT_NODE) {
+ valueStrings = modelQuery.getPossibleDataTypeValues((Element) fNode, attrDecl);
+ } else {
+ valueStrings = attrDecl.getAttrType().getEnumeratedValues();
+ }
+ if (valueStrings != null) {
+ for (int i = 0; i < valueStrings.length; i++) {
+ if (checkIfCurrentValueIsKnown && valueStrings[i].equals(currentValue))
+ currentValueKnown = true;
+ values.add(valueStrings[i]);
+ }
+ }
+ }
+ if (valuesHelper.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE && valuesHelper.getImpliedValue() != null) {
+ if (!values.contains(valuesHelper.getImpliedValue()))
+ values.add(valuesHelper.getImpliedValue());
+ }
+
+ if (checkIfCurrentValueIsKnown && !currentValueKnown && currentValue != null && currentValue.length() > 0)
+ values.add(currentValue);
+ String[] validStrings = new String[values.size()];
+ validStrings = (String[]) values.toArray(validStrings);
+ return validStrings;
+ }
+
+ protected void clearDescriptors() {
+ fDescriptors = null;
+ }
+
+ protected IPropertyDescriptor createDefaultPropertyDescriptor(String attributeName) {
+ return createDefaultPropertyDescriptor(attributeName, false);
+ }
+
+ protected IPropertyDescriptor createDefaultPropertyDescriptor(String attributeName, boolean hideOnFilter) {
+ // The descriptor class used here is also used in
+ // updatePropertyDescriptors()
+ TextPropertyDescriptor descriptor = new TextPropertyDescriptor(attributeName, attributeName);
+ descriptor.setCategory(getCategory(null));
+ descriptor.setDescription(attributeName);
+ if (hideOnFilter && fSetExpertFilter)
+ descriptor.setFilterFlags(new String[]{IPropertySheetEntry.FILTER_ID_EXPERT});
+ return descriptor;
+ }
+
+ /**
+ * Creates a property descriptor for an attribute with ENUMERATED values -
+ * if the value does not exist, an editable combo box is returned - if the
+ * value exists but is not one in the enumerated list of value, a combo
+ * box featuring the current and correct values is returned - if the value
+ * exists and it is a valid value, a combo box featuring the correct
+ * values with the current one visible is returned
+ */
+ private IPropertyDescriptor createEnumeratedPropertyDescriptor(CMAttributeDeclaration attrDecl, CMDataType valuesHelper) {
+ // the displayName MUST be set
+ EnumeratedStringPropertyDescriptor descriptor = new EnumeratedStringPropertyDescriptor(attrDecl.getAttrName(), attrDecl.getAttrName(), _getValidStrings(attrDecl, valuesHelper));
+ descriptor.setCategory(getCategory(attrDecl));
+ descriptor.setDescription(attrDecl.getAttrName());
+ if (attrDecl.getUsage() != CMAttributeDeclaration.REQUIRED && fSetExpertFilter)
+ descriptor.setFilterFlags(new String[]{IPropertySheetEntry.FILTER_ID_EXPERT});
+ return descriptor;
+ }
+
+ /**
+ * Creates a property descriptor for an attribute with a FIXED value - if
+ * the value does not exist, an editable combo box is returned - if the
+ * value exists but is not the fixed/default value, a combo box featuring
+ * the current and correct value is returned - if the value exists and it
+ * is the fixed/default value, no cell editor is provided "locking" the
+ * value in
+ */
+ private IPropertyDescriptor createFixedPropertyDescriptor(CMAttributeDeclaration attrDecl, CMDataType helper) {
+ // the displayName MUST be set
+ EnumeratedStringPropertyDescriptor descriptor = new EnumeratedStringPropertyDescriptor(attrDecl.getNodeName(), attrDecl.getNodeName(), _getValidFixedStrings(attrDecl, helper));
+ descriptor.setCategory(getCategory(attrDecl));
+ descriptor.setDescription(attrDecl.getAttrName());
+ return descriptor;
+ }
+
+ protected IPropertyDescriptor createPropertyDescriptor(CMAttributeDeclaration attrDecl) {
+ IPropertyDescriptor descriptor = null;
+ CMDataType attrType = attrDecl.getAttrType();
+
+ if (attrType != null) {
+ // handle declarations that provide FIXED/ENUMERATED values
+ if (attrType.getEnumeratedValues() != null && attrType.getEnumeratedValues().length > 0) {
+ descriptor = createEnumeratedPropertyDescriptor(attrDecl, attrType);
+ } else if ((attrDecl.getUsage() == CMAttributeDeclaration.FIXED || attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) && attrType.getImpliedValue() != null) {
+ descriptor = createFixedPropertyDescriptor(attrDecl, attrType);
+ } else {
+ // plain text
+ descriptor = createTextPropertyDescriptor(attrDecl);
+ }
+ } else {
+ // no extra information given
+ descriptor = createTextPropertyDescriptor(attrDecl);
+ }
+ return descriptor;
+ }
+
+ /**
+ * Returns the current collection of property descriptors.
+ *
+ * @return all valid descriptors.
+ */
+ protected IPropertyDescriptor[] createPropertyDescriptors() {
+ CMNamedNodeMap attrMap = null;
+ CMElementDeclaration ed = getDeclaration();
+ if (ed != null) {
+ attrMap = ed.getAttributes();
+ }
+
+ List descriptorList = new ArrayList();
+ List names = new ArrayList();
+ IPropertyDescriptor descriptor;
+
+ CMAttributeDeclaration attrDecl = null;
+
+ // add descriptors for existing attributes
+ NamedNodeMap attributes = fNode.getAttributes();
+ if (attributes != null) {
+ for (int i = 0; i < attributes.getLength(); i++) {
+ Attr attr = (Attr) attributes.item(i);
+ // if metainfo is present for this attribute, use the
+ // CMAttributeDeclaration to derive a descriptor
+ if (attrMap != null) {
+ String attrName = attr.getName();
+ if (fCaseSensitive)
+ attrDecl = (CMAttributeDeclaration) attrMap.getNamedItem(attrName);
+ else {
+ for (int j = 0; j < attrMap.getLength(); j++) {
+ if (!fCaseSensitive && attrMap.item(j).getNodeName().equalsIgnoreCase(attrName)) {
+ attrDecl = (CMAttributeDeclaration) attrMap.item(j);
+ break;
+ }
+ }
+ }
+ }
+ // be consistent: if there's metainfo, use *that* as the
+ // descriptor ID
+ if (attrDecl != null) {
+ descriptor = createPropertyDescriptor(attrDecl);
+ if (descriptor != null)
+ names.add(attrDecl.getNodeName());
+ } else {
+ descriptor = createDefaultPropertyDescriptor(attr.getName());
+ if (descriptor != null)
+ names.add(attr.getName());
+ }
+ if (descriptor != null)
+ descriptorList.add(descriptor);
+ }
+ }
+
+ // add descriptors from the metainfo that are not yet listed
+ if (attrMap != null) {
+ for (int i = 0; i < attrMap.getLength(); i++) {
+ attrDecl = (CMAttributeDeclaration) attrMap.item(i);
+ if (!names.contains(attrDecl.getAttrName())) {
+ IPropertyDescriptor holdDescriptor = createPropertyDescriptor(attrDecl);
+ if (holdDescriptor != null) {
+ descriptorList.add(holdDescriptor);
+ }
+ }
+ }
+ }
+
+ IPropertyDescriptor[] descriptors = new IPropertyDescriptor[descriptorList.size()];
+ for (int i = 0; i < descriptors.length; i++)
+ descriptors[i] = (IPropertyDescriptor) descriptorList.get(i);
+ return descriptors;
+ }
+
+ private IPropertyDescriptor createTextPropertyDescriptor(CMAttributeDeclaration attrDecl) {
+ TextPropertyDescriptor descriptor = new TextPropertyDescriptor(attrDecl.getAttrName(), attrDecl.getAttrName());
+ descriptor.setCategory(getCategory(attrDecl));
+ descriptor.setDescription(attrDecl.getAttrName());
+ if (attrDecl.getUsage() != CMAttributeDeclaration.REQUIRED && fSetExpertFilter)
+ descriptor.setFilterFlags(new String[]{IPropertySheetEntry.FILTER_ID_EXPERT});
+ return descriptor;
+ }
+
+ protected String getCategory(CMAttributeDeclaration attrDecl) {
+ if (attrDecl != null) {
+ if (attrDecl.supports("category")) { //$NON-NLS-1$
+ return (String) attrDecl.getProperty("category"); //$NON-NLS-1$
+ }
+ if (fShouldDeriveCategories && attrDecl.getAttrType() != null && attrDecl.getAttrType().getNodeName() != null && attrDecl.getAttrType().getNodeName().length() > 0) {
+ return attrDecl.getAttrType().getDataTypeName();
+ }
+ }
+ return CATEGORY_ATTRIBUTES;
+ }
+
+ protected CMElementDeclaration getDeclaration() {
+ if (fNode == null || fNode.getNodeType() != Node.ELEMENT_NODE)
+ return null;
+ ModelQuery modelQuery = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument());
+ if (modelQuery != null) {
+ return modelQuery.getCMElementDeclaration((Element) fNode);
+ }
+ return null;
+ }
+
+ private Display getDisplay() {
+
+ return PlatformUI.getWorkbench().getDisplay();
+ }
+
+ /**
+ * Returns a value for this Node that can be editted in a property sheet.
+ *
+ * @return a value that can be editted
+ */
+ public Object getEditableValue() {
+ return null;
+ }
+
+ /**
+ * Returns the current collection of property descriptors.
+ *
+ * @return all valid descriptors.
+ */
+ public IPropertyDescriptor[] getPropertyDescriptors() {
+ if (fDescriptors == null || fDescriptors.length == 0) {
+ fDescriptors = createPropertyDescriptors();
+ } else {
+ updatePropertyDescriptors();
+ }
+ return fDescriptors;
+ }
+
+ /**
+ * Returns the current value for the named property.
+ *
+ * @param name
+ * the name of the property as named by its property descriptor
+ * @return the current value of the property
+ */
+ public Object getPropertyValue(Object nameObject) {
+ String name = nameObject.toString();
+ String returnedValue = null;
+ NamedNodeMap attrMap = fNode.getAttributes();
+ if (attrMap != null) {
+ Node attribute = attrMap.getNamedItem(name);
+ if (attribute != null) {
+ if (attribute instanceof XMLNode)
+ returnedValue = ((XMLNode) attribute).getValueSource();
+ else
+ returnedValue = attribute.getNodeValue();
+ }
+ }
+ if (returnedValue == null)
+ returnedValue = ""; //$NON-NLS-1$
+ return returnedValue;
+ }
+
+ protected String[] getValidValues(CMAttributeDeclaration attrDecl) {
+ if (attrDecl == null)
+ return new String[0];
+
+ String[] validValues = null;
+ CMDataType attrType = attrDecl.getAttrType();
+ if (attrType != null) {
+ validValues = _getValidStrings(attrDecl, attrType);
+ if (fSortEnumeratedValues)
+ Arrays.sort(validValues);
+ }
+ if (validValues == null)
+ validValues = new String[0];
+ return validValues;
+ }
+
+ /**
+ * Allowing the INodeAdapter to compare itself against the type allows it
+ * to return true in more than one case.
+ */
+ public boolean isAdapterForType(Object type) {
+ return type == IPropertySource.class;
+ }
+
+ protected boolean isFixedValue(CMAttributeDeclaration attrDecl) {
+ if (attrDecl == null)
+ return true;
+
+ CMDataType attrType = attrDecl.getAttrType();
+ if (attrType != null) {
+ return attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED || attrDecl.getUsage() == CMAttributeDeclaration.FIXED;
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether the property value has changed from the default.
+ *
+ * @return <code>true</code> if the value of the specified property has
+ * changed from its original default value; <code>false</code>
+ * otherwise.
+ */
+ public boolean isPropertySet(Object propertyObject) {
+ String property = propertyObject.toString();
+
+ NamedNodeMap attrMap = fNode.getAttributes();
+ if (attrMap != null)
+ return attrMap.getNamedItem(property) != null;
+ return false;
+ }
+
+ public void notifyChanged(INodeNotifier notifier, int eventType, java.lang.Object changedFeature, java.lang.Object oldValue, java.lang.Object newValue, int pos) {
+ }
+
+ /**
+ * Remove the given attribute from the Node
+ *
+ * @param propertyObject
+ */
+ public void removeProperty(Object propertyObject) {
+ NamedNodeMap attrMap = fNode.getAttributes();
+ if (attrMap != null) {
+ Node attribute = attrMap.getNamedItem(propertyObject.toString());
+ if (attribute != null) {
+ try {
+ attrMap.removeNamedItem(propertyObject.toString());
+ } catch (DOMException e) {
+ if (e.code != DOMException.INVALID_MODIFICATION_ERR) {
+ Logger.logException(e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Resets the specified property's value to its default value.
+ *
+ * @param property
+ * the property to reset
+ */
+ public void resetPropertyValue(Object propertyObject) {
+ String property = propertyObject.toString();
+ CMNamedNodeMap attrDecls = null;
+
+ CMElementDeclaration ed = getDeclaration();
+ if (ed != null) {
+ attrDecls = ed.getAttributes();
+ }
+
+ NamedNodeMap attrMap = fNode.getAttributes();
+ if (attrDecls != null) {
+ CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attrDecls.getNamedItem(property);
+ String defValue = null;
+ if (attrDecl != null) {
+ if (attrDecl.getAttrType() != null) {
+ CMDataType helper = attrDecl.getAttrType();
+ if (helper.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE && helper.getImpliedValue() != null)
+ defValue = helper.getImpliedValue();
+ }
+ }
+ if (defValue != null && defValue.length() > 0) {
+ ((Attr) attrMap.getNamedItem(property)).setValue(defValue);
+ } else {
+ attrMap.removeNamedItem(property);
+ }
+ } else {
+ attrMap.removeNamedItem(property);
+ }
+ }
+
+ /**
+ * Sets the named property to the given value.
+ *
+ * @param name
+ * the name of the property being set
+ * @param value
+ * the new value for the property
+ */
+ public void setPropertyValue(Object nameObject, Object value) {
+ // Avoid cycling - can happen if a closing cell editor causes a
+ // refresh
+ // on the PropertySheet page and the setInput again asks the editor to
+ // close; besides, why apply the same value twice?
+ if (!fValuesBeingSet.isEmpty() && fValuesBeingSet.peek() == nameObject)
+ return;
+ fValuesBeingSet.push(nameObject);
+ String name = nameObject.toString();
+ String valueString = null;
+ if (value != null)
+ valueString = value.toString();
+ NamedNodeMap attrMap = fNode.getAttributes();
+ try {
+ if (attrMap != null) {
+ Attr attr = (Attr) attrMap.getNamedItem(name);
+ if (attr != null) {
+ // EXISTING VALUE
+ // potential out of control loop if updating the value
+ // triggers a viewer update, forcing the
+ // active cell editor to save its value and causing the
+ // loop to continue
+ if (attr.getValue() == null || !attr.getValue().equals(valueString)) {
+ if (attr instanceof XMLNode)
+ ((XMLNode) attr).setValueSource(valueString);
+ else
+ attr.setValue(valueString);
+ }
+ } else {
+ // NEW(?) value
+ if (value != null) { // never create an empty attribute
+ Attr newAttr = fNode.getOwnerDocument().createAttribute(name);
+ if (newAttr instanceof XMLNode)
+ ((XMLNode) newAttr).setValueSource(valueString);
+ else
+ newAttr.setValue(valueString);
+ attrMap.setNamedItem(newAttr);
+ }
+ }
+ } else {
+ if (fNode instanceof Element) {
+ ((Element) fNode).setAttribute(name, valueString);
+ }
+ }
+ } catch (DOMException e) {
+ Display d = getDisplay();
+ if (d != null)
+ d.beep();
+ }
+ fValuesBeingSet.pop();
+ }
+
+ protected void updatePropertyDescriptors() {
+ if (fDescriptors == null || fDescriptors.length == 0)
+ // Nothing to update
+ return;
+
+ // List of all names encountered in the tag and defined by the element
+ List declaredNames = new ArrayList();
+ // New descriptor list that will become fDescriptors after all
+ // processing is done
+ List descriptors = new ArrayList();
+ // Names of the descriptors in the above List
+ List descriptorNames = new ArrayList();
+
+ // Update any descriptors derived from the metainfo
+ CMElementDeclaration ed = getDeclaration();
+ CMNamedNodeMap attrMap = null;
+ if (ed != null) {
+ attrMap = ed.getAttributes();
+ }
+ // Update exiting descriptors; not added to the final list here
+ if (attrMap != null) {
+ // Update existing descriptor types based on metainfo
+ CMAttributeDeclaration attrDecl = null;
+ for (int i = 0; i < attrMap.getLength(); i++) {
+ attrDecl = (CMAttributeDeclaration) attrMap.item(i);
+ String attrName = attrDecl.getAttrName();
+ if (!declaredNames.contains(attrName)) {
+ declaredNames.add(attrName);
+ }
+ for (int j = 0; j < fDescriptors.length; j++) {
+ boolean sameName = (fCaseSensitive && fDescriptors[j].getId().equals(attrDecl.getNodeName())) || (!fCaseSensitive && attrDecl.getNodeName().equals(fDescriptors[j].getId().toString()));
+ if (sameName) {
+ String[] validValues = getValidValues(attrDecl);
+ // Update the descriptor for this
+ // CMAttributeDeclaration (only enumerated values get
+ // updated for now)
+ if (fDescriptors[j] instanceof EnumeratedStringPropertyDescriptor) {
+ ((EnumeratedStringPropertyDescriptor) fDescriptors[j]).updateValues(validValues);
+ }
+ // Replace with better descriptor
+ else if (validValues != null && validValues.length > 0) {
+ fDescriptors[j] = createPropertyDescriptor(attrDecl);
+ }
+ }
+ }
+ }
+ } else {
+ // Update existing descriptors based on not having any metainfo
+ for (int j = 0; j < fDescriptors.length; j++) {
+ // Replace with basic descriptor
+ if (!(fDescriptors[j] instanceof TextPropertyDescriptor)) {
+ fDescriptors[j] = createDefaultPropertyDescriptor((String) fDescriptors[j].getId());
+ }
+ }
+ }
+
+ NamedNodeMap attributes = fNode.getAttributes();
+
+ // Remove descriptors for attributes that aren't present AND aren't
+ // known through metainfo,
+ // do this by only reusing existing descriptors for attributes that
+ // are present or declared
+ for (int i = 0; i < fDescriptors.length; i++) {
+ if (fDescriptors[i] != null) {
+ String descriptorName = fDescriptors[i].getId().toString();
+ if ((declaredNames.contains(descriptorName) || (attributes.getNamedItem(descriptorName) != null)) && !descriptorNames.contains(descriptorName)) {
+ descriptorNames.add(descriptorName);
+ descriptors.add(fDescriptors[i]);
+ }
+ }
+ }
+
+ // Add descriptors for declared attributes that don't already have one
+ if (attrMap != null) {
+ // Update existing descriptor types based on metainfo
+ CMAttributeDeclaration attrDecl = null;
+ for (int i = 0; i < attrMap.getLength(); i++) {
+ attrDecl = (CMAttributeDeclaration) attrMap.item(i);
+ String attrName = attrDecl.getAttrName();
+ if (fCaseSensitive) {
+ if (!descriptorNames.contains(attrName)) {
+ IPropertyDescriptor descriptor = createPropertyDescriptor(attrDecl);
+ if (descriptor != null) {
+ descriptorNames.add(attrName);
+ descriptors.add(descriptor);
+ }
+ }
+ } else {
+ boolean exists = false;
+ for (int j = 0; j < descriptorNames.size(); j++)
+ exists = (descriptorNames.get(j).toString().equalsIgnoreCase(attrName)) || exists;
+ if (!exists) {
+ descriptorNames.add(attrName);
+ IPropertyDescriptor descriptor = createPropertyDescriptor(attrDecl);
+ if (descriptor != null) {
+ descriptorNames.add(attrName);
+ descriptors.add(descriptor);
+ }
+ }
+ }
+ }
+ }
+
+ // Add descriptors for existing attributes that don't already have one
+ if (attributes != null) {
+ for (int i = 0; i < attributes.getLength(); i++) {
+ Attr attr = (Attr) attributes.item(i);
+ String attrName = attr.getName();
+ if (fCaseSensitive) {
+ if (!descriptorNames.contains(attrName)) {
+ descriptorNames.add(attrName);
+ descriptors.add(createDefaultPropertyDescriptor(attrName));
+ }
+ } else {
+ boolean exists = false;
+ for (int j = 0; j < descriptorNames.size(); j++)
+ exists = (descriptorNames.get(j).toString().equalsIgnoreCase(attrName)) || exists;
+ if (!exists) {
+ descriptorNames.add(attrName);
+ descriptors.add(createDefaultPropertyDescriptor(attrName));
+ }
+ }
+ }
+ }
+
+ // Update fDescriptors
+ IPropertyDescriptor[] newDescriptors = new IPropertyDescriptor[descriptors.size()];
+ for (int i = 0; i < newDescriptors.length; i++)
+ newDescriptors[i] = (IPropertyDescriptor) descriptors.get(i);
+ fDescriptors = newDescriptors;
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySourceAdapterFactory.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySourceAdapterFactory.java
new file mode 100644
index 0000000000..0d14000882
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/views/properties/XMLPropertySourceAdapterFactory.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 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
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.xml.ui.views.properties;
+
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.wst.sse.core.AbstractAdapterFactory;
+import org.eclipse.wst.sse.core.AdapterFactory;
+import org.eclipse.wst.sse.core.INodeAdapter;
+import org.eclipse.wst.sse.core.INodeNotifier;
+import org.w3c.dom.Node;
+
+
+public class XMLPropertySourceAdapterFactory extends AbstractAdapterFactory {
+
+ public XMLPropertySourceAdapterFactory() {
+ super(IPropertySource.class, true);
+ }
+
+ public XMLPropertySourceAdapterFactory(Object adapterKey, boolean registerAdapters) {
+ super(adapterKey, registerAdapters);
+ }
+
+ public AdapterFactory copy() {
+ return new XMLPropertySourceAdapterFactory(this.adapterKey, this.shouldRegisterAdapter);
+ }
+
+ protected INodeAdapter createAdapter(INodeNotifier target) {
+ // at the moment, only one implementation exists
+ if (target != null && target instanceof Node && ((Node) target).getNodeType() == Node.PROCESSING_INSTRUCTION_NODE)
+ return new ProcessingInstructionPropertySourceAdapter(target);
+ return new XMLPropertySourceAdapter(target);
+ }
+}
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.properties
new file mode 100644
index 0000000000..4a178765c2
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=comment
+Templates.comment.desc=xml comment
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.xml b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.xml
new file mode 100644
index 0000000000..1ba2929662
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templates>
+
+<template name="%Templates.comment.name" description="%Templates.comment.desc" id="org.eclipse.wst.xml.ui.templates.comment" context="xml_tag" enabled="true">&lt;!-- ${cursor} --&gt;</template>
+</templates>
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_de.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_de.properties
new file mode 100644
index 0000000000..9d5e20bf40
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_de.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=Kommentar
+Templates.comment.desc=XML-Kommentar
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_es.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_es.properties
new file mode 100644
index 0000000000..3a5d4a3114
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_es.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=comment
+Templates.comment.desc=Comentario xml
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_fr.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_fr.properties
new file mode 100644
index 0000000000..15246b2d68
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_fr.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=commentaire
+Templates.comment.desc=commentaire xml
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_it.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_it.properties
new file mode 100644
index 0000000000..7319bebc3d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_it.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=commento
+Templates.comment.desc=commento xml
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_ja.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_ja.properties
new file mode 100644
index 0000000000..8c87bc80fa
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_ja.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=\u30b3\u30e1\u30f3\u30c8
+Templates.comment.desc=xml \u30b3\u30e1\u30f3\u30c8
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_ko.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_ko.properties
new file mode 100644
index 0000000000..8c61a284af
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_ko.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=\uc8fc\uc11d
+Templates.comment.desc=xml \uc8fc\uc11d
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_pt_BR.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_pt_BR.properties
new file mode 100644
index 0000000000..3fe1125463
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_pt_BR.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=coment\u00e1rio
+Templates.comment.desc=coment\u00e1rio xml
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_zh_CN.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_zh_CN.properties
new file mode 100644
index 0000000000..9bff0b4d3d
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_zh_CN.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=\u6ce8\u91ca
+Templates.comment.desc=xml \u6ce8\u91ca
diff --git a/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_zh_TW.properties b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_zh_TW.properties
new file mode 100644
index 0000000000..b051523c64
--- /dev/null
+++ b/bundles/org.eclipse.wst.xml.ui/templates/xmldefault-templates_zh_TW.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2001, 2004 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
+# Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+Templates.comment.name=\u8a3b\u89e3
+Templates.comment.desc=xml \u8a3b\u89e3

Back to the top