All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.lib.cvsclient.command.log.LogMessageParser Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition javacvs-src library. This is release number 1 of trunk branch 142.

The newest version!
/*
 *                 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-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.lib.cvsclient.command.log;

import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.text.SyncDateFormat;
import org.jetbrains.annotations.NonNls;
import org.netbeans.lib.cvsclient.JavaCvsSrcBundle;
import org.netbeans.lib.cvsclient.command.AbstractMessageParser;
import org.netbeans.lib.cvsclient.command.KeywordSubstitution;
import org.netbeans.lib.cvsclient.event.IEventSender;
import org.netbeans.lib.cvsclient.file.ICvsFileSystem;
import org.netbeans.lib.cvsclient.util.BugLog;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author Thomas Singer
 */
final public class LogMessageParser extends AbstractMessageParser {

  // Constants ==============================================================


  @NonNls private static final String RCS_FILE = "RCS file: ";
  @NonNls private static final String WORKING_FILE = "Working file: ";
  @NonNls private static final String HEAD = "head: ";
  @NonNls private static final String BRANCH = "branch:";
  @NonNls private static final String LOCKS = "locks: ";
  @NonNls private static final String ACCESS_LIST = "access list:";
  @NonNls private static final String SYMBOLIC_NAMES = "symbolic names:";
  @NonNls private static final String KEYWORD_SUBST = "keyword substitution: ";
  @NonNls private static final String TOTAL_REVISIONS = "total revisions: ";
  @NonNls private static final String SELECTED_REVISIONS = ";\tselected revisions: ";
  @NonNls private static final String DESCRIPTION = "description:";
  @NonNls private static final String REVISION = "revision ";
  @NonNls private static final String DATE = "date: ";
  @NonNls private static final String BRANCHES = "branches: ";
  @NonNls private static final String AUTHOR = "  author: ";
  @NonNls private static final String STATE = "  state: ";
  @NonNls private static final String LINES = "  lines: ";
  @NonNls private static final String SPLITTER = "----------------------------";
  @NonNls private static final String FINAL_SPLIT = "=============";
  @NonNls private static final String FINAL_SPLIT_WITH_TAB = "\t=============";

  private static final SyncDateFormat[] EXPECTED_DATE_FORMATS = new SyncDateFormat[2];
  @NonNls private static final String NO_FILE_MESSAGE = "no file";

  static {
    initDateFormats();
  }

  @SuppressWarnings({"HardCodedStringLiteral"})
  private static void initDateFormats() {
    EXPECTED_DATE_FORMATS[0] = new SyncDateFormat(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US));
    EXPECTED_DATE_FORMATS[0].setTimeZone(TimeZone.getTimeZone("GMT"));

    EXPECTED_DATE_FORMATS[1] = new SyncDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US));
    EXPECTED_DATE_FORMATS[1].setTimeZone(TimeZone.getTimeZone("GMT"));
  }

  // Fields =================================================================

  private final IEventSender eventSender;
  private final ICvsFileSystem cvsFileSystem;
  private LogInformation logInfo;
  private Revision revision;
  private boolean addingSymNames;
  private boolean addingDescription;
  private boolean processingRevision;
  private List logMessageBuffer;
  private final Pattern myRevisionPattern;

  // Setup ==================================================================

  public LogMessageParser(IEventSender eventSender, ICvsFileSystem cvsFileSystem) {
    BugLog.getInstance().assertNotNull(eventSender);
    BugLog.getInstance().assertNotNull(cvsFileSystem);

    this.cvsFileSystem = cvsFileSystem;
    this.eventSender = eventSender;

    myRevisionPattern = Pattern.compile("revision \\d+(\\.\\d+){1,3}.*");
  }

  // Implemented ============================================================

  protected void outputDone() {
    if (addingDescription) {
      addingDescription = false;
    }
    if (processingRevision) {
      revision.setMessage(getMessageFromBuffer());
      logInfo.addRevision(revision);
      revision = null;
      processingRevision = false;

    }
    if (logInfo != null) {
      eventSender.notifyFileInfoListeners(logInfo);
      logInfo = null;
    }
    logMessageBuffer = null;
  }

  private String getMessageFromBuffer() {
    if (logMessageBuffer.size() > 0 && lastLogMessageIsFinalSeparator(logMessageBuffer.get(logMessageBuffer.size()-1))) {
      logMessageBuffer.remove(logMessageBuffer.size()-1);
    }
    else if (logMessageBuffer.size() > 1 &&
      lastLogMessageIsFinalSeparator(logMessageBuffer.get(logMessageBuffer.size()-2)) &&
      logMessageBuffer.get(logMessageBuffer.size()-1).length() == 0) {
      logMessageBuffer.remove(logMessageBuffer.size()-2);
      logMessageBuffer.remove(logMessageBuffer.size()-1);
    }

    if (logMessageBuffer.size() > 0) {
      return StringUtil.join(logMessageBuffer, "\n") + "\n";
    }
    return "";
  }

  private static boolean lastLogMessageIsFinalSeparator(String logMessageString) {
    return logMessageString.startsWith(FINAL_SPLIT) || logMessageString.startsWith(FINAL_SPLIT_WITH_TAB);
  }

  public void parseLine(String line, boolean isErrorMessage) {
    if (isErrorMessage) return;
    if (processingRevision) {
      if (line.startsWith(RCS_FILE)) {
        processRcsFile(line.substring(RCS_FILE.length()));
        return;
      }

      if (myRevisionPattern.matcher(line).matches()) {
        processRevisionStart(line);
        return;
      }

      if (line.startsWith(DATE)) {
        processRevisionDate(line);
        return;
      }

      // first check for the branches tag
      if (line.startsWith(BRANCHES)) {
        processBranches(line.substring(BRANCHES.length()));
      }
      else {
        logMessageBuffer.add(line);
      }
      return;
    }
    if (addingSymNames) {
      if (line.startsWith("\t")) {
        processSymbolicNames(line.substring(1));
        return;
      }
    }
    // revision stuff first -> will be  the most common to parse
    if (line.startsWith(REVISION)) {
      processRevisionStart(line);
      return;
    }
    if (line.startsWith(KEYWORD_SUBST)) {
      final String keywordSubstitution = line.substring(KEYWORD_SUBST.length()).trim();
      logInfo.setKeywordSubstitution(KeywordSubstitution.getValue(keywordSubstitution));
      addingSymNames = false;
      return;
    }

    if (line.startsWith(RCS_FILE)) {
      processRcsFile(line.substring(RCS_FILE.length()));
      return;
    }
    if (line.startsWith(WORKING_FILE)) {
      processWorkingFile(line.substring(WORKING_FILE.length()));
      return;
    }
    if (line.startsWith(HEAD)) {
      logInfo.setHeadRevision(line.substring(HEAD.length()).trim());
      return;
    }
    if (line.startsWith(BRANCH)) {
      logInfo.setBranch(line.substring(BRANCH.length()).trim());
      return;
    }
    if (line.startsWith(LOCKS)) {
      logInfo.setLocks(line.substring(LOCKS.length()).trim());
      return;
    }
    if (line.startsWith(ACCESS_LIST)) {
      logInfo.setAccessList(line.substring(ACCESS_LIST.length()).trim());
      return;
    }
    if (line.startsWith(SYMBOLIC_NAMES)) {
      addingSymNames = true;
      return;
    }
    if (line.startsWith(TOTAL_REVISIONS)) {
      final String separator = SELECTED_REVISIONS;
      final int semicolonIndex = line.indexOf(separator);
      if (semicolonIndex < 0) {
        // no selected revisions here..
        logInfo.setTotalRevisions(line.substring(TOTAL_REVISIONS.length()).trim());
        logInfo.setSelectedRevisions("0");
      }
      else {
        final String totalRevisions = line.substring(0, semicolonIndex);
        final String selectedRevisions = line.substring(semicolonIndex);
        logInfo.setTotalRevisions(totalRevisions.substring(TOTAL_REVISIONS.length()).trim());
        logInfo.setSelectedRevisions(selectedRevisions.substring(SELECTED_REVISIONS.length()).trim());
      }
      return;
    }

    if (addingDescription) {
      if (!processingRevision && line.startsWith(SPLITTER)) {
        return;
      }
      logMessageBuffer.add(line);
      return;
    }

    if (line.startsWith(DESCRIPTION)) {
      logMessageBuffer = new ArrayList();
      logMessageBuffer.add(line.substring(DESCRIPTION.length()));
      addingDescription = true;
    }
  }

  // Utils ==================================================================

  private void processRcsFile(String line) {
    if (logInfo != null) {
      outputDone();
    }
    logInfo = new LogInformation();
    logInfo.setRcsFileName(line.trim());
  }

  private void processWorkingFile(String line) {
    String fileName = line.trim();
    if (fileName.startsWith(NO_FILE_MESSAGE)) {
      fileName = fileName.substring(8);
    }

    logInfo.setFile(createFile(fileName));
  }

  private void processBranches(String line) {
    final int ind = line.lastIndexOf(';');
    if (ind > 0) {
      line = line.substring(0, ind);
    }
    revision.setBranches(line.trim());
  }

  private void processSymbolicNames(String line) {
    final int index = line.lastIndexOf(':');
    if (index < 0) {
      return;
    }

    final String symName = line.substring(0, index).trim();
    final String revName = line.substring(index + 1, line.length()).trim();
    logInfo.addSymbolicName(symName, revName);
  }

  private void processRevisionStart(String line) {
    revisionProcessingFinished();

    int tabIndex = line.indexOf('\t', REVISION.length());
    if (tabIndex < 0) {
      tabIndex = line.length();
    }

    final String revisionNumber = line.substring(REVISION.length(), tabIndex);
    revision = new Revision(revisionNumber);
    processingRevision = true;
  }

  private void revisionProcessingFinished() {
    if (revision != null) {
      if (logMessageBuffer.size() > 0 && logMessageBuffer.get(logMessageBuffer.size()-1).startsWith(SPLITTER)) {
        logMessageBuffer.remove(logMessageBuffer.size()-1);
      }
      processingRevision = false;
      revision.setMessage(getMessageFromBuffer());

      logInfo.addRevision(revision);
    }
  }

  private void processRevisionDate(String line) {
    // a line may looks like:
    // date: 2003/02/20 14:52:06;  author: tom;  state: Exp;  lines: +1 -1; kopt: o; commitid: 3803e54eb96167d;
    // or:
    // date: 2003/01/11 17:56:27;  author: tom;  state: Exp;
    final StringTokenizer token = new StringTokenizer(line, ";", false);
    if (token.hasMoreTokens()) {
      final String date = token.nextToken();
      final String dateString = date.substring(DATE.length());
      Date parsedDate = null;
      for (SyncDateFormat expectedDateFormat : EXPECTED_DATE_FORMATS) {
        try {
          parsedDate = expectedDateFormat.parse(dateString);
        }
        catch (ParseException e) {
          //ignore
        }
        if (parsedDate != null) break;
      }
      if (parsedDate != null) {
        revision.setDate(parsedDate);
      }
      else {
        BugLog.getInstance().showException(new Exception(JavaCvsSrcBundle.message("line.could.not.be.parsed.error.message", line)));
      }
    }
    if (token.hasMoreTokens()) {
      final String author = token.nextToken();
      if (author.startsWith(AUTHOR)) {
        revision.setAuthor(author.substring(AUTHOR.length()));
      }
    }
    if (token.hasMoreTokens()) {
      final String state = token.nextToken();
      if (state.startsWith(STATE)) {
        revision.setState(state.substring(STATE.length()));
      }
    }
    if (token.hasMoreTokens()) {
      final String linesModified = token.nextToken();
      if (linesModified.startsWith(LINES)) {
        revision.setLines(linesModified.substring(LINES.length()));
      }
    }

    processingRevision = true;
    logMessageBuffer = new ArrayList();
  }

  private File createFile(String fileName) {
    return cvsFileSystem.getLocalFileSystem().getFile(fileName);
  }

  public void binaryMessageSent(final byte[] bytes) {
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy