blob: c04aebd59551d4a3c0fa82d229153177456080da [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.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.xsd.ui.internal.editor;
import java.util.List;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDAttributeGroupDefinition;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDIdentityConstraintDefinition;
import org.eclipse.xsd.XSDModelGroupDefinition;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSchemaDirective;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.XSDTypeDefinition;
import org.eclipse.xsd.XSDVariety;
import org.eclipse.xsd.util.XSDConstants;
import org.eclipse.xsd.util.XSDSwitch;
/**
* A custom XSDSwitch used to locate the "referenced" component. Used by the
* hyperlink/F3 navigation mechanism. Made a separate class because it is used
* from the WSDL editor as well.
*/
public class XSDHyperlinkTargetLocator extends XSDSwitch
{
/**
* Holds the attribute name if the cursor/mouse is over an attribute.
*/
private String attributeName;
/*
* (non-Javadoc)
*
* @see org.eclipse.xsd.util.XSDSwitch#caseXSDAttributeDeclaration(org.eclipse.xsd.XSDAttributeDeclaration)
*/
public Object caseXSDAttributeDeclaration(XSDAttributeDeclaration attributeDeclaration)
{
XSDConcreteComponent target = null;
if (attributeDeclaration.isAttributeDeclarationReference())
{
target = attributeDeclaration.getResolvedAttributeDeclaration();
}
else if (attributeDeclaration.getAnonymousTypeDefinition() == null)
{
target = attributeDeclaration.getTypeDefinition();
// Avoid navigating to built in data types.
if (isFromSchemaForSchema(target))
{
target = null;
}
}
return target;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xsd.util.XSDSwitch#caseXSDAttributeGroupDefinition(org.eclipse.xsd.XSDAttributeGroupDefinition)
*/
public Object caseXSDAttributeGroupDefinition(XSDAttributeGroupDefinition attributeGroupDefinition)
{
XSDConcreteComponent target = null;
if (attributeGroupDefinition.isAttributeGroupDefinitionReference())
{
target = attributeGroupDefinition.getResolvedAttributeGroupDefinition();
}
return target;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xsd.util.XSDSwitch#caseXSDElementDeclaration(org.eclipse.xsd.XSDElementDeclaration)
*/
public Object caseXSDElementDeclaration(XSDElementDeclaration elementDeclaration)
{
XSDConcreteComponent target = null;
if (elementDeclaration.isElementDeclarationReference())
{
target = elementDeclaration.getResolvedElementDeclaration();
}
else
{
XSDConcreteComponent typeDefinition = null;
if (elementDeclaration.getAnonymousTypeDefinition() == null)
{
typeDefinition = elementDeclaration.getTypeDefinition();
}
XSDConcreteComponent substitutionGroupAffiliation = elementDeclaration.getSubstitutionGroupAffiliation();
if (typeDefinition != null && substitutionGroupAffiliation != null)
{
// There are 2 things we can navigate to: if the cursor is anywhere on
// the
// substitution attribute then jump to that, otherwise just go to the
// base type.
if (XSDConstants.SUBSTITUTIONGROUP_ATTRIBUTE.equals(attributeName))
{
target = substitutionGroupAffiliation;
}
else
{
target = typeDefinition;
}
}
else
{
target = typeDefinition != null ? typeDefinition : substitutionGroupAffiliation;
}
if (isFromSchemaForSchema(target))
{
target = null;
}
}
return target;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xsd.util.XSDSwitch#caseXSDIdentityConstraintDefinition(org.eclipse.xsd.XSDIdentityConstraintDefinition)
*/
public Object caseXSDIdentityConstraintDefinition(XSDIdentityConstraintDefinition idConstraintDefinition)
{
Object target = null;
XSDIdentityConstraintDefinition referencedKey = idConstraintDefinition.getReferencedKey();
if (referencedKey != null)
{
target = referencedKey;
}
return target;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xsd.util.XSDSwitch#caseXSDModelGroupDefinition(org.eclipse.xsd.XSDModelGroupDefinition)
*/
public Object caseXSDModelGroupDefinition(XSDModelGroupDefinition modelGroupDefinition)
{
XSDConcreteComponent target = null;
if (modelGroupDefinition.isModelGroupDefinitionReference())
{
target = modelGroupDefinition.getResolvedModelGroupDefinition();
}
return target;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xsd.util.XSDSwitch#caseXSDSchemaDirective(org.eclipse.xsd.XSDSchemaDirective)
*/
public Object caseXSDSchemaDirective(XSDSchemaDirective directive)
{
XSDSchema schema = directive.getResolvedSchema();
return schema;
}
public Object caseXSDSimpleTypeDefinition(XSDSimpleTypeDefinition typeDefinition)
{
XSDConcreteComponent target = null;
// Simple types can be one of: atomic, list or union.
XSDVariety variety = typeDefinition.getVariety();
int varietyType = variety.getValue();
switch (varietyType)
{
case XSDVariety.ATOMIC:
{
target = typeDefinition.getBaseTypeDefinition();
}
break;
case XSDVariety.LIST:
{
target = typeDefinition.getItemTypeDefinition();
}
break;
case XSDVariety.UNION:
{
List memberTypes = typeDefinition.getMemberTypeDefinitions();
if (memberTypes != null && memberTypes.size() > 0)
{
// ISSUE: What if there are more than one type?
// This could be a case for multiple hyperlinks at the same
// location.
target = (XSDConcreteComponent) memberTypes.get(0);
}
}
break;
}
// Avoid navigating to built in data types.
if (isFromSchemaForSchema(target))
{
target = null;
}
return target;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xsd.util.XSDSwitch#caseXSDTypeDefinition(org.eclipse.xsd.XSDTypeDefinition)
*/
public Object caseXSDTypeDefinition(XSDTypeDefinition typeDefinition)
{
XSDConcreteComponent target = null;
XSDTypeDefinition baseType = typeDefinition.getBaseType();
if (baseType != null)
{
target = baseType;
}
// Avoid navigating to built in data types.
if (isFromSchemaForSchema(target))
{
target = null;
}
return target;
}
/**
* Detects if a given schema component is from the schema for schema (built in
* data types). Used to avoid navigating to this type of components as they
* don't have an accessible physical location.
*
* @param component the component to check.
* @return true if the component is from the schema for schema namespace,
* false otherwise.
*/
public boolean isFromSchemaForSchema(XSDConcreteComponent component)
{
if (component == null)
{
return false;
}
XSDSchema schema = component.getSchema();
if (schema != null && schema.equals(schema.getSchemaForSchema()))
{
return true;
}
return false;
}
/**
* Locates the target component - for example the element declaration pointed
* to by an element reference, etc.
*
* @param component the current component.
* @param attributeName the attribute name if the cursor/mouse is over an
* attribute. This is used to provide fine grained navigation for
* components with more than one "active" attribute.
* @return the referenced XSD concrete component or null if none is found.
*/
public XSDConcreteComponent locate(XSDConcreteComponent component, String attributeName)
{
this.attributeName = attributeName;
return (XSDConcreteComponent) doSwitch(component);
}
}