1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2019, Chris Fraire <cfraire@me.com>. 23 */ 24 package org.opengrok.indexer.history; 25 26 import java.io.Serializable; 27 import java.util.Collection; 28 import java.util.Date; 29 import java.util.Objects; 30 import java.util.SortedSet; 31 import java.util.TreeSet; 32 import java.util.logging.Level; 33 import java.util.logging.Logger; 34 35 import org.jetbrains.annotations.VisibleForTesting; 36 import org.opengrok.indexer.logger.LoggerFactory; 37 38 /** 39 * Collect all information of a given revision. 40 * 41 * @author Trond Norbye 42 */ 43 public class HistoryEntry implements Serializable { 44 45 private static final long serialVersionUID = -1; 46 47 private static final Logger LOGGER = LoggerFactory.getLogger(HistoryEntry.class); 48 49 private String revision; 50 private Date date; 51 private String author; 52 53 @SuppressWarnings("PMD.AvoidStringBufferField") 54 private final StringBuffer message; 55 56 private boolean active; 57 private SortedSet<String> files; 58 59 /** Creates a new instance of HistoryEntry. */ HistoryEntry()60 public HistoryEntry() { 61 message = new StringBuffer(); 62 files = new TreeSet<>(); 63 } 64 65 /** 66 * Copy constructor. 67 * @param that HistoryEntry object 68 */ HistoryEntry(HistoryEntry that)69 public HistoryEntry(HistoryEntry that) { 70 this.revision = that.revision; 71 this.date = that.date; 72 this.author = that.author; 73 this.message = that.message; 74 this.active = that.active; 75 this.files = that.files; 76 } 77 HistoryEntry(String revision, Date date, String author, String message, boolean active)78 public HistoryEntry(String revision, Date date, String author, String message, boolean active) { 79 this.revision = revision; 80 setDate(date); 81 this.author = author; 82 this.message = new StringBuffer(message); 83 this.active = active; 84 this.files = new TreeSet<>(); 85 } 86 HistoryEntry(String revision, Date date, String author, String message, boolean active, Collection<String> files)87 public HistoryEntry(String revision, Date date, String author, 88 String message, boolean active, Collection<String> files) { 89 this(revision, date, author, message, active); 90 this.files.addAll(files); 91 } 92 93 @VisibleForTesting HistoryEntry(String revision)94 HistoryEntry(String revision) { 95 this(); 96 this.revision = revision; 97 } 98 getLine()99 public String getLine() { 100 return String.join(" ", 101 getRevision(), getDate().toString(), getAuthor(), message, "\n"); 102 } 103 dump()104 public void dump() { 105 106 LOGGER.log(Level.FINE, "HistoryEntry : revision = {0}", revision); 107 LOGGER.log(Level.FINE, "HistoryEntry : date = {0}", date); 108 LOGGER.log(Level.FINE, "HistoryEntry : author = {0}", author); 109 LOGGER.log(Level.FINE, "HistoryEntry : active = {0}", (active ? 110 "True" : "False")); 111 String[] lines = message.toString().split("\n"); 112 String separator = "="; 113 for (String line : lines) { 114 LOGGER.log(Level.FINE, "HistoryEntry : message {0} {1}", 115 new Object[]{separator, line}); 116 separator = ">"; 117 } 118 separator = "="; 119 for (String file : files) { 120 LOGGER.log(Level.FINE, "HistoryEntry : files {0} {1}", 121 new Object[]{separator, file}); 122 separator = ">"; 123 } 124 } 125 getAuthor()126 public String getAuthor() { 127 return author; 128 } 129 getDate()130 public Date getDate() { 131 return (date == null) ? null : (Date) date.clone(); 132 } 133 getMessage()134 public String getMessage() { 135 return message.toString().trim(); 136 } 137 getRevision()138 public String getRevision() { 139 return revision; 140 } 141 setAuthor(String author)142 public void setAuthor(String author) { 143 this.author = author; 144 } 145 setDate(Date date)146 public final void setDate(Date date) { 147 if (date == null) { 148 this.date = null; 149 } else { 150 this.date = (Date) date.clone(); 151 } 152 } 153 isActive()154 public boolean isActive() { 155 return active; 156 } 157 setActive(boolean active)158 public void setActive(boolean active) { 159 this.active = active; 160 } 161 setMessage(String message)162 public void setMessage(String message) { 163 this.message.setLength(0); 164 this.message.append(message); 165 } 166 setRevision(String revision)167 public void setRevision(String revision) { 168 this.revision = revision; 169 } 170 appendMessage(String message)171 public void appendMessage(String message) { 172 this.message.append(message); 173 this.message.append("\n"); 174 } 175 addFile(String file)176 public void addFile(String file) { 177 files.add(file); 178 } 179 getFiles()180 public SortedSet<String> getFiles() { 181 return files; 182 } 183 setFiles(SortedSet<String> files)184 public void setFiles(SortedSet<String> files) { 185 this.files = files; 186 } 187 188 /** 189 * @deprecated The method is kept only for backward compatibility to avoid warnings when deserializing objects 190 * from the previous format. 191 * The tags were moved to the {@link History} class. 192 * Will be removed sometime after the OpenGrok 1.8.0 version. 193 */ 194 @Deprecated(since = "1.7.11", forRemoval = true) setTags(String tags)195 public void setTags(String tags) { 196 // Tags moved to the History object. 197 } 198 199 @Override toString()200 public String toString() { 201 return String.join(" ", 202 getRevision(), getDate().toString(), getAuthor(), getMessage(), getFiles().toString()); 203 } 204 205 /** 206 * Remove list of files and tags. 207 */ strip()208 public void strip() { 209 stripFiles(); 210 } 211 212 /** 213 * Remove list of files. 214 */ stripFiles()215 public void stripFiles() { 216 files.clear(); 217 } 218 219 @Override equals(Object o)220 public boolean equals(Object o) { 221 if (this == o) { 222 return true; 223 } 224 if (o == null || getClass() != o.getClass()) { 225 return false; 226 } 227 HistoryEntry that = (HistoryEntry) o; 228 229 return Objects.equals(this.getAuthor(), that.getAuthor()) && 230 Objects.equals(this.getRevision(), that.getRevision()) && 231 Objects.equals(this.getDate(), that.getDate()) && 232 Objects.equals(this.getMessage(), that.getMessage()) && 233 Objects.equals(this.getFiles(), that.getFiles()); 234 } 235 236 @Override hashCode()237 public int hashCode() { 238 return Objects.hash(getAuthor(), getRevision(), getDate(), getMessage(), getFiles()); 239 } 240 } 241