/*
* Copyright (c) 2010-2011 United States Government as represented by the Administrator for The National Aeronautics and Space Administration. All Rights Reserved.
*/
package net.certware.argument.cae.navigator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.certware.argument.arm.ArgumentElement;
import net.certware.argument.arm.ArgumentLink;
import net.certware.argument.arm.AssertedEvidence;
import net.certware.argument.arm.AssertedRelationship;
import net.certware.argument.arm.InformationElement;
import net.certware.argument.arm.ModelElement;
import net.certware.argument.arm.ReasoningElement;
import net.certware.argument.cae.Argument;
import net.certware.argument.cae.Assumption;
import net.certware.argument.cae.CaePackage;
import net.certware.argument.cae.Claim;
import net.certware.argument.cae.Context;
import net.certware.argument.cae.Evidence;
import net.certware.argument.cae.Justification;
import net.certware.argument.cae.util.CaeSwitch;
import net.certware.core.ICertWareConstants;
import org.eclipse.core.resources.IFile;
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.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
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.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.ui.progress.UIJob;
/**
* Provides model statistics as navigator content.
* @author mrb
* @since 1.0
*/
public class ContentProvider
implements ITreeContentProvider, IResourceChangeListener, IResourceDeltaVisitor, ICertWareConstants {
/** Field NO_CHILDREN */
private static final Object[] NO_CHILDREN = new Object[0];
/** cached model map for quick restore */
private final Map<IFile, TreeData[]> cachedModelMap = new HashMap<IFile, TreeData[]>();
/** structured viewer */
private StructuredViewer viewer;
/** claim count */
protected int claimCount = 0;
/** argument count */
protected int argumentCount = 0;
/** evidence count */
protected int evidenceCount = 0;
/** to be supported */
protected int toBeSupported = 0;
/**
* Constructor adds post change listener to workspace resource change events.
*/
public ContentProvider() {
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
}
/**
* Dispose of the cached model map and remove the resource change listener.
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
@Override
public void dispose() {
cachedModelMap.clear();
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
}
/**
* Handles input changed events.
* Clears the cached model map if necessary.
* @param aViewer structured viewer
* @param oldInput old input
* @param newInput new input
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(Viewer, Object, Object)
*/
@Override
public void inputChanged(Viewer aViewer, Object oldInput, Object newInput) {
if (oldInput != null && !oldInput.equals(newInput))
cachedModelMap.clear();
viewer = (StructuredViewer) aViewer;
}
/**
* A visitor for resource change delta traversal.
* @param delta resource change delta
* @return true if ROOT, PROJECT, or FOLDER, or false if FILE or unknown
* @throws CoreException for job problems refreshing the UI thread
* @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(IResourceDelta)
*/
@Override
public boolean visit(IResourceDelta delta) throws CoreException {
IResource source = delta.getResource();
switch (source.getType()) {
case IResource.ROOT:
case IResource.PROJECT:
case IResource.FOLDER:
return true;
case IResource.FILE:
final IFile file = (IFile) source;
if ( ICertWareConstants.CAE_EXTENSION.equals(file.getFileExtension())) {
updateModel(file);
new UIJob(Messages.ContentProvider_0) {
public IStatus runInUIThread(IProgressMonitor monitor) {
if (viewer != null ) // && ! viewer.getControl().isDisposed())
viewer.refresh(file);
return Status.OK_STATUS;
}
}.schedule();
}
return false;
}
return false;
}
/**
* Handles resource change events. Runs the delta accept to invoke visitor.
* Catches core exceptions and prints stack trace.
* @param event resource change event
* @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(IResourceChangeEvent)
*/
@Override
public void resourceChanged(IResourceChangeEvent event) {
IResourceDelta delta = event.getDelta();
try {
delta.accept(this);
} catch (CoreException e) {
e.printStackTrace();
}
}
/**
* Gets the elements of the model.
* @param inputElement input element
* @return result of calling getChildren() on the input element
* @see org.eclipse.jface.viewers.ITreeContentProvider#getElements(Object)
*/
@Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
/**
* Gets the children of the given element.
* @param parentElement parent element
* @return children of the given parent, or NO_CHILDREN
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(Object)
*/
@Override
public Object[] getChildren(Object parentElement) {
Object[] children = null;
if ( parentElement instanceof TreeData ) {
children = NO_CHILDREN;
} else if (parentElement instanceof IFile) {
IFile modelFile = (IFile)parentElement;
if ( ICertWareConstants.CAE_EXTENSION.equals( modelFile.getFileExtension() ) ) {
children = cachedModelMap.get(modelFile);
if ( children == null && updateModel(modelFile) != null ) {
children = cachedModelMap.get(modelFile);
}
}
}
return children != null ? children : NO_CHILDREN;
}
/**
* Gets the parent of the model element.
* @param element model element, expecting a TreeData object
* @return parent file of the tree data object, or null
* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(Object)
*/
@Override
public Object getParent(Object element) {
if ( element instanceof TreeData ) {
TreeData td = (TreeData)element;
return td.getIfile();
}
return null;
}
/**
* Whether the element has children.
* @param element model element, expecting a TreeData or IFile object
* @return false for TreeData or unknown objects; true if the IFile extension matches the CAE extension
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(Object)
*/
@Override
public boolean hasChildren(Object element) {
if ( element instanceof TreeData )
return false;
else if ( element instanceof IFile )
return ICertWareConstants.CAE_EXTENSION.equals(((IFile)element).getFileExtension());
return false;
}
/**
* Updates the navigator model from the project statistics in the resource model file.
* @param modelFile input file
* @return model resource processed from file
*/
private synchronized Resource updateModel(IFile modelFile) {
if ( ICertWareConstants.CAE_EXTENSION.equals(modelFile.getFileExtension())) {
if (modelFile.exists()) {
@SuppressWarnings("unused") // uses side effect
CaePackage caePackage = CaePackage.eINSTANCE;
ResourceSet resourceSet = new ResourceSetImpl();
Resource resource = resourceSet.getResource(
URI.createPlatformResourceURI(modelFile.getFullPath().toString(), true),
true);
if ( resource != null ) {
setClaimCount(0);
setArgumentCount(0);
setEvidenceCount(0);
setToBeSupported(0);
// visit the model, collect statistics
for ( Iterator<EObject> i = resource.getAllContents(); i.hasNext(); ) {
EObject eo = i.next();
visitor.doSwitch(eo);
} // iterator
TreeData td;
List<TreeData> treeNodes = new ArrayList<TreeData>();
td = new TreeData(modelFile,Messages.ContentProvider_1,getClaimCount(),TreeData.COUNT_TYPE_CLOSED);
treeNodes.add(td);
td = new TreeData(modelFile,Messages.ContentProvider_2,getArgumentCount(),TreeData.COUNT_TYPE_CLOSED);
treeNodes.add(td);
td = new TreeData(modelFile,Messages.ContentProvider_3,getEvidenceCount(),TreeData.COUNT_TYPE_CLOSED);
treeNodes.add(td);
if ( getToBeSupported() > 0 )
td = new TreeData(modelFile,Messages.ContentProvider_4,getToBeSupported(),TreeData.COUNT_TYPE_OPEN);
else
td = new TreeData(modelFile,Messages.ContentProvider_5,-1,TreeData.COUNT_TYPE_CLOSED);
treeNodes.add(td);
// populate array and model map
TreeData[] treeDataArray = treeNodes.toArray(new TreeData[treeNodes.size()]);
cachedModelMap.put(modelFile, treeDataArray);
return resource;
} // model not null
} // model file exists
} // file extension matches
cachedModelMap.remove(modelFile);
return null;
} // method
/**
* Gets the argument count.
* @return the argumentCount
*/
public int getArgumentCount() {
return argumentCount;
}
/**
* Sets the argument count.
* @param argumentCount the argument count to set
*/
public void setArgumentCount(int argumentCount) {
this.argumentCount = argumentCount;
}
/**
* Increments the argument count by one.
*/
public void incrementArgumentCount() {
this.argumentCount += 1;
}
/**
* Gets the claim count.
* @return the claim count
*/
public int getClaimCount() {
return claimCount;
}
/**
* Sets the claim count.
* @param claimCount the claim count
*/
public void setClaimCount(int claimCount) {
this.claimCount = claimCount;
}
/**
* Increments the claim count by one.
*/
public void incrementClaimCount() {
this.claimCount += 1;
}
/**
* Gets the evidence count.
* @return the evidence count
*/
public int getEvidenceCount() {
return evidenceCount;
}
/**
* Sets the evidence count.
* @param evidenceCount the evidence count
*/
public void setEvidenceCount(int evidenceCount) {
this.evidenceCount = evidenceCount;
}
/**
* Increment the evidence count by one.
*/
public void incrementEvidenceCount() {
this.evidenceCount += 1;
}
/**
* Gets the to be supported count.
* @return the to be supported count
*/
public int getToBeSupported() {
return toBeSupported;
}
/**
* Sets the to be supported count.
* @param toBeSupported the count value
*/
public void setToBeSupported(int toBeSupported) {
this.toBeSupported = toBeSupported;
}
/**
* Increments the to be supported count by one.
*/
public void incrementToBeSupported() {
this.toBeSupported += 1;
}
/**
* Visitor for iterating over the resource content.
*/
public CaeSwitch<Boolean> visitor = new CaeSwitch<Boolean> () {
/**
* Returns the result of interpreting the object as an instance of '<em>Claim</em>'.
* <!-- begin-user-doc -->
* Increments the claim node count.
* Increments the to-be-supported count if field is true
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Claim</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseClaim(Claim object) {
incrementClaimCount();
if ( object.isToBeSupported() )
incrementToBeSupported();
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Argument</em>'.
* <!-- begin-user-doc -->
* Increments the argument node count.
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Argument</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseArgument(Argument object) {
incrementArgumentCount();
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Evidence</em>'.
* <!-- begin-user-doc -->
* Increments the evidence node count.
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Evidence</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseEvidence(Evidence object) {
incrementEvidenceCount();
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Assumption</em>'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Assumption</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseAssumption(Assumption object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Context</em>'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Context</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseContext(Context object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Justification</em>'.
* <!-- begin-user-doc -->
* returning a non-null result will terminate the switch.
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Justification</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseJustification(Justification object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Model Element</em>'.
* <!-- begin-user-doc -->
* returning a non-null result will terminate the switch.
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Model Element</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseModelElement(ModelElement object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Argument Element</em>'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Argument Element</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseArgumentElement(ArgumentElement object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Reasoning Element</em>'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Reasoning Element</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseReasoningElement(ReasoningElement object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Claim</em>'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Claim</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseArm_Claim(net.certware.argument.arm.Claim object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Argument Link</em>'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Argument Link</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseArgumentLink(ArgumentLink object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Asserted Relationship</em>'.
* <!-- begin-user-doc -->
* returning a non-null result will terminate the switch.
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Asserted Relationship</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseAssertedRelationship(AssertedRelationship object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Asserted Evidence</em>'.
* <!-- begin-user-doc -->
* returning a non-null result will terminate the switch.
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Asserted Evidence</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseAssertedEvidence(AssertedEvidence object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>Information Element</em>'.
* <!-- begin-user-doc -->
* returning a non-null result will terminate the switch.
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>Information Element</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject)
*/
public Boolean caseInformationElement(InformationElement object) {
return Boolean.TRUE;
}
/**
* Returns the result of interpreting the object as an instance of '<em>EObject</em>'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @param object the target of the switch.
* @return the result of interpreting the object as an instance of '<em>EObject</em>'.
* @see #doSwitch(org.eclipse.emf.ecore.EObject)
*/
public Boolean defaultCase(EObject object) {
return Boolean.TRUE;
}
};
}