/******************************************************************************* * Copyright (c) 2010 SAP AG. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Emil Simeonov - initial API and implementation. * Dimitar Donchev - initial API and implementation. * Dimitar Tenev - initial API and implementation. * Nevena Manova - initial API and implementation. * Georgi Konstantinov - initial API and implementation. * Keshav Veerapaneni - initial API and implementation. *******************************************************************************/ package org.eclipse.wst.sse.sieditor.command.emf.xsd; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; import java.text.MessageFormat; import java.util.List; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.URIUtil; import org.eclipse.xsd.XSDFactory; import org.eclipse.xsd.XSDImport; import org.eclipse.xsd.XSDInclude; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.XSDSchemaContent; import org.eclipse.xsd.impl.XSDImportImpl; import org.eclipse.wst.sse.sieditor.command.common.AbstractXSDNotificationOperation; import org.eclipse.wst.sse.sieditor.model.Activator; import org.eclipse.wst.sse.sieditor.model.api.IXSDModelRoot; import org.eclipse.wst.sse.sieditor.model.i18n.Messages; import org.eclipse.wst.sse.sieditor.model.utils.EmfXsdUtils; import org.eclipse.wst.sse.sieditor.model.utils.ResourceUtils; import org.eclipse.wst.sse.sieditor.model.utils.URIHelper; import org.eclipse.wst.sse.sieditor.model.xsd.api.ISchema; import org.eclipse.wst.sse.sieditor.model.xsd.impl.AbstractType; import org.eclipse.wst.sse.sieditor.model.xsd.impl.Schema; import org.eclipse.wst.sse.sieditor.model.xsd.impl.UnresolvedType; /** * Command for importing an external schema document Imports another schema * within a schema * * */ public class ImportSchemaCommand extends AbstractXSDNotificationOperation { private final AbstractType type; private ISchema _importedSchema; public ImportSchemaCommand(final IXSDModelRoot root, final ISchema schema, final AbstractType type) { super(root, schema, Messages.ImportSchemaCommand_import_schema_command_label); this.type = type; } @Override public IStatus run(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException { final ISchema typeSchema = type.getParent(); if (type == UnresolvedType.instance() || this.modelObject.equals(typeSchema) || EmfXsdUtils.isSchemaForSchemaNS(typeSchema.getNamespace())) { _importedSchema = typeSchema; return Status.OK_STATUS; } final XSDSchema xsdSchema = (XSDSchema) modelObject.getComponent(); final List<XSDSchemaContent> contents = xsdSchema.getContents(); final String typeTargetNamespace = type.getParent().getNamespace(); if (typeTargetNamespace == null) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.ImportSchemaCommand_cannot_refer_schema_without_namespace); } URI uri; try { uri = URIUtil.fromString(URLDecoder.decode( ((Schema) type.getParent()).getComponent().eResource().getURI().toString(), "UTF-8")); //$NON-NLS-1$ } catch (final URISyntaxException e) { throw new ExecutionException(e.getLocalizedMessage()); } catch (final UnsupportedEncodingException e) { throw new ExecutionException(e.getLocalizedMessage()); } String schemaRelativePath; try { schemaRelativePath = ResourceUtils.makeRelativeLocation(URIHelper.createEncodedURI(xsdSchema.getSchemaLocation()) .toString(), uri); } catch (final UnsupportedEncodingException e) { throw new ExecutionException(e.getLocalizedMessage()); } catch (final URISyntaxException e) { throw new ExecutionException(e.getLocalizedMessage()); } try { schemaRelativePath = URLDecoder.decode(schemaRelativePath, "UTF-8"); //$NON-NLS-1$ } catch (final UnsupportedEncodingException e) { throw new ExecutionException(e.getLocalizedMessage()); } for (final XSDSchemaContent schemaContent : contents) { if (schemaContent instanceof XSDImport) { final XSDImport importDirective = (XSDImport) schemaContent; final String importedNamespace = importDirective.getNamespace(); String importedLocation = importDirective.getSchemaLocation(); if (importedLocation == null) { importedLocation = ""; //$NON-NLS-1$ } final boolean resourceAlreadyImported = typeTargetNamespace.equals(importedNamespace) && schemaRelativePath.equals(importedLocation); if (resourceAlreadyImported) { _importedSchema = type.getParent(); return Status.OK_STATUS; } } } XSDSchema resolvedSchema = null; if (xsdSchema.getTargetNamespace() != null && xsdSchema.getTargetNamespace().equals(type.getNamespace())) { // we have matching namespaces. we need to add include final XSDInclude xsdInclude = XSDFactory.eINSTANCE.createXSDInclude(); if (!"".equals(schemaRelativePath)) { //$NON-NLS-1$ xsdInclude.setSchemaLocation(schemaRelativePath); } xsdSchema.getContents().add(0, xsdInclude); } else { // we need to add an import final XSDImport xsdImport = XSDFactory.eINSTANCE.createXSDImport(); xsdImport.setNamespace(type.getNamespace()); if (!"".equals(schemaRelativePath)) { //$NON-NLS-1$ xsdImport.setSchemaLocation(schemaRelativePath); } // the following line forces the xsd import to resolve the schema // before // it is requested. // Added after the command implementation. Should'nt cause bugs resolvedSchema = ((XSDImportImpl) xsdImport).importSchema(); xsdSchema.getContents().add(0, xsdImport); } // if the resolved schema is not present - return the parent schema of // this type if (null == resolvedSchema) { resolvedSchema = type.getParent().getComponent(); } if (null == resolvedSchema) { return new Status(IStatus.ERROR, Activator.PLUGIN_ID, MessageFormat.format( Messages.ImportSchemaCommand_can_not_resolve_schema_X, xsdSchema.getSchemaLocation())); } _importedSchema = new Schema(resolvedSchema, getModelRoot(), null, uri); return Status.OK_STATUS; } @Override public boolean canExecute() { return !(null == modelObject || null == type); } public ISchema getSchema() { return _importedSchema; } }