blob: 6f256a1437e7e63aebb79da908402e72997cf172 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.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.navigation;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.INavigationLocation;
import org.eclipse.ui.NavigationLocation;
import org.eclipse.wst.xsd.ui.internal.adapters.XSDAdapterFactory;
import org.eclipse.wst.xsd.ui.internal.adapters.XSDVisitor;
import org.eclipse.wst.xsd.ui.internal.adt.design.DesignViewGraphicalViewer;
import org.eclipse.wst.xsd.ui.internal.adt.facade.IADTObject;
import org.eclipse.xsd.XSDAttributeGroupDefinition;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDModelGroupDefinition;
import org.eclipse.xsd.XSDRedefine;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDTypeDefinition;
import com.ibm.icu.util.StringTokenizer;
/**
* This class exists to support navigation in a context where there is no text
* editor page. In these cases we can't rely on the TextSelectionNavigationLocations
* so we this class which is designed to work with just the design view.
*/
public class DesignViewNavigationLocation extends NavigationLocation
{
protected Path path;
private static final String PATH_TAG = "path"; //$NON-NLS-1$
public DesignViewNavigationLocation(IEditorPart part)
{
super(part);
this.path = new Path();
}
public DesignViewNavigationLocation(IEditorPart part, XSDConcreteComponent component)
{
super(part);
this.path = Path.computePath(component);
}
public boolean mergeInto(INavigationLocation currentLocation)
{
boolean result = false;
if (currentLocation instanceof DesignViewNavigationLocation)
{
DesignViewNavigationLocation loc = (DesignViewNavigationLocation) currentLocation;
result = loc.path.toString().equals(path.toString());
}
else
{
}
return result;
}
public void restoreLocation()
{
XSDSchema schema = (XSDSchema) getEditorPart().getAdapter(XSDSchema.class);
Object viewer = getEditorPart().getAdapter(GraphicalViewer.class);
if (viewer instanceof DesignViewGraphicalViewer)
{
DesignViewGraphicalViewer graphicalViewer = (DesignViewGraphicalViewer) viewer;
XSDConcreteComponent component = Path.computeComponent(schema, path);
if (component != null)
{
Adapter adapter = XSDAdapterFactory.getInstance().adapt(component);
if (adapter instanceof IADTObject)
{
graphicalViewer.setInput((IADTObject)adapter);
}
}
else if (path.segments.isEmpty())
{
Adapter adapter = XSDAdapterFactory.getInstance().adapt(schema);
if (adapter instanceof IADTObject)
{
graphicalViewer.setInput((IADTObject)adapter);
}
}
}
}
public void restoreState(IMemento memento)
{
String string = memento.getString(PATH_TAG);
path = Path.createPath(string);
}
public void saveState(IMemento memento)
{
memento.putString(PATH_TAG, path.toString());
}
public void update()
{
// TODO (cs) not sure what needs to be done here
}
static class PathSegment
{
final static int ELEMENT = 1;
final static int TYPE = 2;
final static int MODEL_GROUP = 3;
final static int ATTRIBUTE_GROUP = 4;
final static int REDEFINE = 5;
int kind;
String name;
PathSegment()
{
}
PathSegment(int kind, String name)
{
this.kind = kind;
this.name = name;
}
}
protected static class Path
{
private static final String REDEFINE_TOKEN = "redefine"; //$NON-NLS-1$
private static final String MODEL_GROUP_TOKEN = "modelGroup"; //$NON-NLS-1$
private static final String ATTRIBUTE_GROUP_TOKEN = "attributeGroup"; //$NON-NLS-1$
private static final String TYPE_TOKEN = "type"; //$NON-NLS-1$
private static final String ELEMENT_TOKEN = "element"; //$NON-NLS-1$
List segments = new ArrayList();
public static XSDConcreteComponent computeComponent(XSDSchema schema, Path path)
{
PathResolvingXSDVisitor visitor = new PathResolvingXSDVisitor(path);
visitor.visitSchema(schema);
if (visitor.isDone())
{
return visitor.result;
}
return null;
}
static Path createPath(String pathString)
{
Path path = new Path();
PathSegment segment = null;
for (StringTokenizer st = new StringTokenizer(pathString, "/"); st.hasMoreTokens();)
{
String token = st.nextToken();
int kind = -1;
if (token.startsWith(ELEMENT_TOKEN))
{
kind = PathSegment.ELEMENT;
}
else if (token.startsWith(TYPE_TOKEN))
{
kind = PathSegment.TYPE;
}
else if (token.startsWith(ATTRIBUTE_GROUP_TOKEN))
{
kind = PathSegment.ATTRIBUTE_GROUP;
}
else if (token.startsWith(MODEL_GROUP_TOKEN))
{
kind = PathSegment.MODEL_GROUP;
}
else if (token.startsWith(REDEFINE_TOKEN))
{
kind = PathSegment.REDEFINE;
}
if (kind != -1)
{
segment = new PathSegment();
segment.kind = kind;
path.segments.add(segment);
String namePattern = "[@name='";
int startIndex = token.indexOf(namePattern);
if (startIndex != -1)
{
startIndex += namePattern.length();
int endIndex = token.indexOf("']");
if (endIndex != -1)
{
segment.name = token.substring(startIndex, endIndex);
}
}
}
}
return path;
}
public static Path computePath(XSDConcreteComponent component)
{
Path path = new Path();
for (EObject c = component; c != null; c = c.eContainer())
{
if (c instanceof XSDConcreteComponent)
{
PathSegment segment = computePathSegment((XSDConcreteComponent) c);
if (segment != null)
{
path.segments.add(0, segment);
}
}
}
return path;
}
static PathSegment computePathSegment(XSDConcreteComponent component)
{
PathSegment pathSegment = null;
if (component instanceof XSDElementDeclaration)
{
XSDElementDeclaration elementDeclaration = (XSDElementDeclaration) component;
pathSegment = new PathSegment(PathSegment.ELEMENT, elementDeclaration.getResolvedElementDeclaration().getName());
}
else if (component instanceof XSDTypeDefinition)
{
XSDTypeDefinition typeDefinition = (XSDTypeDefinition) component;
pathSegment = new PathSegment(PathSegment.TYPE, typeDefinition.getName());
}
else if (component instanceof XSDModelGroupDefinition)
{
XSDModelGroupDefinition modelGroupDefinition = (XSDModelGroupDefinition) component;
pathSegment = new PathSegment(PathSegment.MODEL_GROUP, modelGroupDefinition.getName());
}
else if (component instanceof XSDAttributeGroupDefinition)
{
XSDAttributeGroupDefinition attributeGroupDefinition = (XSDAttributeGroupDefinition) component;
pathSegment = new PathSegment(PathSegment.ATTRIBUTE_GROUP, attributeGroupDefinition.getResolvedAttributeGroupDefinition().getName());
}
else if (component instanceof XSDRedefine)
{
XSDRedefine redefine = (XSDRedefine) component;
pathSegment = new PathSegment(PathSegment.REDEFINE, redefine.getSchemaLocation());
}
return pathSegment;
}
public String toString()
{
StringBuffer b = new StringBuffer();
for (Iterator i = segments.iterator(); i.hasNext();)
{
PathSegment segment = (PathSegment) i.next();
String kind = "";
if (segment.kind == PathSegment.ELEMENT)
{
kind = ELEMENT_TOKEN;
}
else if (segment.kind == PathSegment.TYPE)
{
kind = TYPE_TOKEN;
}
else if (segment.kind == PathSegment.MODEL_GROUP)
{
kind = MODEL_GROUP_TOKEN;
}
else if (segment.kind == PathSegment.ATTRIBUTE_GROUP)
{
kind = ATTRIBUTE_GROUP_TOKEN;
}
else if (segment.kind == PathSegment.REDEFINE)
{
kind = REDEFINE_TOKEN;
}
b.append(kind);
if (segment.name != null)
{
b.append("[@name='" + segment.name + "']");
}
if (i.hasNext())
{
b.append("/");
}
}
return b.toString();
}
}
static class PathResolvingXSDVisitor extends XSDVisitor
{
Path path;
int index = -1;
PathSegment segment;
XSDConcreteComponent result = null;
PathResolvingXSDVisitor(Path path)
{
this.path = path;
incrementSegment();
}
boolean isDone()
{
return index >= path.segments.size();
}
void incrementSegment()
{
index++;
if (index < path.segments.size())
{
segment = (PathSegment) path.segments.get(index);
}
else
{
segment = null;
}
}
public void visitSchema(XSDSchema schema)
{
if (segment != null)
{
if (segment.kind == PathSegment.ELEMENT)
{
XSDElementDeclaration elementDeclaration = schema.resolveElementDeclaration(segment.name);
if (elementDeclaration != null)
{
visitElementDeclaration(elementDeclaration);
}
}
else if (segment.kind == PathSegment.TYPE)
{
XSDTypeDefinition typeDefinition = schema.resolveTypeDefinition(segment.name);
if (typeDefinition != null)
{
visitTypeDefinition(typeDefinition);
}
}
else if (segment.kind == PathSegment.MODEL_GROUP)
{
XSDModelGroupDefinition modelGroupDefinition = schema.resolveModelGroupDefinition(segment.name);
if (modelGroupDefinition != null)
{
visitModelGroupDefinition(modelGroupDefinition);
}
}
else if (segment.kind == PathSegment.ATTRIBUTE_GROUP)
{
XSDAttributeGroupDefinition attributeGroupDefinition = schema.resolveAttributeGroupDefinition(segment.name);
if (attributeGroupDefinition != null)
{
visitAttributeGroupDefinition(attributeGroupDefinition);
}
}
else if (segment.kind == PathSegment.REDEFINE)
{
Iterator iterator = schema.getContents().iterator();
while (iterator.hasNext())
{
Object object = iterator.next();
if (object instanceof XSDRedefine)
{
XSDRedefine redefine = (XSDRedefine)object;
visitRedefine(redefine);
}
}
}
}
}
public void visitElementDeclaration(XSDElementDeclaration element)
{
if (segment != null)
{
String name = element.getResolvedElementDeclaration().getName();
if (segment.kind == PathSegment.ELEMENT && isMatch(segment.name, name))
{
result = element;
incrementSegment();
if (!isDone())
{
super.visitElementDeclaration(element);
}
}
}
}
public void visitTypeDefinition(XSDTypeDefinition type)
{
if (segment != null)
{
String name = type.getName();
if (segment.kind == PathSegment.TYPE && isMatch(segment.name, name))
{
result = type;
incrementSegment();
if (!isDone())
{
super.visitTypeDefinition(type);
}
}
}
}
public void visitModelGroupDefinition(XSDModelGroupDefinition modelGroup)
{
if (segment != null)
{
String name = modelGroup.getName();
if (segment.kind == PathSegment.MODEL_GROUP && isMatch(segment.name, name))
{
result = modelGroup;
incrementSegment();
if (!isDone())
{
super.visitModelGroupDefinition(modelGroup);
}
}
}
}
public void visitAttributeGroupDefinition(XSDAttributeGroupDefinition attributeGroup)
{
if (segment != null)
{
String name = attributeGroup.getName();
if (segment.kind == PathSegment.ATTRIBUTE_GROUP && isMatch(segment.name, name))
{
result = attributeGroup;
incrementSegment();
if (!isDone())
{
super.visitAttributeGroupDefinition(attributeGroup);
}
}
}
}
public void visitRedefine(XSDRedefine redefine)
{
if (segment != null)
{
String name = redefine.getSchemaLocation();
if (segment.kind == PathSegment.REDEFINE && isMatch(segment.name, name))
{
result = redefine;
incrementSegment();
if (!isDone())
{
visitSchema(redefine.getSchema());
}
}
}
}
protected boolean isMatch(String name1, String name2)
{
return name1 != null ? name1.equals(name2) : name1 == name2;
}
}
}