// Path: java/collabode/PadDocument.java
// public class PadDocument extends Document {
//     
//     public final PadDocumentOwner owner;
//     public final CollabDocument collab;
//     
//     PadDocument(PadDocumentOwner owner, CollabDocument collab) throws IOException {
//         super();
//         this.owner = owner;
//         this.collab = collab;
//     }
//     
//     /**
//      * Returns an informal name for this document's preferred content type.
//      */
//     public String getContentTypeName() {
//         try {
//             InputStream contents = new ByteArrayInputStream(get().getBytes());
//             IContentType type = collab.file.getProject().getContentTypeMatcher().findContentTypeFor(contents, collab.file.getName());
//             if (type != null) {
//                 return type.getId().replaceFirst(".*\\.", "");
//             }
//         } catch (IOException ioe) {
//             ioe.printStackTrace(); // XXX
//         } catch (CoreException ce) {
//             ce.printStackTrace(); // XXX
//         }
//         return "unknown";
//     }
//     
//     /*
//      * Synchronize methods that access the document's rep, to make the
//      * implementation a bit more threadsafe. Maybe. XXX
//      */
//     
//     @Override public synchronized char getChar(int pos) throws BadLocationException {
//         return super.getChar(pos);
//     }
//     
//     @Override public synchronized int getLength() {
//         return super.getLength();
//     }
//     
//     @Override public synchronized String get() {
//         return super.get();
//     }
//     
//     @Override public synchronized String get(int pos, int length) throws BadLocationException {
//         return super.get(pos, length);
//     }
//     
//     @Override public synchronized void replace(int pos, int length, String text, long modificationStamp) throws BadLocationException {
//         super.replace(pos, length, text, modificationStamp);
//     }
//     
//     @Override public synchronized void set(String text, long modificationStamp) {
//         super.set(text, modificationStamp);
//     }
//     
//     /**
//      * Returns true iff the edits are allowed.
//      * This implementation always permits edits. XXX should it?
//      */
//     public synchronized boolean isAllowed(ReplaceEdit[] edits, String[] permissions) {
//         return true;
//     }
//     
//     @Override public String toString() {
//         return getClass().getSimpleName() + "<" + owner.username + "," + collab.collaboration.id + "," + collab.file + ">";
//     }
// }


import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import scala.Function1;
import collabode.PadDocument;
     * Create a new document in the collaboration.
     * Creates a {@link CollabDocument} for the given file, and a {@link PadDocument} for the given user.
     * 
     * @param userId user ID
     * @param file file
     * @param rev current head revision number
     * @param setPadText function to set the pad text and obtain the new head revision number
     */
    public synchronized void createDocument(String userId, IFile file, int rev, Function1<String,Double> setPadText) throws IOException, CoreException {
        final String path = file.getFullPath().toString();
        if ( ! docsByPath.containsKey(path)) {
            docsByPath.putIfAbsent(path, new CollabDocument(this, file, setPadText));
            String project = file.getProject().getFullPath().toString();
            docsByProj.putIfAbsent(project, new CopyOnWriteArrayList<CollabDocument>());
            docsByProj.get(project).add(docsByPath.get(path));
        }
        docsByPath.get(path).createPadDocument(userId);
    }
    
    public CollabDocument get(IFile file) {
        return docsByPath.get(file.getFullPath().toString());
    }
    
    public Collection<CollabDocument> get(IProject project) {
        return docsByProj.get(project.getFullPath().toString());
    }
    
    /**
     * Notify listeners that edits were synchronized from pad to documents.
     */
// Path: java/collabode/PadDocument.java
// public class PadDocument extends Document {
//     
//     public final PadDocumentOwner owner;
//     public final CollabDocument collab;
//     
//     PadDocument(PadDocumentOwner owner, CollabDocument collab) throws IOException {
//         super();
//         this.owner = owner;
//         this.collab = collab;
//     }
//     
//     /**
//      * Returns an informal name for this document's preferred content type.
//      */
//     public String getContentTypeName() {
//         try {
//             InputStream contents = new ByteArrayInputStream(get().getBytes());
//             IContentType type = collab.file.getProject().getContentTypeMatcher().findContentTypeFor(contents, collab.file.getName());
//             if (type != null) {
//                 return type.getId().replaceFirst(".*\\.", "");
//             }
//         } catch (IOException ioe) {
//             ioe.printStackTrace(); // XXX
//         } catch (CoreException ce) {
//             ce.printStackTrace(); // XXX
//         }
//         return "unknown";
//     }
//     
//     /*
//      * Synchronize methods that access the document's rep, to make the
//      * implementation a bit more threadsafe. Maybe. XXX
//      */
//     
//     @Override public synchronized char getChar(int pos) throws BadLocationException {
//         return super.getChar(pos);
//     }
//     
//     @Override public synchronized int getLength() {
//         return super.getLength();
//     }
//     
//     @Override public synchronized String get() {
//         return super.get();
//     }
//     
//     @Override public synchronized String get(int pos, int length) throws BadLocationException {
//         return super.get(pos, length);
//     }
//     
//     @Override public synchronized void replace(int pos, int length, String text, long modificationStamp) throws BadLocationException {
//         super.replace(pos, length, text, modificationStamp);
//     }
//     
//     @Override public synchronized void set(String text, long modificationStamp) {
//         super.set(text, modificationStamp);
//     }
//     
//     /**
//      * Returns true iff the edits are allowed.
//      * This implementation always permits edits. XXX should it?
//      */
//     public synchronized boolean isAllowed(ReplaceEdit[] edits, String[] permissions) {
//         return true;
//     }
//     
//     @Override public String toString() {
//         return getClass().getSimpleName() + "<" + owner.username + "," + collab.collaboration.id + "," + collab.file + ">";
//     }
// }


// Path: java/collabode/collab/Collab.java
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import scala.Function1;
import collabode.PadDocument;

     * Create a new document in the collaboration.
     * Creates a {@link CollabDocument} for the given file, and a {@link PadDocument} for the given user.
     * 
     * @param userId user ID
     * @param file file
     * @param rev current head revision number
     * @param setPadText function to set the pad text and obtain the new head revision number
     */
    public synchronized void createDocument(String userId, IFile file, int rev, Function1<String,Double> setPadText) throws IOException, CoreException {
        final String path = file.getFullPath().toString();
        if ( ! docsByPath.containsKey(path)) {
            docsByPath.putIfAbsent(path, new CollabDocument(this, file, setPadText));
            String project = file.getProject().getFullPath().toString();
            docsByProj.putIfAbsent(project, new CopyOnWriteArrayList<CollabDocument>());
            docsByProj.get(project).add(docsByPath.get(path));
        }
        docsByPath.get(path).createPadDocument(userId);
    }
    
    public CollabDocument get(IFile file) {
        return docsByPath.get(file.getFullPath().toString());
    }
    
    public Collection<CollabDocument> get(IProject project) {
        return docsByProj.get(project.getFullPath().toString());
    }
    
    /**
     * Notify listeners that edits were synchronized from pad to documents.
     */
    public void updated(PadDocument doc) {