/** * Copyright (C) 2013-2014 Olaf Lessenich * Copyright (C) 2014-2015 University of Passau, Germany * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * Contributors: * Olaf Lessenich <lessenic@fim.uni-passau.de> * Georg Seibt <seibt@fim.uni-passau.de> */ package de.fosd.jdime.stats.parser; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; /** * The <code>Parser</code> generates a list of <code>Content</code> instances that represent the parts that the parsed * piece of code was split up into. A <code>Content</code> implementation may simply represent a list of lines * of code or a conflict that was found in the code. */ public abstract class Content { private static final Logger LOG = Logger.getLogger(Content.class.getCanonicalName()); /** * A list of lines of code that were not part of a conflict. */ public static class Merged extends Content { private List<String> lines; /** * Constructs a new <code>Merged</code> instance. */ public Merged() { super(false); this.lines = new ArrayList<>(); } /** * Adds a line of code to this <code>Merged</code> instance. * * @param line * the line to add */ public void add(String line) { lines.add(line); } @Override public String toString() { return String.join(System.lineSeparator(), lines); } @Override public String toString(String fstId, String... ids) { return toString(); } } /** * A two sided conflict. */ public static class Conflict extends Content { private static final String CONFLICT_START = "<<<<<<<"; private static final String CONFLICT_DELIM = "======="; private static final String CONFLICT_END = ">>>>>>>"; private List<String> leftLines; private List<String> rightLines; /** * Constructs a new <code>Conflict</code> instance. */ public Conflict() { super(true); this.leftLines = new ArrayList<>(); this.rightLines = new ArrayList<>(); } /** * Adds the left and right side lines of the given <code>Conflict</code> to this <code>Conflict</code>s * left and right lines. * * @param other * the <code>Conflict</code> to add */ public void add(Conflict other) { leftLines.addAll(other.leftLines); rightLines.addAll(other.rightLines); } /** * Adds a line to the left side of this <code>Conflict</code>. * * @param line * the line to add */ public void addLeft(String line) { leftLines.add(line); } /** * Adds a line to the right side of this <code>Conflict</code>. * * @param line * the line to add */ public void addRight(String line) { rightLines.add(line); } @Override public String toString() { String ls = System.lineSeparator(); StringBuilder b = new StringBuilder(); b.append(CONFLICT_START).append(ls); b.append(String.join(ls, leftLines)).append(ls); b.append(CONFLICT_DELIM).append(ls); b.append(String.join(ls, rightLines)).append(ls); b.append(CONFLICT_END); return b.toString(); } @Override public String toString(String fstId, String... ids) { if (fstId != null && ids == null || ids.length < 1) { LOG.warning("Insufficient identifiers for constructing a detailed conflict representation."); return toString(); } StringBuilder b = new StringBuilder(); String ls = System.lineSeparator(); b.append(CONFLICT_START).append(" ").append(fstId).append(ls); b.append(String.join(ls, leftLines)).append(ls); b.append(CONFLICT_DELIM).append(ls); b.append(String.join(ls, rightLines)).append(ls); b.append(CONFLICT_END).append(" ").append(ids[0]); return b.toString(); } } protected boolean isConflict; /** * Constructs a new <code>Content</code> piece. * * @param isConflict * whether this <code>Content</code> is a <code>Conflict</code> */ public Content(boolean isConflict) { this.isConflict = isConflict; } /** * Returns whether this <code>Content</code> piece is a <code>Conflict</code>. * * @return true iff this is a <code>Conflict</code> */ public boolean isConflict() { return isConflict; } @Override public abstract String toString(); /** * Returns a <code>String</code> representation of this piece of <code>Content</code>. The identifiers will * be used by the implementations to identify their parts (for example <code>Conflict</code> will use the first * two identifiers for marking the two sides of the conflict). * * @param fstId * to first identifier to use * @param ids * the other identifiers to use * @return a <code>String</code> representing this piece of <code>Content</code> */ public abstract String toString(String fstId, String... ids); }