/*******************************************************************************
* Copyright (c) 2010 Martin Schnabel <mb0@mb0.org>.
* 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
******************************************************************************/
package org.axdt.asdoc.access;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
import org.axdt.asdoc.model.AsdocRoot;
import org.axdt.asdoc.model.ParseLevel;
import org.axdt.asdoc.parser.AsdocParser;
import org.axdt.asdoc.ui.preferences.AsdocPreferences;
import org.axdt.asdoc.ui.preferences.DocTableFieldEditor.DocItem;
import org.axdt.avm.access.AvmAccess;
import org.axdt.core.model.AxdtProject;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.Display;
import org.eclipse.xtext.resource.XtextResourceSet;
import com.google.common.collect.Lists;
import com.google.inject.Singleton;
@Singleton
public class AsdocRootProvider extends AbstractAsdocRootProvider {
private final Logger logger = Logger.getLogger(AsdocRootProvider.class);
private static AsdocRootProvider instance;
public static AsdocRootProvider getInstance() {
if (instance == null)
instance = new AsdocRootProvider();
return instance;
}
private AsdocRootProvider() {
super();
}
protected URI createDocRootUri(String url) {
String docRootName = Integer.toHexString(url.hashCode()) + ".asdoc";
URI asdocCacheURI = CommonPlugin.resolve(URI
.createURI("platform:/meta/org.axdt.asdoc.runtime"));
return asdocCacheURI.appendSegment(docRootName);
}
public Iterable<AsdocRoot> getDocRoots(ResourceSet resourceSet) {
IProject project = null;
AxdtProject axdtProject = getAxdtProject(resourceSet);
if (axdtProject != null) {
project = axdtProject.getProject();
}
return initializeAsdocs(project);
}
public AxdtProject getAxdtProject(ResourceSet resourceSet) {
if (resourceSet instanceof XtextResourceSet) {
XtextResourceSet xtextResourceSet = (XtextResourceSet) resourceSet;
Object context = xtextResourceSet.getClasspathURIContext();
if (context instanceof AxdtProject)
return (AxdtProject) context;
}
return null;
}
public Iterable<AsdocRoot> initializeAsdocs(IProject project) {
AsdocPreferences asdocPreferences = AsdocPreferences.getInstance();
IPreferenceStore store = asdocPreferences.getProjectStore(project);
Object[] docItems = asdocPreferences.getDocItems(store);
return initializeAsdocs(docItems);
}
public Iterable<AsdocRoot> initializeAsdocs(Object[] docItems) {
// retrieve doc items
if (docItems == null || docItems.length == 0)
return Collections.emptyList();
List<DocItem> failedLoading = Lists.newArrayList();
List<AsdocRoot> initialized = Lists.newArrayList();
try {
for (Object value : docItems) {
if (value instanceof DocItem) {
DocItem item = (DocItem) value;
try {
AsdocRoot root = addRoot(item.name, item.url);
initialize(root, ParseLevel.GLOBAL);
if (item.asdocUrl != null) {
// XXX ugly hack should use a property or map
root.setAsdoc(item.asdocUrl);
}
initialized.add(root);
} catch (Exception e) {
item.status = new Status(IStatus.ERROR,
"org.axdt.asdoc.ui",
e.getClass().getSimpleName() + " "
+ e.getMessage(), e);
failedLoading.add(item);
}
}
}
if (!failedLoading.isEmpty()) {
final StringBuilder msgBuf = new StringBuilder(
"could not read asdoc at:\n");
IStatus firstStatus = null;
for (DocItem item : failedLoading) {
if (firstStatus == null)
firstStatus = item.status;
msgBuf.append("\t* " + item.url + "\n");
}
msgBuf.append("please check your preferences");
Display.getDefault().asyncExec(
new ErrorRunnable(firstStatus, msgBuf.toString()));
}
return initialized;
} catch (Exception e) {
logger.error("error loading asdoc", e);
}
return Collections.emptyList();
}
public void initialize(AsdocRoot root, ParseLevel level) throws Exception {
try {
AsdocParser parser = root.getParseType().getParser();
parser.parseDoc(root, level);
if (root.eResource().isModified())
saveRoot(root);
} catch (Exception e) {
logger.error("error parsing asdoc at " + root.getBaseUri(), e);
throw e;
}
}
public void saveRoot(AsdocRoot root) {
if (root == null)
return;
Resource index = root.eResource();
if (index == null)
return;
List<Resource> resources = index.getResourceSet().getResources();
for (Resource res : resources) {
try {
String scheme = res.getURI().scheme();
if (!AvmAccess.PROTOCOL.equals(scheme))
res.save(null);
} catch (IOException e) {
logger.error("error saving asdoc at " + index.getURI(), e);
}
}
}
public static class ErrorRunnable implements Runnable {
private final IStatus status;
private final String message;
public ErrorRunnable(IStatus status, String message) {
this.status = status;
this.message = message;
}
public void run() {
ErrorDialog.openError(Display.getCurrent().getActiveShell(),
"Error reading asdoc", message, status);
}
}
}