| /******************************************************************************* |
| * Copyright (c) 2001, 2004 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.graph.model; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.Notifier; |
| import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.wst.xsd.ui.internal.XSDEditorPlugin; |
| import org.eclipse.wst.xsd.ui.internal.graph.XSDChildUtility; |
| import org.eclipse.wst.xsd.ui.internal.provider.XSDAbstractAdapter; |
| import org.eclipse.wst.xsd.ui.internal.provider.XSDModelAdapterFactoryImpl; |
| import org.eclipse.xsd.XSDComplexTypeDefinition; |
| import org.eclipse.xsd.XSDElementDeclaration; |
| import org.eclipse.xsd.XSDModelGroup; |
| import org.eclipse.xsd.XSDNamedComponent; |
| import org.eclipse.xsd.XSDParticle; |
| import org.eclipse.xsd.XSDParticleContent; |
| import org.eclipse.xsd.XSDSchema; |
| import org.eclipse.xsd.XSDSchemaDirective; |
| import org.eclipse.xsd.XSDTypeDefinition; |
| import org.eclipse.xsd.XSDWildcard; |
| import org.eclipse.xsd.util.XSDSwitch; |
| |
| |
| |
| |
| public class XSDModelAdapterFactory |
| { |
| protected static XSDModelAdapterFactory instance; |
| protected static XSDAdapterFactoryImpl xsdAdapterFactoryImpl = new XSDAdapterFactoryImpl(); |
| |
| public static XSDModelAdapterFactory getInstance() |
| { |
| if (instance == null) |
| { |
| instance = new XSDModelAdapterFactory(); |
| } |
| return instance; |
| } |
| |
| |
| public static ModelAdapter getAdapter(Object o) |
| { |
| ModelAdapter result = null; |
| if (o instanceof Notifier) |
| { |
| Notifier target = (Notifier)o; |
| Adapter adapter = xsdAdapterFactoryImpl.adapt(target); |
| if (adapter instanceof XSDObjectAdapter) |
| { |
| result = (XSDObjectAdapter)adapter; |
| } |
| } |
| else if (o instanceof ModelAdapter) |
| { |
| result = (ModelAdapter)o; |
| } |
| return result; |
| } |
| |
| |
| public static XSDObjectAdapter getExisitingAdapter(Object xsdObject) |
| { |
| XSDObjectAdapter result = null; |
| if (xsdObject instanceof Notifier) |
| { |
| Notifier target = (Notifier)xsdObject; |
| Adapter adapter = EcoreUtil.getExistingAdapter(target,xsdAdapterFactoryImpl); |
| if (adapter instanceof XSDObjectAdapter) |
| { |
| result = (XSDObjectAdapter)adapter; |
| } |
| } |
| return result; |
| } |
| |
| // |
| // |
| // |
| public static class XSDAdapterFactoryImpl extends AdapterFactoryImpl |
| { |
| public Adapter createAdapter(Notifier target) |
| { |
| XSDSwitch xsdSwitch = new XSDSwitch() |
| { |
| public Object caseXSDElementDeclaration(XSDElementDeclaration object) |
| { |
| return new XSDElementDeclarationAdapter(object); |
| } |
| |
| public Object caseXSDParticle(XSDParticle object) |
| { |
| return new XSDParticleAdapter(object); |
| } |
| |
| public Object caseXSDSchema(XSDSchema object) |
| { |
| return new XSDSchemaAdapter(object); |
| } |
| |
| public Object defaultCase(EObject object) |
| { |
| return new XSDObjectAdapter(); |
| } |
| }; |
| Object o = xsdSwitch.doSwitch((EObject)target); |
| |
| Adapter result = null; |
| if (o instanceof Adapter) |
| { |
| result = (Adapter)o; |
| } |
| else |
| { |
| // System.out.println("did not create adapter for target : " + target); |
| // Thread.dumpStack(); |
| } |
| return result; |
| } |
| |
| |
| public Adapter adapt(Notifier target) |
| { |
| return adapt(target, this); |
| } |
| } |
| |
| |
| |
| // |
| // |
| // |
| protected static class XSDObjectAdapter extends AdapterImpl implements ModelAdapter |
| { |
| protected List listenerList = new ArrayList(); |
| protected boolean isUpdating = false; |
| |
| public boolean isAdapterForType(Object type) |
| { |
| return type == xsdAdapterFactoryImpl; |
| } |
| |
| public void addListener(ModelAdapterListener l) |
| { |
| listenerList.add(l); |
| } |
| |
| public void removeListener(ModelAdapterListener l) |
| { |
| listenerList.remove(l); |
| } |
| |
| public Object getProperty(Object modelObject, String propertyName) |
| { |
| Object result = null; |
| if (ModelAdapter.LABEL_PROPERTY.equals(propertyName)) |
| { |
| result = ""; |
| // TODO... move this logic into each adapter |
| // |
| if (modelObject instanceof XSDNamedComponent) |
| { |
| result = ((XSDNamedComponent)modelObject).getName(); |
| } |
| else if (modelObject instanceof XSDSchemaDirective) |
| { |
| result = ((XSDSchemaDirective)modelObject).getSchemaLocation(); |
| if (result == null) result = "(" + XSDEditorPlugin.getXSDString("_UI_LABEL_NO_LOCATION_SPECIFIED") + ")"; |
| if (result.equals("")) result = "(" + XSDEditorPlugin.getXSDString("_UI_LABEL_NO_LOCATION_SPECIFIED") + ")"; |
| return result; |
| } |
| } |
| else if ("drillDown".equals(propertyName)) |
| { |
| // TODO... move this logic into each adapter |
| // |
| List list = XSDChildUtility.getModelChildren(modelObject); |
| result = list.size() > 0 ? Boolean.TRUE : Boolean.FALSE; |
| } |
| else if (ModelAdapter.IMAGE_PROPERTY.equals(propertyName)) |
| { |
| // result = XSDEditorPlugin.getDefault().getImage("icons/XSDElement.gif"); |
| XSDModelAdapterFactoryImpl factory = XSDModelAdapterFactoryImpl.getInstance(); |
| Adapter adapter = factory.createAdapter((Notifier)modelObject); |
| result = ((XSDAbstractAdapter)adapter).getImage(modelObject); |
| } |
| return result; |
| } |
| |
| public void firePropertyChanged(Object modelObject, String propertyName) |
| { |
| List newList = new ArrayList(); |
| newList.addAll(listenerList); |
| for (Iterator i = newList.iterator(); i.hasNext(); ) |
| { |
| ModelAdapterListener l = (ModelAdapterListener)i.next(); |
| try |
| { |
| l.propertyChanged(modelObject, propertyName); |
| } |
| catch (Exception e) |
| { |
| } |
| } |
| } |
| |
| public void notifyChanged(Notification msg) |
| { |
| firePropertyChanged(msg.getNotifier(), null); |
| } |
| } |
| |
| protected static class XSDParticleAdapter extends XSDObjectAdapter implements ModelAdapterListener |
| { |
| protected XSDParticle particle; |
| |
| public XSDParticleAdapter(XSDParticle particle) |
| { |
| this.particle = particle; |
| } |
| |
| public void notifyChanged(Notification msg) |
| { |
| XSDParticle xsdParticle = (XSDParticle)msg.getNotifier(); |
| XSDParticleContent xsdParticleContent = xsdParticle.getContent(); |
| XSDModelAdapterFactoryImpl factory = XSDModelAdapterFactoryImpl.getInstance(); |
| if (xsdParticleContent != null) |
| { |
| if (xsdParticleContent instanceof XSDElementDeclaration) |
| { |
| firePropertyChanged((XSDElementDeclaration)xsdParticleContent, null); |
| factory.fireNotifyChanged(msg); |
| } |
| else if (xsdParticleContent instanceof XSDModelGroup) |
| { |
| firePropertyChanged((XSDModelGroup)xsdParticleContent, null); |
| factory.fireNotifyChanged(msg); |
| } |
| else if (xsdParticleContent instanceof XSDWildcard) |
| { |
| firePropertyChanged((XSDWildcard)xsdParticleContent, null); |
| factory.fireNotifyChanged(msg); |
| } |
| } |
| } |
| |
| |
| public void propertyChanged(Object object, String property) |
| { |
| firePropertyChanged(object, property); |
| } |
| } |
| |
| // |
| // |
| // |
| protected static class XSDElementDeclarationAdapter extends XSDObjectAdapter implements ModelAdapterListener |
| { |
| protected XSDElementDeclaration ed; |
| protected XSDTypeDefinition typeDefinition; |
| |
| public XSDElementDeclarationAdapter(XSDElementDeclaration ed) |
| { |
| this.ed = ed; |
| updateTypeDefinition(); |
| } |
| |
| protected void updateTypeDefinition() |
| { |
| XSDTypeDefinition td = ed.getTypeDefinition(); |
| td = (td instanceof XSDComplexTypeDefinition) ? td : null; |
| if (td != typeDefinition) |
| { |
| if (typeDefinition != null) |
| { |
| XSDObjectAdapter adapter = (XSDObjectAdapter)xsdAdapterFactoryImpl.adapt(typeDefinition); |
| adapter.removeListener(this); |
| } |
| typeDefinition = td; |
| if (typeDefinition != null) |
| { |
| XSDObjectAdapter adapter = (XSDObjectAdapter)xsdAdapterFactoryImpl.adapt(typeDefinition); |
| adapter.addListener(this); |
| } |
| } |
| } |
| |
| |
| public void notifyChanged(Notification msg) |
| { |
| updateTypeDefinition(); |
| firePropertyChanged(msg.getNotifier(), null); |
| } |
| |
| |
| public void propertyChanged(Object object, String property) |
| { |
| // here we propagate typeDefinition changes to our listeners |
| firePropertyChanged(object, property); |
| } |
| } |
| |
| |
| // |
| // |
| protected static class XSDSchemaAdapter extends XSDObjectAdapter |
| { |
| protected XSDSchema schema; |
| protected List groups; |
| |
| public XSDSchemaAdapter(XSDSchema schema) |
| { |
| this.schema = schema; |
| groups = new ArrayList(); |
| groups.add(new Category(schema, Category.DIRECTIVES)); |
| groups.add(new Category(schema, Category.ATTRIBUTES)); |
| //groups.add(new Category(schema, Category.ATTRIBUTE_GROUPS)); |
| groups.add(new Category(schema, Category.ELEMENTS)); |
| groups.add(new Category(schema, Category.TYPES)); |
| //groups.add(new Category(schema, Category.SIMPLE_TYPES)); |
| groups.add(new Category(schema, Category.GROUPS)); |
| } |
| |
| public void notifyChanged(Notification msg) |
| { |
| super.notifyChanged(msg); |
| for (Iterator i = groups.iterator(); i.hasNext(); ) |
| { |
| ModelAdapter group = (ModelAdapter)i.next(); |
| group.firePropertyChanged(group, null); |
| } |
| } |
| |
| public Object getProperty(Object modelObject, String propertyName) |
| { |
| Object result = null; |
| if ("groups".equals(propertyName)) |
| { |
| /* |
| List list = new ArrayList(); |
| for (Iterator i = groups.iterator(); i.hasNext(); ) |
| { |
| Category group = (Category)i.next(); |
| if (group.getChildren().size() > 0) |
| { |
| list.add(group); |
| } |
| } |
| result = list;*/ |
| result = groups; |
| } |
| if (result == null) |
| { |
| result = super.getProperty(modelObject, propertyName); |
| } |
| return result; |
| } |
| } |
| |
| |
| public static void addModelAdapterListener(Object modelObject, ModelAdapterListener listener) |
| { |
| ModelAdapter modelAdapter = getModelAdapter(modelObject); |
| if (modelAdapter != null) |
| { |
| modelAdapter.addListener(listener); |
| } |
| } |
| |
| |
| public static void removeModelAdapterListener(Object modelObject, ModelAdapterListener listener) |
| { |
| ModelAdapter modelAdapter = getModelAdapter(modelObject); |
| if (modelAdapter != null) |
| { |
| modelAdapter.removeListener(listener); |
| } |
| } |
| |
| protected static ModelAdapter getModelAdapter(Object modelObject) |
| { |
| ModelAdapter modelAdapter = null; |
| if (modelObject instanceof Notifier) |
| { |
| modelAdapter = (ModelAdapter)xsdAdapterFactoryImpl.adapt((Notifier)modelObject); |
| } |
| else if (modelObject instanceof ModelAdapter) |
| { |
| modelAdapter = (ModelAdapter)modelObject; |
| } |
| return modelAdapter; |
| } |
| } |
| |
| |
| |
| // -------------------------------------------------------------------------------------------- |
| // todo... revist this stuff |
| // -------------------------------------------------------------------------------------------- |
| |
| /* |
| public static void handleTypeChange(XSDTypeDefinition td, XSDSchema schema, int change) |
| { |
| try |
| { |
| TypeFindingSchemaVisitor visitor = new TypeFindingSchemaVisitor(schema, td, change == Notification.ADD); |
| List list = visitor.findElementsUsingType(schema); |
| |
| if (change == Notification.REMOVE) |
| { |
| visitor.removeMatchingReferences(); |
| } |
| else if (change == Notification.ADD) |
| { |
| visitor.setMatchingReferences(); |
| } |
| else |
| { |
| visitor.cleanUpTypeMismatches(); |
| } |
| |
| for (Iterator i = list.iterator(); i.hasNext(); ) |
| { |
| Object o = i.next(); |
| XSDObjectAdapter adapter = getExisitingAdapter(o); |
| if (adapter != null) |
| { |
| adapter.fireChildrenChangedNotification(); |
| } |
| } |
| } |
| catch (Exception e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| |
| |
| protected static class TypeFindingSchemaVisitor extends org.eclipse.wst.xsd.utility.XSDVisitor |
| { |
| protected XSDTypeDefinition td; |
| protected List list = new ArrayList(); |
| protected XSDSchema schema; |
| protected boolean matchByName; |
| |
| public TypeFindingSchemaVisitor(XSDSchema schema, XSDTypeDefinition td, boolean matchByName) |
| { |
| this.td = td; |
| this.schema = schema; |
| this.matchByName = matchByName; |
| } |
| |
| public void visitElementDeclaration(XSDElementDeclaration ed) |
| { |
| if (ed.getTypeDefinition() == td) |
| { |
| list.add(ed); |
| } |
| else if (matchByName) |
| { |
| String[] name = getDOMName(ed); |
| if (name[0].equals(td.getTargetNamespace()) && name[1].equals(td.getName())) |
| { |
| list.add(ed); |
| } |
| } |
| } |
| |
| public List findElementsUsingType(XSDSchema schema) |
| { |
| if (td != null) |
| { |
| visitSchema(schema); |
| } |
| return list; |
| } |
| |
| public List getMatchingTypeList() |
| { |
| return list; |
| } |
| |
| public String[] getDOMName(XSDElementDeclaration ed) |
| { |
| String[] result = new String[2]; |
| org.w3c.dom.Element domElement = ed.getElement(); |
| String typeName = domElement.getAttribute("type"); |
| if (typeName != null && !typeName.endsWith(td.getName())) |
| { |
| int index = typeName.indexOf(":"); |
| String prefix = index == -1 ? "" : typeName.substring(0, index); |
| result[0] = (String)schema.getQNamePrefixToNamespaceMap().get(prefix); |
| if (result[0] == null) result[0] = ""; |
| if (result[1] == null) result[1] = ""; |
| result[1] = index == -1 ? typeName : typeName.substring(index + 1); |
| } |
| else |
| { |
| result[0] = ""; |
| result[1] = ""; |
| } |
| return result; |
| } |
| |
| |
| public void cleanUpTypeMismatches() |
| { |
| for (Iterator i = list.iterator(); i.hasNext(); ) |
| { |
| XSDElementDeclaration ed = (XSDElementDeclaration)i.next(); |
| XSDTypeDefinition candidateTd = ed.getTypeDefinition(); |
| if (candidateTd != null && candidateTd.getName() != null) |
| { |
| String[] result = getDOMName(ed); |
| ed.setTypeDefinition((XSDTypeDefinition)schema.resolveComplexTypeDefinition(result[0], result[1])); |
| } |
| } |
| } |
| |
| public void removeMatchingReferences() |
| { |
| for (Iterator i = list.iterator(); i.hasNext(); ) |
| { |
| XSDElementDeclaration ed = (XSDElementDeclaration)i.next(); |
| String[] result = getDOMName(ed); |
| if (ed.getElement() != null) |
| { |
| // NOTE ... this forces the model to reset the ed's XSDTypeDefinition without causing the |
| // DOM element's 'type' attribute to be set to null |
| ed.elementAttributesChanged(ed.getElement()); |
| } |
| } |
| } |
| |
| public void setMatchingReferences() |
| { |
| for (Iterator i = list.iterator(); i.hasNext(); ) |
| { |
| XSDElementDeclaration ed = (XSDElementDeclaration)i.next(); |
| ed.setTypeDefinition(td); |
| } |
| } |
| } */ |