Proper loading of the profiles and packages from the SRS
[EMFCompare2.git] / plugins / org.eclipse.emf.compare.ide / src / org / eclipse / emf / compare / ide / internal / utils / NotifyingParserPool.java
blob202b298dc0a29816f67852d963d2401ab8a5696d
1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 Obeo.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Obeo - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.emf.compare.ide.internal.utils;
13 import java.util.Map;
14 import java.util.StringTokenizer;
16 import org.eclipse.core.runtime.ListenerList;
17 import org.eclipse.emf.common.util.URI;
18 import org.eclipse.emf.ecore.EObject;
19 import org.eclipse.emf.ecore.EReference;
20 import org.eclipse.emf.ecore.EStructuralFeature;
21 import org.eclipse.emf.ecore.util.ExtendedMetaData;
22 import org.eclipse.emf.ecore.xmi.XMLDefaultHandler;
23 import org.eclipse.emf.ecore.xmi.XMLHelper;
24 import org.eclipse.emf.ecore.xmi.XMLLoad;
25 import org.eclipse.emf.ecore.xmi.XMLResource;
26 import org.eclipse.emf.ecore.xmi.impl.XMLParserPoolImpl;
27 import org.xml.sax.Attributes;
28 import org.xml.sax.SAXException;
30 /**
31 * This implementation of an XML parser pool will notify a list of {@link INamespaceDeclarationListener
32 * namespace declaration listeners} of all namespaces declared in the parsed resource (xsi:schemalocation),
33 * then a list of {@link IProxyCreationListener proxy creation listeners} of each and every proxy it sees
34 * while loading an XML file as an EMF model.
36 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
38 public class NotifyingParserPool extends XMLParserPoolImpl {
39 /** Only set containment reference values, ignore the rest. */
40 protected final boolean containmentOnly;
42 /** The list of parties interested by our proxies. */
43 private ListenerList proxyListeners;
45 /** The list of parties interested in the declaration of namespaces. */
46 private ListenerList namespaceDeclarationListeners;
48 /**
49 * Default constructor.
51 * @param containmentOnly
52 * only set containment reference values. The model will be mostly empty except for its
53 * containment tree.
55 public NotifyingParserPool(boolean containmentOnly) {
56 super(true);
57 this.proxyListeners = new ListenerList();
58 this.namespaceDeclarationListeners = new ListenerList();
59 this.containmentOnly = containmentOnly;
62 /** {@inheritDoc} */
63 @Override
64 public synchronized XMLDefaultHandler getDefaultHandler(XMLResource resource, XMLLoad xmlLoad,
65 XMLHelper helper, Map<?, ?> options) {
66 final NotifyingXMLHelper wrapper = new NotifyingXMLHelper(helper, containmentOnly);
67 for (Object listener : proxyListeners.getListeners()) {
68 wrapper.addProxyListener((IProxyCreationListener)listener);
70 final XMLDefaultHandler handler = createDefaultHandler(resource, xmlLoad, wrapper, options);
71 final NamespaceDeclarationNotifyingXMLDefaultHandler handlerWrapper = new NamespaceDeclarationNotifyingXMLDefaultHandler(
72 handler);
73 for (Object listener : namespaceDeclarationListeners.getListeners()) {
74 handlerWrapper.addNamespaceDeclarationListener((INamespaceDeclarationListener)listener);
76 handlerWrapper.prepare(resource, wrapper, options);
77 return handlerWrapper;
80 /**
81 * Create the default (unwrapped) XMLDefaultHandler. This is merely a call to <code>super</code> but can
82 * be sub-classed.
84 * @param resource
85 * The resource to load.
86 * @param xmlLoad
87 * The XML load to pass on tho the handler.
88 * @param helper
89 * The XML helper to pass on tho the handler.
90 * @param options
91 * The load options for this resource.
92 * @return The created XMLDefaultHandler.
93 * @see #getDefaultHandler(XMLResource, XMLLoad, XMLHelper, Map)
95 protected XMLDefaultHandler createDefaultHandler(XMLResource resource, XMLLoad xmlLoad, XMLHelper helper,
96 Map<?, ?> options) {
97 return super.getDefaultHandler(resource, xmlLoad, helper, options);
101 * Add a proxy creation listener to this parser pool's list.
103 * @param listener
104 * The listener to add to this pool's list.
106 public void addProxyListener(IProxyCreationListener listener) {
107 proxyListeners.add(listener);
111 * Remove a proxy creation listener from this parser pool's list.
113 * @param listener
114 * The listener to remove from this pool's list.
116 public void removeProxyListener(IProxyCreationListener listener) {
117 proxyListeners.remove(listener);
121 * Add a namespace declaration listener to this parser pool's list.
123 * @param listener
124 * The listener to add to this pool's list.
126 public void addNamespaceDeclarationListener(INamespaceDeclarationListener listener) {
127 namespaceDeclarationListeners.add(listener);
131 * Remove a namespace declaration listener from this parser pool's list.
133 * @param listener
134 * The listener to remove from this pool's list.
136 public void removeNamespaceDeclarationListener(INamespaceDeclarationListener listener) {
137 namespaceDeclarationListeners.remove(listener);
141 * An XMLDefaultHandler that will notify interested {@link INamespaceDeclarationListener listeners} of its
142 * namespace declarations.
144 private static class NamespaceDeclarationNotifyingXMLDefaultHandler extends ForwardingXMLDefaultHandler {
145 /** The list of parties interested in the declaration of namespaces. */
146 private ListenerList namespaceDeclarationListeners;
148 /** <code>true</code> only when we're parsing the very first element. */
149 private boolean isRoot;
152 * Constructs a wrapper given its delegate.
154 * @param delegate
155 * The delegate handler.
157 public NamespaceDeclarationNotifyingXMLDefaultHandler(XMLDefaultHandler delegate) {
158 super(delegate);
159 this.namespaceDeclarationListeners = new ListenerList();
162 @Override
163 public void startDocument() throws SAXException {
164 isRoot = true;
165 super.startDocument();
168 @Override
169 public void startElement(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException {
170 if (isRoot) {
171 String xsiSchemaLocation = arg3.getValue(ExtendedMetaData.XSI_URI,
172 XMLResource.SCHEMA_LOCATION);
173 if (xsiSchemaLocation != null) {
174 declareSchemaLocation(xsiSchemaLocation);
176 isRoot = false;
178 super.startElement(arg0, arg1, arg2, arg3);
182 * Add a namespace declaration listener to this helper's list.
184 * @param listener
185 * The listener to add to this helper's list.
187 public void addNamespaceDeclarationListener(INamespaceDeclarationListener listener) {
188 namespaceDeclarationListeners.add(listener);
192 * We've read the headers of the resource to load. Notify our {@link #namespaceDeclarationListeners
193 * listeners} about the schema locations that can be found therein.
195 * @param xsiSchemaLocation
196 * The String of xsi:schemalocation declarations in the file.
198 private void declareSchemaLocation(String xsiSchemaLocation) {
199 StringTokenizer stringTokenizer = new StringTokenizer(xsiSchemaLocation, " "); //$NON-NLS-1$
200 while (stringTokenizer.hasMoreTokens()) {
201 String key = stringTokenizer.nextToken();
202 if (stringTokenizer.hasMoreTokens()) {
203 String value = stringTokenizer.nextToken();
204 URI uri = URI.createURI(value);
205 for (Object listener : namespaceDeclarationListeners.getListeners()) {
206 ((INamespaceDeclarationListener)listener).schemaLocationDeclared(key, uri);
214 * An XMLHelper wrapper that's capable of notifying {@link IProxyCreationListener listeners}s about proxy
215 * creations.
217 private static class NotifyingXMLHelper extends ForwardingXMLHelper {
218 /** The list of parties interested by our proxy creations. */
219 private final ListenerList proxyListeners;
221 /** Only set containment reference values, ignore the rest. */
222 private final boolean containmentOnly;
225 * Constructs a wrapper given its delegate XMLHelper.
227 * @param delegate
228 * The delegate XMLHelper.
229 * @param containmentOnly
230 * Only set containment reference values.
232 public NotifyingXMLHelper(XMLHelper delegate, boolean containmentOnly) {
233 super(delegate);
234 this.proxyListeners = new ListenerList();
235 this.containmentOnly = containmentOnly;
238 /** {@inheritDoc} */
239 @Override
240 public void setValue(EObject eObject, EStructuralFeature eStructuralFeature, Object value,
241 int position) {
242 if (!containmentOnly
243 || (eStructuralFeature instanceof EReference && ((EReference)eStructuralFeature)
244 .isContainment())) {
245 super.setValue(eObject, eStructuralFeature, value, position);
247 if (value instanceof EObject && ((EObject)value).eIsProxy()) {
248 for (Object listener : proxyListeners.getListeners()) {
249 ((IProxyCreationListener)listener).proxyCreated(getResource(), eObject,
250 eStructuralFeature, (EObject)value, position);
256 * Add a proxy creation listener to this helper's list.
258 * @param listener
259 * The listener to add to this helper's list.
261 public void addProxyListener(IProxyCreationListener listener) {
262 proxyListeners.add(listener);