/******************************************************************************* * Copyright (c) 2012, 2015 Obeo. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipse.emf.compare.ide.internal.utils; import java.util.Iterator; import java.util.Map; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.xmi.UnresolvedReferenceException; import org.eclipse.emf.ecore.xmi.XMLDefaultHandler; import org.eclipse.emf.ecore.xmi.XMLHelper; import org.eclipse.emf.ecore.xmi.XMLLoad; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.emf.ecore.xmi.impl.XMLHandler; /** * This implementation of an {@link org.eclipse.emf.ecore.xmi.XMLParserPool} aims at disabling all * notifications when the {@link XMLResource#OPTION_DISABLE_NOTIFY option} is set, including the notifications * at the very end of parsing. * <p> * This is one of the steps that allows EMF Compare to bypass UML's CacheAdapter when loading UML models from * the logical model. * </p> * * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a> */ public class NoNotificationParserPool extends NotifyingParserPool { /** * Default constructor. * * @param containmentOnly * only set containment reference values. The model will be mostly empty except for its * containment tree. */ public NoNotificationParserPool(boolean containmentOnly) { super(containmentOnly); } @Override protected XMLDefaultHandler createDefaultHandler(XMLResource resource, XMLLoad xmlLoad, XMLHelper helper, Map<?, ?> options) { final XMLDefaultHandler handler = super.createDefaultHandler(resource, xmlLoad, helper, options); if (handler instanceof XMLHandler) { return new NoNotificationXMLHandler((XMLHandler)handler, resource, helper, options); } return handler; } /** * The only purpose of this xml handler is to disable the notifications that are sent from the default * implementation of {@link #endDocument()} . * * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a> */ private class NoNotificationXMLHandler extends ForwardingXMLHandler { /** * Creates this forwarding handler given its delegate. All other parameters are only used to call the * mandatory super-constructor... but none should be of any use here. * * @param delegate * Our delegate XMLHandler. * @param xmlResource * The resource we'll be loading. Mandatory for the super-constructor, but we'll forward * all calls to {@code delegate} anyway. * @param helper * The xml helper to use. Mandatory for the super-constructor, but we'll forward all calls * to {@code delegate} anyway. * @param options * The load options that were specified. Mandatory for the super-constructor, but we'll * forward all calls to {@code delegate} anyway. */ NoNotificationXMLHandler(XMLHandler delegate, XMLResource xmlResource, XMLHelper helper, Map<?, ?> options) { super(delegate, xmlResource, helper, options); } /** * {@inheritDoc} * * @see org.eclipse.emf.ecore.xmi.impl.XMLHandler#endDocument() */ @Override public void endDocument() { // prevent the sending of notifications at the end of loading // "disableNotify" at true would still send some from here setField("disableNotify", delegate(), Boolean.FALSE); //$NON-NLS-1$ super.endDocument(); setField("disableNotify", delegate(), Boolean.TRUE); //$NON-NLS-1$ if (containmentOnly) { // Same document references are all left as proxies since we haven't set them. // The xml handler would diagnose that has an error. final Iterator<Resource.Diagnostic> errors = xmlResource.getErrors().iterator(); while (errors.hasNext()) { final Resource.Diagnostic diagnostic = errors.next(); if (diagnostic instanceof UnresolvedReferenceException) { errors.remove(); } } } } } }