/*
* Copyright (c) 2004-2011 Marco Maccaferri 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:
* Marco Maccaferri - initial API and implementation
*/
package org.eclipsetrader.ui.internal.ats.explorer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.Observables;
import org.eclipse.core.databinding.observable.list.ObservableList;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
import org.eclipse.jface.databinding.viewers.TreeStructureAdvisor;
import org.eclipsetrader.core.IScript;
import org.eclipsetrader.core.ats.IScriptStrategy;
import org.eclipsetrader.core.ats.IStrategy;
import org.eclipsetrader.core.instruments.ISecurity;
import org.eclipsetrader.core.repositories.IRepositoryChangeListener;
import org.eclipsetrader.core.repositories.IRepositoryService;
import org.eclipsetrader.core.repositories.IStoreObject;
import org.eclipsetrader.core.repositories.RepositoryChangeEvent;
import org.eclipsetrader.core.repositories.RepositoryResourceDelta;
public class ExplorerViewModel extends TreeStructureAdvisor implements IObservableFactory {
private final IRepositoryService repositoryService;
private final List<ExplorerViewItem> list = new ArrayList<ExplorerViewItem>();
private final WritableList root = new WritableList(list, ExplorerViewItem.class);
public static class InstrumentRootItem implements ExplorerViewItem {
private final StrategyItem parent;
private final IStrategy strategy;
private final List<InstrumentItem> list = new ArrayList<InstrumentItem>();
private final WritableList childs = new WritableList(list, InstrumentItem.class);
public InstrumentRootItem(StrategyItem parent) {
this.parent = parent;
this.strategy = parent.getStrategy();
for (ISecurity instrument : strategy.getInstruments()) {
childs.add(new InstrumentItem(this, instrument));
}
}
public IStrategy getStrategy() {
return strategy;
}
public void update() {
List<ISecurity> currentInstruments = Arrays.asList(strategy.getInstruments());
List<InstrumentItem> toAdd = new ArrayList<InstrumentItem>();
for (ISecurity instrument : currentInstruments) {
if (!contains(instrument)) {
toAdd.add(new InstrumentItem(this, instrument));
}
}
List<InstrumentItem> toRemove = new ArrayList<InstrumentItem>();
for (InstrumentItem item : list) {
if (!currentInstruments.contains(item.getInstrument())) {
toRemove.add(item);
}
}
childs.addAll(toAdd);
childs.removeAll(toRemove);
}
private boolean contains(ISecurity instrument) {
for (Object o : childs) {
if (((InstrumentItem) o).getInstrument() == instrument) {
return true;
}
}
return false;
}
/* (non-Javadoc)
* @see org.eclipsetrader.ui.internal.ats.ExplorerViewItem#getParent()
*/
@Override
public ExplorerViewItem getParent() {
return parent;
}
/* (non-Javadoc)
* @see org.eclipsetrader.ui.internal.ats.ExplorerViewItem#hasChildren()
*/
@Override
public boolean hasChildren() {
return childs.size() != 0;
}
/* (non-Javadoc)
* @see org.eclipsetrader.ui.internal.ats.ExplorerViewItem#getItems()
*/
@Override
public ObservableList getItems() {
return childs;
}
/* (non-Javadoc)
* @see org.eclipsetrader.ui.internal.ats.ExplorerViewItem#accept(org.eclipsetrader.ui.internal.ats.ViewItemVisitor)
*/
@Override
public void accept(ExplorerViewItemVisitor visitor) {
visitor.visit(this);
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
*/
@Override
@SuppressWarnings({
"unchecked", "rawtypes"
})
public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(strategy.getClass())) {
return strategy;
}
if (adapter.isAssignableFrom(getClass())) {
return this;
}
return null;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Instruments";
}
}
public static class ScriptRootItem implements ExplorerViewItem {
private final StrategyItem parent;
private final IScriptStrategy strategy;
private final List<ScriptItem> list = new ArrayList<ScriptItem>();
private final WritableList childs = new WritableList(list, ScriptItem.class);
public ScriptRootItem(StrategyItem parent) {
this.parent = parent;
this.strategy = (IScriptStrategy) parent.getStrategy();
childs.add(new MainScriptItem(this));
for (IScript script : strategy.getIncludes()) {
childs.add(new ScriptItem(this, script));
}
}
public IStrategy getStrategy() {
return strategy;
}
public void update() {
List<IScript> currentScripts = Arrays.asList(strategy.getIncludes());
List<ScriptItem> toAdd = new ArrayList<ScriptItem>();
for (IScript script : currentScripts) {
if (!contains(script)) {
toAdd.add(new ScriptItem(this, script));
}
}
List<ScriptItem> toRemove = new ArrayList<ScriptItem>();
for (ScriptItem item : list.subList(1, list.size())) {
if (!currentScripts.contains(item.getScript())) {
toRemove.add(item);
}
}
childs.addAll(toAdd);
childs.removeAll(toRemove);
}
private boolean contains(IScript script) {
for (ScriptItem item : list.subList(1, list.size())) {
if (item.getScript() == script) {
return true;
}
}
return false;
}
/* (non-Javadoc)
* @see org.eclipsetrader.ui.internal.ats.ExplorerViewItem#getParent()
*/
@Override
public ExplorerViewItem getParent() {
return parent;
}
/* (non-Javadoc)
* @see org.eclipsetrader.ui.internal.ats.ExplorerViewItem#hasChildren()
*/
@Override
public boolean hasChildren() {
return childs.size() != 0;
}
/* (non-Javadoc)
* @see org.eclipsetrader.ui.internal.ats.ExplorerViewItem#getItems()
*/
@Override
public ObservableList getItems() {
return childs;
}
/* (non-Javadoc)
* @see org.eclipsetrader.ui.internal.ats.ExplorerViewItem#accept(org.eclipsetrader.ui.internal.ats.ViewItemVisitor)
*/
@Override
public void accept(ExplorerViewItemVisitor visitor) {
visitor.visit(this);
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class)
*/
@Override
@SuppressWarnings({
"unchecked", "rawtypes"
})
public Object getAdapter(Class adapter) {
if (adapter.isAssignableFrom(strategy.getClass())) {
return strategy;
}
if (adapter.isAssignableFrom(getClass())) {
return this;
}
return null;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Scripts";
}
}
private final IRepositoryChangeListener repositoryChangeListener = new IRepositoryChangeListener() {
@Override
public void repositoryResourceChanged(RepositoryChangeEvent event) {
for (RepositoryResourceDelta delta : event.getDeltas()) {
if (delta.getResource() instanceof IStrategy) {
IStrategy resource = (IStrategy) delta.getResource();
if ((delta.getKind() & RepositoryResourceDelta.CHANGED) != 0) {
StrategyItem viewItem = (StrategyItem) getViewItemFor(resource);
if (viewItem != null) {
viewItem.update();
}
}
else if ((delta.getKind() & RepositoryResourceDelta.ADDED) != 0) {
root.add(new StrategyItem(resource));
}
else if ((delta.getKind() & RepositoryResourceDelta.REMOVED) != 0) {
ExplorerViewItem viewItem = getViewItemFor(resource);
if (viewItem != null) {
if (viewItem.getParent() == null) {
root.remove(viewItem);
}
else {
viewItem.getParent().getItems().remove(viewItem);
}
}
}
}
}
}
};
public ExplorerViewModel(IRepositoryService repositoryService) {
this.repositoryService = repositoryService;
for (IStoreObject object : repositoryService.getAllObjects()) {
if (object instanceof IStrategy) {
root.add(new StrategyItem((IStrategy) object));
}
}
repositoryService.addRepositoryResourceListener(repositoryChangeListener);
}
public WritableList getRoot() {
return root;
}
public void dispose() {
repositoryService.removeRepositoryResourceListener(repositoryChangeListener);
root.clear();
root.dispose();
}
/* (non-Javadoc)
* @see org.eclipse.core.databinding.observable.masterdetail.IObservableFactory#createObservable(java.lang.Object)
*/
@Override
public IObservable createObservable(Object target) {
if (target == this) {
return Observables.unmodifiableObservableList(root);
}
if (target instanceof ExplorerViewItem) {
ObservableList list = ((ExplorerViewItem) target).getItems();
if (list != null) {
return Observables.unmodifiableObservableList(list);
}
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.databinding.viewers.TreeStructureAdvisor#getParent(java.lang.Object)
*/
@Override
public Object getParent(Object element) {
if (element instanceof ExplorerViewItem) {
return ((ExplorerViewItem) element).getParent();
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.databinding.viewers.TreeStructureAdvisor#hasChildren(java.lang.Object)
*/
@Override
public Boolean hasChildren(Object element) {
if (element == this) {
return root.size() != 0;
}
if (element instanceof ExplorerViewItem) {
return ((ExplorerViewItem) element).hasChildren();
}
return false;
}
public ExplorerViewItem getViewItemFor(final Object target) {
final AtomicReference<ExplorerViewItem> result = new AtomicReference<ExplorerViewItem>();
final ExplorerViewItemVisitor visitor = new ExplorerViewItemVisitor() {
@Override
public void visit(ExplorerViewItem viewItem) {
if (viewItem.getAdapter(target.getClass()) == target) {
result.set(viewItem);
}
else if (viewItem.getItems() != null) {
for (Object childItem : viewItem.getItems()) {
((ExplorerViewItem) childItem).accept(this);
if (result.get() != null) {
break;
}
}
}
}
};
for (ExplorerViewItem viewItem : list) {
viewItem.accept(visitor);
if (result.get() != null) {
break;
}
}
return result.get();
}
}