blob: 8fbb8e2d44de0e1cd9e8702dae59c28b3c417206 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 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.e4.core.services.internal.context;
import javax.inject.Named;
import org.eclipse.e4.core.services.context.ContextChangeEvent;
import org.eclipse.e4.core.services.context.IEclipseContext;
import org.eclipse.e4.core.services.context.IRunAndTrack;
import org.eclipse.e4.core.services.injector.AbstractObjectSupplier;
import org.eclipse.e4.core.services.injector.IInjector;
import org.eclipse.e4.core.services.injector.IObjectDescriptor;
import org.eclipse.e4.core.services.injector.IRequestor;
public class ContextObjectSupplier extends AbstractObjectSupplier {
static private class ContextInjectionListener implements IRunAndTrackObject {
final private Object[] result;
final private String[] keys;
final private IInjector injector;
final private IRequestor requestor;
final private AbstractObjectSupplier supplier;
final private IEclipseContext context;
public ContextInjectionListener(IEclipseContext context, Object[] result, String[] keys,
IInjector injector, IRequestor requestor, AbstractObjectSupplier supplier) {
this.result = result;
this.keys = keys;
this.injector = injector;
this.requestor = requestor;
this.supplier = supplier;
this.context = context;
}
public boolean notify(ContextChangeEvent event) {
if (event.getEventType() == ContextChangeEvent.INITIAL) {
// needs to be done inside runnable to establish dependencies
for (int i = 0; i < keys.length; i++) {
if (keys[i] == null)
continue;
if (context.containsKey(keys[i]))
result[i] = context.get(keys[i]);
else
result[i] = IInjector.NOT_A_VALUE; // TBD make sure this still creates
// dependency on the key
}
} else if (event.getEventType() == ContextChangeEvent.DISPOSE) {
injector.disposed(supplier);
return false;
} else if (event.getEventType() == ContextChangeEvent.UNINJECTED) {
injector.uninject(event.getArguments()[0], supplier);
return false;
} else
injector.update(new IRequestor[] { requestor }, supplier);
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((context == null) ? 0 : context.hashCode());
result = prime * result + ((injector == null) ? 0 : injector.hashCode());
result = prime * result + ((requestor == null) ? 0 : requestor.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ContextInjectionListener other = (ContextInjectionListener) obj;
if (context == null) {
if (other.context != null)
return false;
} else if (!context.equals(other.context))
return false;
if (injector == null) {
if (other.injector != null)
return false;
} else if (!injector.equals(other.injector))
return false;
if (requestor == null) {
if (other.requestor != null)
return false;
} else if (!requestor.equals(other.requestor))
return false;
return true;
}
public Object getObject() {
// XXX remove?
// TODO Auto-generated method stub
return null;
}
public boolean batchProcess() {
return requestor.shouldGroupUpdates();
}
}
final static private String ECLIPSE_CONTEXT_NAME = IEclipseContext.class.getName();
final private IEclipseContext context;
public ContextObjectSupplier(IEclipseContext context, IInjector injector) {
super(injector);
this.context = context;
}
public IEclipseContext getContext() {
return context;
}
@Override
public Object get(IObjectDescriptor descriptor, IRequestor requestor) {
// This method is rarely or never used on the primary supplier
if (descriptor == null)
return IInjector.NOT_A_VALUE;
Object[] result = get(new IObjectDescriptor[] { descriptor }, requestor);
if (result == null)
return null;
return result[0];
}
@Override
public Object[] get(IObjectDescriptor[] descriptors, final IRequestor requestor) {
final Object[] result = new Object[descriptors.length];
final String[] keys = new String[descriptors.length];
for (int i = 0; i < descriptors.length; i++) {
keys[i] = (descriptors[i] == null) ? null : getKey(descriptors[i]);
if (ECLIPSE_CONTEXT_NAME.equals(keys[i])) {
result[i] = context;
keys[i] = null;
}
}
if (requestor != null && requestor.shouldTrack()) { // only track if requested
IRunAndTrack trackable = new ContextInjectionListener(context, result, keys, injector,
requestor, this);
context.runAndTrack(trackable, null);
} else {
for (int i = 0; i < descriptors.length; i++) {
if (keys[i] == null)
continue;
if (context.containsKey(keys[i]))
result[i] = context.get(keys[i]);
else
result[i] = IInjector.NOT_A_VALUE;
}
}
return result;
}
private String getKey(IObjectDescriptor descriptor) {
if (descriptor.hasQualifier(Named.class.getName()))
return descriptor.getQualifierValue(Named.class.getName());
Class<?> elementClass = descriptor.getElementClass();
if (elementClass != null)
return elementClass.getName();
return null;
}
static public ContextObjectSupplier getObjectSupplier(IEclipseContext context,
IInjector injector) {
String key = ContextObjectSupplier.class.getName();
if (context.containsKey(key, true))
return (ContextObjectSupplier) context.get(key);
ContextObjectSupplier objectSupplier = new ContextObjectSupplier(context, injector);
context.set(key, objectSupplier);
return objectSupplier;
}
}