| /******************************************************************************* |
| * Copyright (c) 2006 Sybase, Inc. 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: |
| * Sybase, Inc. - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.pagedesigner.jsp.core.internal.pagevar; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.jst.pagedesigner.jsp.core.ListenerList; |
| import org.eclipse.jst.pagedesigner.jsp.core.pagevar.IChangeListener; |
| import org.eclipse.jst.pagedesigner.jsp.core.pagevar.IVariableInfo; |
| import org.eclipse.jst.pagedesigner.jsp.core.pagevar.adapter.IDocumentPageVariableAdapter; |
| import org.eclipse.jst.pagedesigner.jsp.core.pagevar.adapter.IPageVariableAdapter; |
| import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| /** |
| * This adapter will be adapted on the JSP document. |
| * |
| * @author mengbo |
| * @version 1.5 |
| */ |
| public class DocumentPageVariableAdapter implements |
| IDocumentPageVariableAdapter { |
| private IDOMDocument _document; |
| |
| private ListenerList _changeListeners = new ListenerList(2); |
| |
| private List _variableInfos = new ArrayList(); |
| |
| private boolean _readingInfo = false; |
| |
| /** |
| * @param doc |
| * |
| */ |
| public DocumentPageVariableAdapter(IDOMDocument doc) { |
| super(); |
| this._document = doc; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jst.pagedesigner.jsp.core.pagevar.IPageVariablesProvider#getBeanInfos() |
| */ |
| public IVariableInfo[] getBeanInfos() { |
| IVariableInfo[] ret = new IVariableInfo[_variableInfos.size()]; |
| return (IVariableInfo[]) _variableInfos.toArray(ret); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jst.pagedesigner.jsp.core.pagevar.IPageVariablesProvider#addChangeListener(org.eclipse.jst.pagedesigner.jsp.core.pagevar.IChangeListener) |
| */ |
| public void addChangeListener(IChangeListener listener) { |
| this.reReadInfo(); |
| _changeListeners.add(listener); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jst.pagedesigner.jsp.core.pagevar.IPageVariablesProvider#removeChangeListener(org.eclipse.jst.pagedesigner.jsp.core.pagevar.IChangeListener) |
| */ |
| public void removeChangeListener(IChangeListener listener) { |
| _changeListeners.remove(listener); |
| } |
| |
| /** |
| * fire change events on all listeners |
| */ |
| protected void fireChanged() { |
| Object[] listeners = _changeListeners.getListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| IChangeListener l = (IChangeListener) listeners[i]; |
| l.changed(); |
| } |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.wst.sse.core.internal.provisional.INodeAdapter#isAdapterForType(java.lang.Object) |
| */ |
| public boolean isAdapterForType(Object type) { |
| return IDocumentPageVariableAdapter.class.equals(type); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.wst.sse.core.internal.provisional.INodeAdapter#notifyChanged(org.eclipse.wst.sse.core.internal.provisional.INodeNotifier, |
| * int, java.lang.Object, java.lang.Object, java.lang.Object, int) |
| */ |
| public void notifyChanged(INodeNotifier notifier, int eventType, |
| Object changedFeature, Object oldValue, Object newValue, int pos) { |
| switch (eventType) { |
| case INodeNotifier.STRUCTURE_CHANGED: |
| case INodeNotifier.CONTENT_CHANGED: |
| case INodeNotifier.CHANGE: |
| refresh(); |
| break; |
| default: |
| // skip. Ignore other kinds of change. |
| } |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jst.pagedesigner.jsp.core.pagevar.IPageVariablesProvider#refresh() |
| */ |
| public void refresh() { |
| reReadInfo(); |
| } |
| |
| /** |
| * re-read page variable info |
| */ |
| protected void reReadInfo() { |
| if (this._readingInfo) { |
| return; |
| } |
| try { |
| List oldInfo = this._variableInfos; |
| this._variableInfos = new ArrayList(); |
| readNode(_document); |
| if (!isSame(oldInfo, this._variableInfos)) { |
| fireChanged(); |
| } |
| } finally { |
| this._readingInfo = false; |
| } |
| } |
| |
| /** |
| * compare two variable info list. |
| * |
| * @param oldInfo |
| * @param list |
| * @return true if same. |
| */ |
| private boolean isSame(List oldInfo, List list) { |
| if (oldInfo.size() != list.size()) { |
| return false; |
| } |
| for (int i = 0, size = oldInfo.size(); i < size; i++) { |
| IVariableInfo info1 = (IVariableInfo) oldInfo.get(i); |
| IVariableInfo info2 = (IVariableInfo) list.get(i); |
| if (info1 == null) { |
| return false;// should not happen |
| } |
| if (!info1.equals(info2)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * recursively read all element, and see whether they have |
| * IPageVariableAdapter, and then get variable info. |
| * |
| * @param element |
| */ |
| private void readNode(Node node) { |
| if (node instanceof INodeNotifier && node instanceof Element) { |
| Element element = (Element) node; |
| Object obj = ((INodeNotifier) element) |
| .getAdapterFor(IPageVariableAdapter.class); |
| if (obj instanceof IPageVariableAdapter) { |
| IPageVariableAdapter adapter = (IPageVariableAdapter) obj; |
| if (adapter.supportMultipleVariable(element)) { |
| List infos = ((IPageVariableAdapter) obj) |
| .getVariableInfos(element); |
| if (infos != null) { |
| this._variableInfos.addAll(infos); |
| } |
| } else { |
| // hope not doing addAll could improve some performance. |
| IVariableInfo info = adapter.getVariableInfo(element); |
| if (info != null) { |
| this._variableInfos.add(info); |
| } |
| } |
| } |
| } |
| |
| NodeList childNodes = node.getChildNodes(); |
| if (childNodes != null) { |
| for (int i = 0, length = childNodes.getLength(); i < length; i++) { |
| Node childNode = childNodes.item(i); |
| readNode(childNode); |
| } |
| } |
| } |
| } |