/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.jsf.ui.editor.model.impl;
import java.util.*;
import java.beans.*;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Control;
import org.jboss.tools.common.model.*;
import org.jboss.tools.common.model.event.*;
import org.jboss.tools.jsf.JSFPreference;
import org.jboss.tools.jsf.model.helpers.JSFProcessStructureHelper;
import org.jboss.tools.jsf.ui.JsfUiPlugin;
import org.jboss.tools.jsf.ui.editor.model.IJSFElement;
import org.jboss.tools.jsf.ui.editor.model.IJSFElementList;
import org.jboss.tools.jsf.ui.editor.model.IJSFModel;
import org.jboss.tools.jsf.ui.editor.model.IJSFModelListener;
import org.jboss.tools.jsf.ui.editor.model.IJSFOptions;
import org.jboss.tools.jsf.ui.editor.model.ILink;
import org.jboss.tools.jsf.ui.editor.model.IGroup;
import org.jboss.tools.jsf.ui.editor.model.IPage;
import org.jboss.tools.jsf.ui.preferences.JSFFlowTabbedPreferencesPage;
import org.jboss.tools.common.model.ui.action.*;
import org.jboss.tools.common.model.ui.util.ModelUtilities;
import org.jboss.tools.common.model.util.XModelTreeListenerSWTSync;
public class JSFModel extends JSFElement implements IJSFModel, PropertyChangeListener, XModelTreeListener {
protected List<IJSFModelListener> strutsModelListeners = new Vector<IJSFModelListener>();
protected JSFHashtable map = new JSFHashtable();
protected JSFElementList processItemList = new ProcessItemList();
protected JSFProcessStructureHelper helper = JSFProcessStructureHelper.instance;
protected JSFOptions options;
protected boolean modified = false;
public JSFModel() {
try {
setName("Struts Model");
} catch (PropertyVetoException ex) {
JsfUiPlugin.getPluginLog().logError(ex);
}
}
public void dispose() {
this.disconnectFromModel();
if (map != null)
map.dispose();
map = null;
if (strutsModelListeners != null)
strutsModelListeners.clear();
strutsModelListeners = null;
if (processItemList != null)
processItemList.dispose();
processItemList = null;
if (options != null)
options.dispose();
options = null;
}
public boolean isBorderPaint() {
return false;
}
public IJSFOptions getOptions() {
return options;
}
public JSFModel(Object data) {
this();
setData(((XModelObject) data).getChildByPath("process")); //$NON-NLS-1$
map.setData((XModelObject) data);
}
public void updateLinks() {
IGroup group;
IPage page;
for (int i = 0; i < getGroupList().size(); i++) {
group = (IGroup) getGroupList().get(i);
for (int j = 0; j < group.getPageList().size(); j++) {
page = (IPage) group.getPageList().get(j);
for (int k = 0; k < page.getLinkList().size(); k++) {
((ILink) page.getLinkList().get(k)).setTarget();
}
}
}
}
public Object get(String name) {
return null;
}
public void put(String name, Object value) {
}
public JSFProcessStructureHelper getHelper() {
return helper;
}
public int getProcessItemCounter() {
return processItemList.size();
}
public IGroup getGroup(int index) {
return (IGroup) processItemList.get(index);
}
public IGroup getGroup(String groupName) {
return (IGroup) processItemList.get(groupName);
}
public IGroup getGroup(Object source) {
IGroup[] is = (IGroup[]) processItemList.elements
.toArray(new IGroup[0]);
for (int i = 0; i < is.length; i++)
if (is[i].getSource() == source)
return is[i];
return null;
}
// Module removers
public void removeGroup(String moduleName) {
}
public void removeGroup(IGroup removeProcessItem) {
}
public void propertyChange(PropertyChangeEvent pce) {
}
IGroup selectedGroup = null;
public void setSelectedProcessItem(IGroup group) {
IGroup oldValue = selectedGroup;
selectedGroup = group;
propertyChangeSupport.firePropertyChange("selectedProcessItem", //$NON-NLS-1$
oldValue, group);
}
public IGroup getSelectedProcessItem() {
return selectedGroup;
}
public String getText() {
return ""; //$NON-NLS-1$
}
XModelTreeListenerSWTSync listener = null;
public void setData(Object data) {
source = (XModelObject) data;
if (source == null) {
return;
}
helper.autolayout(source);
map.put(source.getPath(), this);
processItemList = new ProcessItemList(source);
listener = new XModelTreeListenerSWTSync(this);
source.getModel().addModelTreeListener(listener);
options = new JSFOptions();
}
public void disconnectFromModel() {
if (listener != null) {
source.getModel().removeModelTreeListener(listener);
}
if(options != null) {
options.disconnectFromModel();
}
if(map != null) {
map.disconnectFromModel();
}
}
public boolean isEditable() {
return source != null
&& source.getModelEntity().isEditable(source, "body"); //$NON-NLS-1$
}
public boolean areCommentsVisible() {
return false;
}
public boolean isModified() {
return modified;
}
public void setModified(boolean set) {
boolean oldValue = modified;
modified = set;
propertyChangeSupport
.firePropertyChange("modified", oldValue, modified); //$NON-NLS-1$
}
// -----------------------------------------------------------------------
// fire events
// -----------------------------------------------------------------------
public void fireProcessChanged(boolean flag) {
if (strutsModelListeners == null)
return;
List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>();
targets.addAll(strutsModelListeners);
for (int i = 0; i < targets.size(); i++) {
IJSFModelListener listener = (IJSFModelListener) targets.get(i);
if (listener != null) {
listener.processChanged(flag);
}
}
setModified(true);
}
public void fireProcessItemAdd(IGroup newProcessItem) {
List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>();
targets.addAll(strutsModelListeners);
for (int i = 0; i < targets.size(); i++) {
IJSFModelListener listener = (IJSFModelListener) targets.get(i);
if (listener != null) {
listener.groupAdd(newProcessItem);
}
}
setModified(true);
}
public void fireProcessItemRemove(IGroup newProcessItem, int index) {
List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>();
targets.addAll(strutsModelListeners);
for (int i = 0; i < targets.size(); i++) {
IJSFModelListener listener = (IJSFModelListener) targets.get(i);
if (listener != null) {
listener.groupRemove(newProcessItem);
}
}
setModified(true);
}
public void fireLinkAdd(ILink newLink) {
List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>();
targets.addAll(strutsModelListeners);
for (int i = 0; i < targets.size(); i++) {
IJSFModelListener listener = (IJSFModelListener) targets.get(i);
if (listener != null) {
listener.linkAdd(newLink);
}
}
setModified(true);
}
public void fireLinkRemove(ILink newLink) {
List<IJSFModelListener> targets = new ArrayList<IJSFModelListener>();
targets.addAll(strutsModelListeners);
for (int i = 0; i < targets.size(); i++) {
IJSFModelListener listener = (IJSFModelListener) targets.get(i);
if (listener != null) {
listener.linkRemove(newLink);
}
}
setModified(true);
}
public void fireElementRemoved(IJSFElement element, int index) {
}
public void fireElementInserted(IJSFElement element) {
}
public void addJSFModelListener(IJSFModelListener listener) {
strutsModelListeners.add(listener);
}
public void removeJSFModelListener(IJSFModelListener listener) {
if(strutsModelListeners != null) strutsModelListeners.remove(listener);
}
public void remove() {
}
public String getIconPath() {
return null;
}
public IGroup addGroup(IGroup group) {
return null;
}
public IGroup addGroup(String group) {
return null;
}
public IGroup addGroup(Object source, int x, int y) {
return null;
}
public IGroup addGroup(IJSFElement element) {
return null;
}
public IJSFElementList getGroupList() {
return processItemList;
}
public void nodeChanged(XModelTreeEvent event) {
fireProcessChanged(false);
if (map == null || event == null)
return;
IJSFElement element = (JSFElement) map.get(event.getInfo());
if (element != null
&& !event.getModelObject().getPath()
.equals(event.getInfo())) {
updateCash((String) event.getInfo());
}
String path = event.getModelObject().getPath();
element = (path == null) ? null : (IJSFElement) map.get(path);
if (element == null) {
return;
}
element.nodeChanged(event);
}
public void structureChanged(XModelTreeEvent event) {
JSFElement element;
Object obj = event.getModelObject().getPath();
if (obj == null)
return;
if (map == null)
return;
element = (JSFElement) map.get(obj);
if (element == null) {
return;
}
if (event.kind() == XModelTreeEvent.STRUCTURE_CHANGED) {
element.structureChanged(event);
} else if (event.kind() == XModelTreeEvent.CHILD_ADDED) {
element.nodeAdded(event);
} else if (event.kind() == XModelTreeEvent.CHILD_REMOVED) {
element.nodeRemoved(event);
}
}
public void putToMap(Object key, IJSFElement value) {
getMap().put(key, value);
}
public void removeFromMap(Object key) {
getMap().remove(key);
}
public IJSFElement getFromMap(Object key) {
return getMap().get(key);
}
public class ProcessItemPropertyChangeListener implements
PropertyChangeListener {
public void propertyChange(PropertyChangeEvent event) {
IGroup processItem = (IGroup) event.getSource();
if (event.getPropertyName().equals("selected")) { //$NON-NLS-1$
if (((Boolean) event.getNewValue()).booleanValue())
setSelectedProcessItem(processItem);
}
}
}
public class ProcessItemList extends JSFElementList {
protected ProcessItemList() {
}
public ProcessItemList(XModelObject processItemSource) {
super(JSFModel.this, JSFModel.this.source);
if (((XModelObject) JSFModel.this.getSource()).getPath() == null)
return;
XModelObject[] processItemNodeList = getHelper().getGroups(
JSFModel.this.source);
for (int i = 0; i < processItemNodeList.length; i++) {
IGroup newProcessItem = new Group(JSFModel.this,
processItemNodeList[i]);
newProcessItem.addPropertyChangeListener("selected", //$NON-NLS-1$
new ProcessItemPropertyChangeListener());
add(newProcessItem);
}
}
public void structureChanged(Object eventData) {
}
public void nodeAdded(Object eventData) {
XModelTreeEvent event = (XModelTreeEvent) eventData;
IGroup newProcessItem = new Group(JSFModel.this,
((XModelObject) event.getInfo()));
this.add(newProcessItem);
fireProcessItemAdd(newProcessItem);
}
public void nodeRemoved(Object eventData) {
XModelTreeEvent event = (XModelTreeEvent) eventData;
IJSFElement removedProcessItem = this.getFromMap(event.getInfo());
int index = this.indexOf(removedProcessItem);
removedProcessItem.remove();
this.remove(removedProcessItem);
this.removeFromMap(((XModelTreeEvent) eventData).getInfo());
fireProcessItemRemove((Group) removedProcessItem, index);
clearCash((String) event.getInfo());
}
}
public JSFHashtable getMap() {
return map;
}
public IJSFElement findElement(String key) {
return map.get(key);
}
public class JSFHashtable implements XModelTreeListener {
private Hashtable<Object, IJSFElement> map = new Hashtable<Object, IJSFElement>();
XModelObject source;
String name;
public void dispose() {
disconnectFromModel();
if (map != null)
map.clear();
map = null;
}
public void put(Object key, IJSFElement value) {
map.put(key, value);
}
public void setData(XModelObject data) {
source = data;
source.getModel().addModelTreeListener(JSFHashtable.this);
name = source.getAttributeValue("name"); //$NON-NLS-1$
}
public void disconnectFromModel() {
source.getModel().removeModelTreeListener(JSFHashtable.this);
}
public IJSFElement get(Object key) {
return map.get(key);
}
public void remove(Object key) {
map.remove(key);
}
public void nodeChanged(XModelTreeEvent event) {
String path;
JSFElement element;
if (!source.getAttributeValue("name").equals(name)) { //$NON-NLS-1$
name = source.getAttributeValue("name"); //$NON-NLS-1$
Enumeration<Object> keys = map.keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
if(!(key instanceof String)) continue;
path = (String) key;
element = (JSFElement) map.get(path);
if (element != null) {
if (element.getSource() != null) {
map.remove(path);
map.put(((XModelObject) element.getSource())
.getPath(), element);
}
}
}
}
}
public void structureChanged(XModelTreeEvent event) {
}
}
protected void clearCash(String path) {
updateCash(path, true);
}
protected void updateCash(String path) {
updateCash(path, false);
}
protected void updateCash(String path, boolean clear) {
String rpath = path + "/"; //$NON-NLS-1$
Object[] ks = map.map.keySet().toArray();
for (int i = 0; i < ks.length; i++) {
if (!ks[i].equals(path) && !ks[i].toString().startsWith(rpath))
continue;
IJSFElement n = (IJSFElement) map.map.get(ks[i]);
map.map.remove(ks[i]);
if (clear)
continue;
XModelObject o = (XModelObject) n.getSource();
if (!o.isActive())
continue;
map.map.put(o.getPath(), n);
}
}
public Menu getPopupMenu(Control control, Object environment) {
if (source == null)
return null;
if (source.getModelEntity().getActionList().getActionItems().length != 0) {
XModelObjectActionList l = new XModelObjectActionList(source
.getModelEntity().getActionList(), source, null,
environment);
Menu menu = l.createMenu(control);
return menu;
}
return null;
}
public Menu getPopupMenu(Control control) {
return getPopupMenu(control, null);
}
public boolean isConfirmed() {
return true;
}
class JSFOptions implements XModelTreeListener, IJSFOptions {
XModelObject optionsObject = ModelUtilities.getPreferenceModel()
.getByPath(JSFFlowTabbedPreferencesPage.JSF_EDITOR_PATH);
XModelTreeListenerSWTSync optionsListener = new XModelTreeListenerSWTSync(
this);
Font viewPathFont = null, linkPathFont = null;
public JSFOptions() {
optionsObject.getModel().addModelTreeListener(optionsListener);
}
public void dispose() {
disconnectFromModel();
if (linkPathFont != null && linkPathFont.isDisposed())
linkPathFont.dispose();
linkPathFont = null;
if (viewPathFont != null && viewPathFont.isDisposed())
viewPathFont.dispose();
viewPathFont = null;
}
public boolean isGridVisible() {
String str = optionsObject.getAttributeValue("Show Grid"); //$NON-NLS-1$
if (str.equals("yes")) //$NON-NLS-1$
return true;
else
return false;
}
public int getGridStep() {
return 8;
}
public int getVisualGridStep() {
String str = optionsObject.getAttributeValue("Grid Step"); //$NON-NLS-1$
return Integer.parseInt(str);
}
public Font getLinkPathFont() {
String name;
int size = 8, style = 1;
int pos, pos2, pos3;
String str = optionsObject.getAttributeValue("Link Path Font"); //$NON-NLS-1$
pos = str.indexOf(","); //$NON-NLS-1$
if (pos < 0)
name = str;
else {
name = str.substring(0, pos);
pos2 = str.indexOf("size="); //$NON-NLS-1$
if (pos2 >= 0) {
pos3 = str.indexOf(",", pos2); //$NON-NLS-1$
if (pos3 < 0)
size = Integer.parseInt(str
.substring(pos2 + 5, str.length()));
else
size = Integer.parseInt(str.substring(pos2 + 5, pos3));
}
pos2 = str.indexOf("style="); //$NON-NLS-1$
if (pos2 >= 0) {
pos3 = str.indexOf(",", pos2); //$NON-NLS-1$
if (pos3 < 0)
style = Integer.parseInt(str.substring(pos2 + 6, str
.length()));
else
style = Integer.parseInt(str.substring(pos2 + 6, pos3));
}
}
if (linkPathFont == null) {
linkPathFont = new Font(null, name, size, style);
} else {
if (!linkPathFont.getFontData()[0].getName().equals(name)
|| linkPathFont.getFontData()[0].getHeight() != size
|| linkPathFont.getFontData()[0].getStyle() != style) {
linkPathFont = new Font(null, name, size, style);
}
}
return linkPathFont;
}
public Font getViewPathFont() {
String name;
int size = 8, style = 1;
int pos, pos2, pos3;
String str = optionsObject.getAttributeValue("View Path Font"); //$NON-NLS-1$
pos = str.indexOf(","); //$NON-NLS-1$
if (pos < 0)
name = str;
else {
name = str.substring(0, pos);
pos2 = str.indexOf("size="); //$NON-NLS-1$
if (pos2 >= 0) {
pos3 = str.indexOf(",", pos2); //$NON-NLS-1$
if (pos3 < 0)
size = Integer.parseInt(str
.substring(pos2 + 5, str.length()));
else
size = Integer.parseInt(str.substring(pos2 + 5, pos3));
}
pos2 = str.indexOf("style="); //$NON-NLS-1$
if (pos2 >= 0) {
pos3 = str.indexOf(",", pos2); //$NON-NLS-1$
if (pos3 < 0)
style = Integer.parseInt(str.substring(pos2 + 6, str
.length()));
else
style = Integer.parseInt(str.substring(pos2 + 6, pos3));
}
}
if (viewPathFont == null) {
viewPathFont = new Font(null, name, size, style);
} else {
if (!viewPathFont.getFontData()[0].getName().equals(name)
|| viewPathFont.getFontData()[0].getHeight() != size
|| viewPathFont.getFontData()[0].getStyle() != style) {
viewPathFont = new Font(null, name, size, style);
}
}
return viewPathFont;
}
public void disconnectFromModel() {
optionsObject.getModel().removeModelTreeListener(optionsListener);
if (optionsListener != null)
optionsListener.dispose();
optionsListener = null;
}
public void nodeChanged(XModelTreeEvent event) {
fireProcessChanged(false);
Group group;
for (int i = 0; i < getGroupList().size(); i++) {
group = (Group) getGroupList().get(i);
group.fireGroupChange();
for (int j = 0; j < group.getListOutputLinks().size(); j++) {
((Link) group.getListOutputLinks().get(j)).fireLinkChange();
}
}
}
public void structureChanged(XModelTreeEvent event) {
//fireProcessChanged(false);
}
public boolean switchToSelectionTool() {
String str = JSFPreference.ENABLE_CONTROL_MODE_ON_TRANSITION_COMPLETED
.getValue();
if (str != null && str.equals("yes")) //$NON-NLS-1$
return true;
else
return false;
}
public boolean showShortcutIcon() {
String str = JSFPreference.SHOW_SHORTCUT_ICON.getValue();
if (str != null && str.equals("yes")) //$NON-NLS-1$
return true;
else
return false;
}
public boolean showShortcutPath() {
String str = JSFPreference.SHOW_SHORTCUT_PATH.getValue();
if (str != null && str.equals("yes")) //$NON-NLS-1$
return true;
else
return false;
}
}
}