package au.com.langdale.cimtoole.project;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.QualifiedName;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import au.com.langdale.cimtoole.CIMToolPlugin;
import au.com.langdale.kena.Composition;
import au.com.langdale.kena.ModelFactory;
import au.com.langdale.kena.OntModel;
import au.com.langdale.kena.OntResource;
import au.com.langdale.kena.Property;
import au.com.langdale.kena.ResourceFactory;
import au.com.langdale.util.Jobs;
public class Settings extends Task {
public Settings() {
ResourcesPlugin.getWorkspace().addResourceChangeListener(
new ResourceListener(), IResourceChangeEvent.POST_CHANGE);
}
/**
* The session property used to cache models.
*/
public static final QualifiedName SETTINGS = new QualifiedName(CIMToolPlugin.PLUGIN_ID, "settings");
public static final QualifiedName[] MIGRATED_SYMBOLS = new QualifiedName[] {
PROFILE_PATH,
BASE_MODEL_PATH,
PROFILE_ENVELOPE,
SCHEMA_NAMESPACE,
PROFILE_NAMESPACE,
INSTANCE_NAMESPACE,
MERGED_SCHEMA_PATH
};
private OntModel migrateSettings(IProject project) throws CoreException {
Migrator visitor = new Migrator();
project.accept(visitor);
OntModel store = visitor.getStore();
project.setSessionProperty(SETTINGS, store);
System.out.println("Saving migrated settings for " + project.getName());
Jobs.runJob(saveSettings(project, store), project, "Migrating CIMTool settings");
return store;
}
private class Migrator implements IResourceVisitor {
private OntModel store = ModelFactory.createMem();
public OntModel getStore() {
return store;
}
public boolean visit(IResource resource) throws CoreException {
Map props = resource.getPersistentProperties();
if( ! props.isEmpty()) {
OntResource subject = createSubject(resource.getProjectRelativePath(), store);
for(int ix = 0; ix < MIGRATED_SYMBOLS.length; ix++) {
Property prop = createProperty(MIGRATED_SYMBOLS[ix]);
String value = (String) props.get(MIGRATED_SYMBOLS[ix]);
if( value != null )
subject.addProperty(prop, value);
}
}
return true;
}
}
public String getSetting(IResource resource, QualifiedName symbol) {
try {
return createSubject(resource.getProjectRelativePath(), getSettingsStore(resource.getProject())).getString(createProperty(symbol));
} catch (CoreException e) {
throw new RuntimeException(e);
}
}
private Property createProperty(QualifiedName symbol) {
String qualifier = symbol.getQualifier();
if( qualifier == null || CIMToolPlugin.PLUGIN_ID.equals(qualifier))
qualifier = CIMToolPlugin.SETTING_NS;
else
qualifier += "#";
return ResourceFactory.createProperty(qualifier + symbol.getLocalName());
}
private OntResource createSubject(IPath path, OntModel store) {
try {
return store.createResource(CIMToolPlugin.PROJECT_NS + new URI(null, path.toPortableString(), null).toASCIIString());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
private OntModel getSettingsStore(IProject project) throws CoreException {
OntModel store = (OntModel) project.getSessionProperty(SETTINGS);
if( store == null ) {
IFile settings = getSettings(project);
if( settings.exists()) {
System.out.println("Loading settings for " + project.getName());
store = Task.parse(settings);
project.setSessionProperty(SETTINGS, store);
}
else
store = migrateSettings(project);
}
return store;
}
private void replaceSettingsStore(IProject project, OntModel store) throws CoreException {
IFile settings = getSettings(project);
project.setSessionProperty(SETTINGS, store);
System.out.println("Saving modified settings for " + project.getName());
Jobs.runJob(saveSettings(project, store), settings, "Saving CIMTool settings");
}
public void putSetting(IResource resource, QualifiedName symbol, String value) {
try {
IProject project = resource.getProject();
OntModel store = getSettingsStore(project);
Property prop = createProperty(symbol);
IPath path = resource.getProjectRelativePath();
String extant = createSubject(path, store).getString(prop);
if( extant == null || ! extant.equals(value)) {
OntModel revised = Composition.copy(store);
createSubject(path, revised).setProperty(prop, value, null);
replaceSettingsStore(project, revised);
}
} catch (CoreException e) {
throw new RuntimeException(e);
}
}
private class ResourceListener implements IResourceChangeListener {
public void resourceChanged(IResourceChangeEvent event) {
if (event.getType() != IResourceChangeEvent.POST_CHANGE)
return;
DeltaVisitor visitor = new DeltaVisitor();
try {
event.getDelta().accept(visitor);
} catch (CoreException e) {
throw new RuntimeException(e);
}
Iterator it = visitor.getRevised().entrySet().iterator();
while( it.hasNext()) {
Entry entry = (Entry) it.next();
try {
replaceSettingsStore((IProject)entry.getKey(), (OntModel)entry.getValue());
} catch (CoreException e) {
throw new RuntimeException(e);
}
}
}
}
private class DeltaVisitor implements IResourceDeltaVisitor {
private Map revised = new HashMap();
public Map getRevised() {
return revised;
}
public boolean visit(IResourceDelta delta) throws CoreException {
if( delta.getResource().getType() == IResource.PROJECT
&& (delta.getKind() == IResourceDelta.ADDED
|| delta.getKind() == IResourceDelta.REMOVED))
return false;
if((delta.getFlags()&IResourceDelta.MOVED_TO) != 0)
copySettings(delta.getResource().getFullPath(), delta.getMovedToPath());
if((delta.getFlags()&IResourceDelta.MOVED_FROM) != 0)
copySettings(delta.getMovedFromPath(), delta.getResource().getFullPath());
if( delta.getKind() == IResourceDelta.REMOVED) {
removeSettings(delta.getResource().getFullPath());
}
return true;
}
private OntModel getRevised(IProject project) throws CoreException {
OntModel result = (OntModel) revised.get(project);
if( result == null ) {
result = Composition.copy(getSettingsStore(project));
revised.put(project, result);
}
return result;
}
private void removeSettings(IPath fullPath) throws CoreException {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(fullPath.segment(0));
OntModel store = getSettingsStore(project);
OntResource subject = createSubject(fullPath.removeFirstSegments(1), store);
if( store.contains(subject)) {
OntModel target = getRevised(project);
target.removeSubject(subject);
}
}
private void copySettings(IPath patha, IPath pathb) throws CoreException {
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IProject project = root.getProject(patha.segment(0));
OntModel store = getSettingsStore(project);
OntResource subject = createSubject(patha.removeFirstSegments(1), store);
Iterator it = store.getGraph().find(subject.asNode(), Node.ANY, Node.ANY);
if( it.hasNext()) {
IProject target_project = root.getProject(pathb.segment(0));
OntModel target_store = getRevised(target_project);
OntResource target_subject = createSubject(pathb.removeFirstSegments(1),target_store);
do {
Triple t = (Triple) it.next();
Property prop = ResourceFactory.createProperty(t.getPredicate());
target_subject.addProperty(prop, t.getObject());
} while( it.hasNext());
}
}
}
}