alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.cvsclient.commands.diff;

import javax.swing.JComponent;
import java.awt.Component;

import org.openide.util.NbBundle;
import org.netbeans.modules.javacvs.commands.CvsDiff;


import org.netbeans.api.diff.*;
import org.netbeans.spi.diff.*;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import org.netbeans.lib.cvsclient.command.diff.DiffCommand;
import org.netbeans.lib.cvsclient.command.diff.DiffInformation;
import org.netbeans.lib.cvsclient.command.diff.DiffInformation.DiffChange;
import org.netbeans.lib.cvsclient.command.PipedFileInformation;
import org.openide.filesystems.FileUtil;
import org.openide.util.*;
import org.openide.*;
import org.openide.windows.*;

import org.netbeans.modules.cvsclient.*;
import org.netbeans.modules.cvsclient.commands.*;
import org.netbeans.modules.javacvs.commands.*;
import java.io.*;
import javax.swing.SwingUtilities;
import org.netbeans.modules.vcscore.util.Debug;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.windows.WindowManager;

/**
 *
 * @author  mkleint
 * @version
 */
public class DiffDisplayer {
    private Debug E=new Debug("DiffDisplayer", true); // NOI18N
    private Debug D=E;
    
    DiffCommand command;
    FileSystemCommand fsCommand;
    DiffInformation diffInfo;

    private Difference[] differences;
    
    boolean finishedOk;
    ArrayList resultList;
    private File startFile;
    private StringBuffer bufLeft;
    private StringBuffer bufRight;
    private int fileLineCount;
    private int leftLineCount;
    private int rightLineCount;
    private File file1;
    private File file2;
    
    /** Creates new Status */
    public DiffDisplayer(DiffCommand diffComm) {
        D.deb("Constructor"); //NOI18N
        command = diffComm;
    }
    
    
    private PipedFileInformation findUpdInfo(LinkedList list, String name) {
        Iterator it = list.iterator();
        while (it.hasNext()) {
            PipedFileInformation info = (PipedFileInformation)it.next();
            if (info.getRepositoryFileName().equals(name)) {
                return info;
            }
        }
        return null;
    }
    
    /** Does the actual display - docking into the javacvs Mode, 
 *  displaying as single Dialog.. whatever.
 */
    public void displayOutputData() {
        if (SwingUtilities.isEventDispatchThread()) {
            _displayOutputData();
        } else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    _displayOutputData();
                }
            });
        }
    }
    
    private void _displayOutputData() {
        DiffVisualizer visual = (DiffVisualizer)Lookup.getDefault().lookup(DiffVisualizer.class);
        if (differences != null && visual != null) {
            try {
                String workingFile = NbBundle.getBundle(DiffDisplayer.class).getString("LBL_WorkingFile"); //NOI18N
                String rightTit = (diffInfo.getRightRevision() != null ? diffInfo.getRightRevision() : workingFile);
                String leftTit = (diffInfo.getLeftRevision() != null ? diffInfo.getLeftRevision() : workingFile);
                TopComponent myTC = new TopComponent();
                myTC.putClientProperty("PersistenceType", "Never"); //NOI18N
                myTC.setLayout(new BorderLayout());
                Reader reader1 = new BufferedReader(new FileReader(file1));
                Reader reader2 = new BufferedReader(new FileReader(file2));
                
                Component comp = visual.createView(differences, leftTit, leftTit, reader1, 
                                                        rightTit, rightTit, reader2, 
                                                        getMIMEType(diffInfo));
                myTC.add(comp, BorderLayout.CENTER);
                Mode editorMode = WindowManager.getDefault().getCurrentWorkspace().findMode("editor");
                if(editorMode != null)
                    editorMode.dockInto(myTC);
                javax.accessibility.AccessibleContext context = myTC.getAccessibleContext();
                javax.accessibility.AccessibleContext compContext = comp.getAccessibleContext();
                context.setAccessibleDescription(compContext.getAccessibleDescription());
                myTC.setName(getName() + " " + diffInfo.getFile().getName());
                myTC.open();                
            } catch (IOException exc) {
                Thread.dumpStack();
            }
        }
    }
    
    protected String getName() {
        return NbBundle.getBundle(CvsDiff.class).getString("CvsDiff.name"); //NOI18N
    }
    
    public void setData(DiffInformation info, DiffCommand command, PipedFileInformation updInfo) {
        D.deb("setData() beginning"); //NOI18N
        File startFile = info.getFile();
        if (updInfo != null) {
            if (!startFile.exists()) {
                startFile = updInfo.getTempFile();
            }
            if (command.getBeforeDate1() != null || command.getRevision2() != null) {
                startFile = updInfo.getTempFile();
            }
        }
        if (startFile == null) return;
        diffInfo = (DiffInformation)info;
        processDocuments(diffInfo, startFile);
        file1 = saveToFile(bufLeft);
        D.deb("file left=" + file1.getAbsolutePath()); //NOI18N
        file2 = saveToFile(bufRight);
        D.deb("file right=" + file2.getAbsolutePath()); //NOI18N
        DiffInformation.DiffChange change = diffInfo.getFirstChange();
        java.util.List diffList = new LinkedList();
        while (change != null) {
            int type = 0;
            if (change.getType() == DiffInformation.DiffChange.ADD) {
                type = Difference.ADD;
            } 
            else if (change.getType() == DiffInformation.DiffChange.CHANGE) {
                type = Difference.CHANGE;
            }
            else if(change.getType() == DiffInformation.DiffChange.DELETE) {
                type = Difference.DELETE;
            } else {
                change = diffInfo.getNextChange();
            }
            diffList.add(new Difference(type, 
                                change.getLeftMin(), change.getLeftMax(),
                                change.getRightMin(), change.getRightMax()));
            change = diffInfo.getNextChange();
        }
        if (diffList.size() > 0) {
            differences = new Difference[diffList.size()];
            differences = (Difference[])diffList.toArray(differences);
        }
    }
    
    private String getMIMEType(DiffInformation info) {
        File file = info.getFile();
        if (file == null) return "text/plain"; //NOI18N
        String mime;
        FileObject[] fos = FileUtil.fromFile(file);
        if (fos.length > 0) {
            mime = FileUtil.getMIMEType(fos[0]);
        } else {
            String ext = FileUtil.getExtension(file.getName());
            mime = FileUtil.getMIMEType(ext);
        }
        if (mime == null) {
            mime = "text/plain"; //NOI18N
        }
        return mime;
    }

    
    private File saveToFile(StringBuffer buff) {
        // TEMPORARY, better solution is to write to the file instantly without the write to StringBuffer
        String TMP_ROOT=System.getProperty("netbeans.user")+File.separator+ //NOI18N
                 "system"+File.separator+"javacvs"+File.separator+"tmp"; //NOI18N
        File tmpDir = new File(TMP_ROOT);
        if (!tmpDir.exists()) {
            tmpDir.mkdirs();
        }
        long tmpId;
        do {
            tmpId = 10000 * (1 + Math.round (Math.random () * 8)) + Math.round (Math.random () * 1000);
        } while (new File(TMP_ROOT+File.separator+"tmp"+tmpId).exists()); // NOI18N
        String tempFileName = TMP_ROOT+File.separator+"tmp"+tmpId; // NOI18N
        File tempFile = new File(tempFileName);
        try {
        PrintWriter bw = new PrintWriter(new FileOutputStream(tempFile),true);
        bw.print(buff);
        bw.close();
        } catch (IOException exc) {
//            E.err("error writing temp file while doing diff");
        }
        return tempFile;
    }
   
    
    private void processDocuments(DiffInformation diffInfo, File startFile) {
        BufferedReader buf = null;
        leftLineCount = 0;
        rightLineCount = 0;
        try {
            buf = new BufferedReader(new FileReader(startFile));
        } catch (FileNotFoundException exc) {
//            E.err("file" + startFile.getAbsolutePath() + " was not found!");
            return;
        }
        bufLeft = new StringBuffer();
        bufRight = new StringBuffer();
        try {
            String line;
            fileLineCount = 0;
            int gap;
            DiffInformation.DiffChange change = diffInfo.getFirstChange();
            while (true) {
                if (change != null) {
                    boolean isDelete = change.getType() == DiffInformation.DiffChange.DELETE;
//                    int start = change.getMainBeginning();
                    int start = (isDelete ? change.getMainBeginning() : change.getMainBeginning() - 1);
                    if (change.getMainBeginning() >= fileLineCount) {
                        gap = fillFromFile(start, buf);
                        D.deb("filled = " + gap); //NOI18N
                    }
                    if (change.getType() == DiffInformation.DiffChange.ADD) {
                        D.deb("we got ADD change here!"); //NOI18N
                        gap = parseAddChange(change, true);
                        skipGap(gap, buf);
                    }
                    if (change.getType() == DiffInformation.DiffChange.DELETE) {
                        D.deb("we got DELETE change here!"); //NOI18N
                        gap = parseDeleteChange(change, true);
                    }
                    if (change.getType() == DiffInformation.DiffChange.CHANGE) {
                        D.deb("we got CHANGE change here!"); //NOI18N
                        gap = parseChangedChange(change);
                        skipGap(gap, buf);
                    }
                    change = diffInfo.getNextChange();
                } else {
                    gap = fillFromFile(-1, buf);
                    // read till end of file
                    break;
                }
            }
            
        } catch (IOException ioExc) {
            ErrorManager.getDefault().notify(ioExc);
        } finally {
            try {
                buf.close();
            } catch (IOException ioex) {
                ErrorManager.getDefault().notify(ioex);
            }
        }
        
    }
    
    private void skipGap(int gap, BufferedReader buf) throws IOException {
        for (int ind = 0; ind < gap; ind++) {
            String line = buf.readLine();
            fileLineCount = fileLineCount + 1;
            D.deb("skipped one line=" + line); //NOI18N
        }
        
    }
    
    private int fillFromFile(int start, BufferedReader buf)
    throws IOException {
        D.deb("fillingGap..."); //NOI18N
        int readCount = 0;
        int max = start;
        // if max is -1, do read till end of file.
        while (fileLineCount < max || max == -1) {
                String line = buf.readLine();
                if (line == null) break;
                fileLineCount = fileLineCount + 1;
                readCount = readCount + 1;
                D.deb("reading linenum=" + readCount + "  line=" + line); //NOI18N
                leftLineCount = leftLineCount + 1;
                bufLeft.append(line + "\n"); //NOI18N
                rightLineCount = rightLineCount + 1;
                bufRight.append(line + "\n"); //NOI18N
        }
        return readCount;
    }
    
    private int parseAddChange(DiffChange change, boolean add) {
        int ind;
        for (ind = change.getRightMin(); ind <= change.getRightMax(); ind++) {
            bufRight.append(change.getLine(ind, false) + "\n"); //NOI18N
            rightLineCount = rightLineCount + 1;
            D.deb("adding to main=" + change.getLine(ind, false)); //NOI18N
        }
        int gap = ind - change.getRightMin();
        D.deb("final ADDED gap =" + gap); //NOI18N
        return gap;
    }
    
    private int parseDeleteChange(DiffChange change, boolean delete) {
        int ind;
        for (ind = change.getLeftMin(); ind <= change.getLeftMax(); ind++) {
            leftLineCount = leftLineCount + 1;
            bufLeft.append(change.getLine(ind, true) + "\n"); //NOI18N
            D.deb("addding to diff=" + change.getLine(ind, true)); //NOI18N
        }
        int gap = ind - change.getLeftMin();
        D.deb("final DELETE gap =" + gap); //NOI18N
        return gap;
    }
    
    private int parseChangedChange(DiffChange change) {
        int gap = parseAddChange(change, false);
        int toReturn = gap;
        int gap2 = parseDeleteChange(change, false);
        return toReturn;
    }
 
    // -- persistent stuff follows.
    
    public void setCommand(DiffCommand comm) {
      command = comm;
    }
    
    public void setFileSystemCommand(FileSystemCommand fsCom) {
        fsCommand = fsCom;
    }
    
  public File getFileDisplayed() {
      if (diffInfo == null) return null;
      return diffInfo.getFile();
  }
   
  public Object getComparisonData() {
      return diffInfo;
  }
   
  public JComponent getComponent() {
      return null;
  }

   // --------------------------------------------
  // persistantDisplayer stuff..
  // --------------------------------------------
  
  public boolean equalDisplayedData(File file, Class type, Object comparisonData) {
      if (!getClass().equals(type)) return false;
      if (diffInfo == null || diffInfo.getFile() == null
                || !diffInfo.getFile().equals(file)) {
          return false;
      }
      return true;
  }

  public FileSystemCommand getFileSystemCommand() {
      return fsCommand;
  }
  
  public String getCommandSwitches() {
      return command.getCVSArguments();
  }
  
    
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.