/*******************************************************************************
* Copyright (c) 2012, 2013 Wind River Systems, 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.tcf.processes.core.model.runtime.services;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.tcf.te.runtime.callback.Callback;
import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback;
import org.eclipse.tcf.te.runtime.model.interfaces.IContainerModelNode;
import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx;
import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryState;
import org.eclipse.tcf.te.runtime.model.interfaces.contexts.IAsyncRefreshableCtx.QueryType;
import org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelRefreshService;
import org.eclipse.tcf.te.tcf.core.model.services.AbstractModelService;
import org.eclipse.tcf.te.tcf.processes.core.activator.CoreBundleActivator;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.IProcessContextNode;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.IProcessContextNodeProperties;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModel;
import org.eclipse.tcf.te.tcf.processes.core.model.interfaces.runtime.IRuntimeModelLookupService;
/**
* Runtime model lookup service implementation.
*/
public class RuntimeModelLookupService extends AbstractModelService<IRuntimeModel> implements IRuntimeModelLookupService {
/**
* Constructor.
*
* @param model The parent model. Must not be <code>null</code>.
*/
public RuntimeModelLookupService(IRuntimeModel model) {
super(model);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelLookupService#lkupModelNodeByUUID(java.util.UUID)
*/
@Override
public IModelNode lkupModelNodeByUUID(UUID uuid) {
return getModel().find(uuid);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelLookupService#lkupModelNodesById(java.lang.String)
*/
@Override
public IModelNode[] lkupModelNodesById(String id) {
Assert.isNotNull(id);
List<IModelNode> nodes = new ArrayList<IModelNode>();
nodes.addAll(findInContainerByIdRecursively(getModel(), id));
return nodes.toArray(new IModelNode[nodes.size()]);
}
/**
* Search the given container recursively and returns all nodes matching the given id.
*
* @param container The container. Must not be <code>null</code<.
* @param id The id to match. Must not be <code>null</code>.
*
* @return The list of matching nodes, or an empty list.
*/
private List<IModelNode> findInContainerByIdRecursively(IContainerModelNode container, String id) {
Assert.isNotNull(container);
Assert.isNotNull(id);
List<IModelNode> nodes = new ArrayList<IModelNode>();
List<IModelNode> candidates = container.getChildren(IModelNode.class);
for (IModelNode candidate : candidates) {
if (id.equals(candidate.getStringProperty(IProcessContextNodeProperties.PROPERTY_ID)) && !nodes.contains(candidate)) {
nodes.add(candidate);
}
if (candidate instanceof IContainerModelNode) nodes.addAll(findInContainerByIdRecursively((IContainerModelNode)candidate, id));
}
return nodes;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelLookupService#lkupModelNodesByName(java.lang.String)
*/
@Override
public IModelNode[] lkupModelNodesByName(String name) {
Assert.isNotNull(name);
List<IModelNode> nodes = new ArrayList<IModelNode>();
nodes.addAll(findInContainerByNameRecursively(getModel(), name));
return nodes.toArray(new IModelNode[nodes.size()]);
}
/**
* Search the given container recursively and returns all nodes matching the given name.
*
* @param container The container. Must not be <code>null</code<.
* @param name The name to match. Must not be <code>null</code>.
*
* @return The list of matching nodes, or an empty list.
*/
private List<IModelNode> findInContainerByNameRecursively(IContainerModelNode container, String name) {
Assert.isNotNull(container);
Assert.isNotNull(name);
List<IModelNode> nodes = new ArrayList<IModelNode>();
List<IModelNode> candidates = container.getChildren(IModelNode.class);
for (IModelNode candidate : candidates) {
if (name.equals(candidate.getName()) && !nodes.contains(candidate)) {
nodes.add(candidate);
}
if (candidate instanceof IContainerModelNode) nodes.addAll(findInContainerByNameRecursively((IContainerModelNode)candidate, name));
}
return nodes;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.tcf.core.model.interfaces.services.IModelLookupService#lkupModelNodeByCapability(java.lang.String[], org.eclipse.tcf.te.runtime.interfaces.callback.ICallback)
*/
@Override
public void lkupModelNodeByCapability(final String[] capabilities, final ICallback callback) {
Assert.isNotNull(capabilities);
Assert.isTrue(capabilities.length > 0);
Assert.isNotNull(callback);
final IAsyncRefreshableCtx refreshable = (IAsyncRefreshableCtx)getModel().getAdapter(IAsyncRefreshableCtx.class);
if (refreshable != null && Boolean.getBoolean("sm.trace.rootnodelkup")) { //$NON-NLS-1$
String message = "RuntimeModelLookupService: lkupModelNodeByCapability: runtime model refreshable=" + refreshable + ", capabilities=" + Arrays.deepToString(capabilities); //$NON-NLS-1$ //$NON-NLS-2$
IStatus s = new Status(IStatus.INFO, CoreBundleActivator.getUniqueIdentifier(), message);
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(s);
}
if (refreshable != null && refreshable.getQueryState(QueryType.CHILD_LIST) != QueryState.DONE) {
// The model needs a refresh
getModel().getService(IModelRefreshService.class).refresh(new Callback() {
@Override
protected void internalDone(Object caller, IStatus status) {
callback.setResult(findInContainerByCapabilitiesRecursively(getModel(), capabilities));
callback.done(RuntimeModelLookupService.this, Status.OK_STATUS);
}
});
} else {
callback.setResult(findInContainerByCapabilitiesRecursively(getModel(), capabilities));
callback.done(RuntimeModelLookupService.this, Status.OK_STATUS);
}
}
/**
* Search the given container recursively and returns all nodes matching the given capabilities.
*
* @param container The container. Must not be <code>null</code<.
* @param capabilities The capabilities to match. Must not be <code>null</code>.
*
* @return The list of matching nodes, or an empty list.
*/
protected IProcessContextNode findInContainerByCapabilitiesRecursively(IContainerModelNode container, String[] capabilities) {
Assert.isNotNull(container);
Assert.isNotNull(capabilities);
if (Boolean.getBoolean("sm.trace.rootnodelkup")) { //$NON-NLS-1$
String message = "RuntimeModelLookupService: findInContainerByCapabilitiesRecursively: container=" + container + ", capabilities=" + Arrays.deepToString(capabilities); //$NON-NLS-1$ //$NON-NLS-2$
IStatus s = new Status(IStatus.INFO, CoreBundleActivator.getUniqueIdentifier(), message);
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(s);
}
IProcessContextNode node = null;
List<IProcessContextNode> candidates = container.getChildren(IProcessContextNode.class);
for (IProcessContextNode candidate : candidates) {
@SuppressWarnings("unchecked")
Map<String, Object> caps = (Map<String, Object>)candidate.getProperty(IProcessContextNodeProperties.PROPERTY_CAPABILITIES);
if (Boolean.getBoolean("sm.trace.rootnodelkup")) { //$NON-NLS-1$
String message = "RuntimeModelLookupService: findInContainerByCapabilitiesRecursively: candidate=" + candidate + ", capabilities=" + caps.keySet(); //$NON-NLS-1$ //$NON-NLS-2$
IStatus s = new Status(IStatus.INFO, CoreBundleActivator.getUniqueIdentifier(), message);
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(s);
}
if (caps != null) {
boolean allFound = true;
for (String capability : capabilities) {
if (!caps.containsKey(capability) || !Boolean.parseBoolean(caps.get(capability).toString())) {
allFound = false;
break;
}
}
if (allFound) {
node = candidate;
break;
}
}
}
if (node == null) {
for (IProcessContextNode candidate : candidates) {
node = findInContainerByCapabilitiesRecursively(candidate, capabilities);
if (node != null) {
break;
}
}
}
if (Boolean.getBoolean("sm.trace.rootnodelkup")) { //$NON-NLS-1$
String message = "RuntimeModelLookupService: findInContainerByCapabilitiesRecursively: node=" + node; //$NON-NLS-1$
IStatus s = new Status(IStatus.INFO, CoreBundleActivator.getUniqueIdentifier(), message);
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(s);
}
return node;
}
}