uidesigner/com.nokia.sdt.sourcegen/src/com/nokia/sdt/sourcegen/core/SourceGenContext.java
changeset 0 fb279309251b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uidesigner/com.nokia.sdt.sourcegen/src/com/nokia/sdt/sourcegen/core/SourceGenContext.java	Fri Apr 03 23:33:03 2009 +0100
@@ -0,0 +1,418 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+package com.nokia.sdt.sourcegen.core;
+
+import com.nokia.cpp.internal.api.utils.core.Check;
+import com.nokia.cpp.internal.api.utils.core.FileUtils;
+import com.nokia.cpp.internal.api.utils.core.IDisposable;
+import com.nokia.cpp.internal.api.utils.core.Logging;
+import com.nokia.cpp.internal.api.utils.core.Message;
+import com.nokia.cpp.internal.api.utils.core.TrackedResource;
+import com.nokia.sdt.datamodel.IDesignerDataModel;
+import com.nokia.sdt.datamodel.adapter.IComponentInstance;
+import com.nokia.sdt.datamodel.util.MessageLocators;
+import com.nokia.sdt.sourcegen.*;
+import com.nokia.sdt.sourcegen.contributions.ComponentSourceGenGatherer;
+import com.nokia.sdt.sourcegen.contributions.IContributionGatherer;
+import com.nokia.sdt.sourcegen.contributions.domains.cpp.*;
+import com.nokia.sdt.utils.*;
+import com.nokia.sdt.workspace.IProjectContext;
+import com.nokia.sdt.workspace.WorkspaceContext;
+
+import org.eclipse.cdt.core.dom.ICodeReaderFactory;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+
+import java.io.*;
+import java.text.MessageFormat;
+import java.util.*;
+
+/**
+ * This context holds the modified file state while
+ * generating C/C++ source.
+ * 
+ *
+ */
+public class SourceGenContext implements IDisposable, ISourceManipulatorProvider {
+    /** Moveable reference to the project */
+    TrackedResource trackedProject;
+    /** Base directory: set to non-null for testing outside project,
+     * otherwise the project's base is used */
+    private File baseDir;
+
+    /** Map of IPath to ISourceManipulator */
+    private Map pathsToSources;
+    
+    /** Set of IPath of sources created without ISourceManipulator */
+    private Set<IPath> pathsToExtraFiles;
+    
+    //private WorkInProgressCodeReaderFactory codeReaderFactory;
+    private ICodeReaderFactory codeReaderFactory;
+	ISourceGenProvider provider;
+    
+	IContributionGatherer gatherer;
+	
+    /**
+     * 
+     */
+    public SourceGenContext(ISourceGenProvider provider) {
+    	this.provider = provider;
+        this.pathsToSources = new HashMap();
+        pathsToExtraFiles = new HashSet<IPath>();
+        
+        //codeReaderFactory = new MemoryBufferCodeReaderFactory(this);
+        codeReaderFactory = new WorkInProgressCodeReaderFactory();
+        this.gatherer = new ComponentSourceGenGatherer();
+    }
+    
+    /**
+     * NOTE: This form is only to be used by CppDomain
+     * @param project
+     */
+    public SourceGenContext(IProject project) {
+    	this((ISourceGenProvider)null);
+    	setProject(project);
+    }
+
+	/* (non-Javadoc)
+     * @see com.nokia.sdt.utils.IDisposable#dispose()
+     */
+    public void dispose() {
+    }
+
+    public IContributionGatherer getContributionGatherer() {
+    	return gatherer;
+    }
+    
+    public void setProject(IProject project) {
+        if (trackedProject != null) {
+            trackedProject.dispose();
+            trackedProject = null;
+        }
+        if (project != null) {
+        	trackedProject = new TrackedResource(project);
+        	setBaseDir(null);
+        }
+    }
+    
+    public IProject getProject() {
+        if (trackedProject == null)
+            return null;
+        return trackedProject.getProject();
+    }
+    
+    /**
+     * Revert changed sources
+     */
+    public void revert() {
+       	for (Iterator iter = pathsToSources.values().iterator(); iter.hasNext();) {
+			ISourceManipulator manip = (ISourceManipulator) iter.next();
+			try {
+				if (manip.changed())
+					manip.revert();
+			} catch (CoreException e) {
+				SourceGenPlugin.getDefault().log(e);
+			}
+		}
+    }
+    
+    /**
+     * Reset the context for a new round of generation
+     * <p>
+     * Clears known source files
+     */
+    public void reset() {
+    	for (Iterator iter = pathsToSources.values().iterator(); iter.hasNext();) {
+			ISourceManipulator manip = (ISourceManipulator) iter.next();
+			try {
+				if (manip.changed())
+					manip.unload();
+			} catch (CoreException e) {
+				SourceGenPlugin.getDefault().log(e);
+			}
+		}
+        pathsToSources.clear();
+        gatherer.getDeadLocations().clear();
+        pathsToExtraFiles.clear();
+    }
+
+    /* copied from Eclipse and fixed to work... */
+    /*
+    private int matchingFirstSegments(IPath my, IPath anotherPath) {
+        int anotherPathLen = anotherPath.segmentCount();
+        int max = Math.min(my.segmentCount(), anotherPathLen);
+        int count = 0;
+        for (int i = 0; i < max; i++) {
+            if (!my.segment(i).equalsIgnoreCase(anotherPath.segment(i))) {
+                return count;
+            }
+            count++;
+        }
+        return count;
+    }*/
+
+    /**
+     * Map the given file to a path in the current workspace.
+     * @param fullPath
+     * @return the IFile for the file
+     */
+    private IFile fullPathToWorkspace(String fullPath) {
+    	return FileUtils.convertFileToIFile(new File(fullPath));
+    	/*
+        if (getProject() == null)
+            return null;
+        
+        IPath path = new Path(fullPath);
+        IPath rootPath;
+        rootPath = trackedProject.getProject().getLocation();
+        
+        // this is BUGGY!  Case sensitive for some dumb reason
+        //int match = path.matchingFirstSegments(rootPath);
+        int match = matchingFirstSegments(path, rootPath);
+        
+        if (match == 0)
+            return null;
+        
+        path = path.removeFirstSegments(match);
+        IFile wsFile = FileUtils.convertFileToIFile(getEffectiveBaseDir()) 
+        	getProject().getFile(path);
+        return wsFile;
+        */
+    }
+
+    /**
+     * Get a manipulator allowing modification of source file
+     * @param path project-relative path
+     */
+    public ISourceManipulator getSourceManipulator(IPath path) {
+        if (trackedProject != null) {
+            if (trackedProject.getProject().getFile(path) == null)
+                return null;
+        }
+        
+        ISourceManipulator sfi = (ISourceManipulator) pathsToSources.get(path); 
+        if (sfi == null) {
+            if (trackedProject != null)
+                sfi = new WorkspaceSourceManipulator(this, path);
+            else
+                sfi = new StandaloneSourceManipulator(this, path);
+            //System.out.println("working with file: " + path);
+            pathsToSources.put(path, sfi);
+        }
+        return sfi;
+    }
+    
+    public ISourceManipulator getSourceManipulator(String fullPath) {
+        if (getProject() != null) {
+            IFile workspaceFile = fullPathToWorkspace(fullPath);
+            if (workspaceFile != null)
+                return getSourceManipulator(workspaceFile.getProjectRelativePath());
+            else
+                return null; //return getSourceManipulator(new Path(fullPath));
+        }
+        else if (baseDir != null)
+            return getSourceManipulator(new Path(fullPath.substring(baseDir.getAbsolutePath().length()+1))); 
+        else
+            return null;
+    }
+
+    /**
+     * @param monitor 
+     * 
+     */
+    public void saveGeneratedSources(IProgressMonitor monitor) throws CoreException {
+        monitor.beginTask(Messages.getString("SourceGenSession.SavingSourceFiles"), //$NON-NLS-1$ 
+                pathsToSources.values().size());
+        Check.checkState(provider != null);
+        try {
+        	writeFiles(provider.getFileTracker(), monitor);
+        } finally {
+            monitor.done();
+        }
+    }
+
+    public List<IPath> getGeneratedSources() {
+    	List<IPath> files = new ArrayList<IPath>();
+    	for (Iterator iter = pathsToSources.values().iterator(); iter.hasNext();) {
+			ISourceManipulator manip = (ISourceManipulator) iter.next();
+			files.add(manip.getPath());
+		}
+    	files.addAll(pathsToExtraFiles);
+    	return files;
+    }
+    
+    /**
+	 *	Write the modified files to disk 
+     * @param fileSaver 
+	 */
+	private void writeFiles(IFileSaver fileSaver, IProgressMonitor monitor) throws CoreException {
+        // write all the one-way files
+        for (Iterator iter = pathsToSources.values().iterator(); iter.hasNext();) {
+            ISourceManipulator sfi = (ISourceManipulator) iter.next();
+            if (sfi.changed()) {
+            	//System.out.println("saving new version of " + sfi.getPath());
+            	sfi.save(fileSaver, new SubProgressMonitor(monitor, 1));
+            } else {
+            	sfi.unload();
+                monitor.worked(1);
+            }
+        }
+	}
+
+	/**
+     * Find or create the file at the given path in the project
+     * @param path project-relative path
+     * @return true: created file
+     * @throws CoreException
+     */
+    public boolean resolveOrCreateFile(IPath path) throws CoreException {
+        resolveOrCreatePath(path.removeLastSegments(1));
+
+        if (getProject() != null) {
+            IFile file = getProject().getFile(path);
+            if (file.exists())
+                return false;
+            
+            file.create(new ByteArrayInputStream(new byte[0]),
+            		false, new NullProgressMonitor());
+            return true;
+        } else if (baseDir != null ){
+            File nf = new File(baseDir, path.toString());
+
+            try {
+            	return nf.createNewFile();
+            } catch (IOException e) {
+                throw new CoreException(Logging.newStatus(SourceGenPlugin.getDefault(), 
+                        e));
+            }
+        } else
+            return false;
+    }
+
+	/**
+     * Set contents of the given file, which must exist already.
+     * @param path project-relative path
+     * @param is stream to initial contents
+     * @throws CoreException
+     */
+    public void setFileContents(IPath path, InputStream is) throws CoreException {
+        if (getProject() != null) {
+            IFile file = getProject().getFile(path);
+            file.setContents(is, false, true, new NullProgressMonitor());
+        } else if (baseDir != null ){
+            File nf = new File(baseDir, path.toString());
+            
+            try {
+                FileOutputStream fos = new FileOutputStream(nf);
+                byte[] buffer = new byte[4096];
+                int len;
+                while ((len = is.read(buffer)) > 0)
+                	fos.write(buffer, 0, len);
+                fos.close();
+            } catch (IOException e) {
+                throw new CoreException(Logging.newStatus(SourceGenPlugin.getDefault(), 
+                        e));
+            }
+        }
+    }
+
+    /**
+     * Find or create the directory at the given path in the project
+     * @param path
+     */
+    protected void resolveOrCreatePath(IPath path) throws CoreException {
+        if (getProject() != null) {
+            
+            IFolder folder = getProject().getFolder(path);
+            if (folder.exists())
+                return;
+            
+            folder.create(false, true, new NullProgressMonitor());
+        } else if (baseDir != null) {
+            File nf = new File(baseDir, path.toString());
+            if (nf.exists())
+                return;
+            
+            nf.mkdirs();
+        }
+    }
+
+    /**
+     * Set the base directory for writing files
+     * @param baseDir if null, use the project base, else
+     * use this directory 
+     */
+    public void setBaseDir(File baseDir) {
+        if (baseDir != null) {
+            this.baseDir = baseDir;
+            this.baseDir.mkdirs();
+        } else
+            this.baseDir = null;
+        
+    }
+
+    /**
+     * Get the effective base directory (either the overridden
+     * one or one based on the project)
+     * @return directory
+     */
+    public File getEffectiveBaseDir() {
+        if (baseDir != null)
+            return baseDir;
+        IProject project = getProject();
+        if (project != null && project.getLocation() != null)
+            return project.getLocation().toFile();
+        else
+            return null;
+    }
+
+    /**
+     */
+    public ICodeReaderFactory getCodeReaderFactory() {
+        return codeReaderFactory;
+    }
+
+ 
+    public static void emit(IComponentInstance instance, int severity, String msgKey, Object[] args) {
+		MessageReporting.emitMessage(
+				new Message(
+						severity,
+						MessageLocators.getComponentOrInstanceLocation(instance),
+						msgKey,
+						MessageFormat.format(Messages.getString(msgKey), args)));
+	}
+
+    public IProjectContext getProjectContext(IDesignerDataModel model) {
+    	IProject project = getProject();
+		if (project != null) {
+			return WorkspaceContext.getContext().getContextForProject(project);
+		}
+		return null;
+    }
+    
+    public ISourceFormatting getSourceFormatting() {
+    	if (provider.getSourceFormatter() != null)
+    		return provider.getSourceFormatter().getSourceFormatting();
+    	else
+    		return null;
+    }
+   
+    public void addExtraSourcePath(IPath extraSourcePath) {
+    	pathsToExtraFiles.add(extraSourcePath);
+    }
+}