/*******************************************************************************
* Copyright (c) 2010 xored software, Inc.
*
* 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:
* xored software, Inc. - initial API and Implementation (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.launching.model;
import java.io.File;
import java.io.IOException;
import java.util.ListIterator;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.dltk.core.Predicate;
import org.eclipse.dltk.internal.launching.DLTKLaunchingPlugin;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EContentAdapter;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
public class LaunchingModel {
private static LaunchingModel instance = null;
public static synchronized LaunchingModel getInstance() {
if (instance == null) {
instance = new LaunchingModel();
}
return instance;
}
private LaunchingModel() {
}
private class Model {
final Resource resource;
public Model(Resource resource) {
this.resource = resource;
}
public InterpreterInfo find(IInterpreterInstall interpreter) {
final String environmentId = interpreter.getEnvironmentId();
final String location = interpreter.getInstallLocation().getPath()
.toString();
for (EObject object : resource.getContents()) {
if (object instanceof InterpreterInfo) {
final InterpreterInfo info = (InterpreterInfo) object;
if (environmentId.equals(info.getEnvironment())
&& location.equals(info.getLocation())) {
return info;
}
}
}
return null;
}
/**
* @param interpreter
* @return
*/
public InterpreterInfo create(IInterpreterInstall interpreter) {
InterpreterInfo info = find(interpreter);
if (info == null) {
info = LaunchingModelFactory.eINSTANCE.createInterpreterInfo();
info.setEnvironment(interpreter.getEnvironmentId());
info.setLocation(interpreter.getInstallLocation().getPath()
.toString());
resource.getContents().add(info);
}
return info;
}
public void save() {
try {
resource.save(null);
synchronized (modelLock) {
model = null;
}
} catch (IOException e) {
DLTKLaunchingPlugin.log(e);
}
}
}
private static class ModelApapter extends EContentAdapter {
@Override
public void notifyChanged(Notification notification) {
if (!notification.isTouch())
throw new UnsupportedOperationException();
super.notifyChanged(notification);
}
}
private Model model = null;
private final Object modelLock = new Object();
private Model getModel() {
synchronized (modelLock) {
if (model == null) {
model = loadModel();
model.resource.eAdapters().add(new ModelApapter());
}
return model;
}
}
private static final String MODEL_FILENAME = "model.xmi"; //$NON-NLS-1$
private static URI getModelLocation() {
final IPath path = DLTKLaunchingPlugin.getDefault().getStateLocation()
.append(MODEL_FILENAME);
return URI.createFileURI(path.toOSString());
}
private static boolean canLoad(URI location) {
if (location.isFile()) {
return new File(location.toFileString()).exists();
} else {
return true;
}
}
private Model loadModel() {
final URI location = getModelLocation();
final Resource resource = new XMIResourceImpl(location);
try {
if (canLoad(location)) {
resource.load(null);
}
} catch (IOException e) {
DLTKLaunchingPlugin.log(e);
}
return new Model(resource);
}
/**
* Returns the first content object of the specified type or
* <code>null</code>.
*
* @param interpreter
* @param clazz
* @return
*/
public EObject find(IInterpreterInstall interpreter,
Predicate<EObject> predicate) {
InterpreterInfo info = getModel().find(interpreter);
if (info != null) {
for (EObject object : info.getContents()) {
if (predicate.evaluate(object)) {
return object;
}
}
}
return null;
}
/**
* Replace the first content object of the specified type with the new
* value.
*
* @param interpreter
* @param clazz
* @param value
* new value or <code>null</code>
* @return
*/
public EObject save(IInterpreterInstall interpreter,
Predicate<EObject> predicate, EObject value) {
if (value != null) {
Assert.isLegal(predicate.evaluate(value));
}
// TODO synchronization
final Model model = loadModel();
final InterpreterInfo info = model.create(interpreter);
for (ListIterator<EObject> i = info.getContents().listIterator(); i
.hasNext();) {
EObject object = i.next();
if (predicate.evaluate(object)) {
if (value != null) {
i.set(value);
} else {
i.remove();
}
model.save();
return object;
}
}
if (value != null) {
info.getContents().add(value);
model.save();
}
return null;
}
}