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) 2018, Chris Fraire <cfraire@me.com>. 22 */ 23 package org.opengrok.indexer.search.context; 24 25 import java.util.Map; 26 import java.util.NoSuchElementException; 27 import java.util.SortedMap; 28 import java.util.TreeMap; 29 import org.apache.lucene.search.uhighlight.UnifiedHighlighter; 30 31 /** 32 * Represents structured results from {@link ContextFormatter} that can be 33 * merged with other instances. 34 * <p> 35 * {@link UnifiedHighlighter} returns results separated by field, and 36 * {@link OGKUnifiedHighlighter} merges them together to return a coherent 37 * result for presentation. 38 */ 39 public class FormattedLines { 40 private final SortedMap<Integer, String> lines = new TreeMap<>(); 41 private String footer; 42 private boolean limited; 43 44 /* 45 * Gets a count of the number of lines in the instance. 46 */ getCount()47 public int getCount() { 48 return lines.size(); 49 } 50 51 /** 52 * @return the footer 53 */ getFooter()54 public String getFooter() { 55 return footer; 56 } 57 setFooter(String value)58 public void setFooter(String value) { 59 footer = value; 60 } 61 62 /* 63 * Gets a value indicating if lines were limited. 64 */ isLimited()65 public boolean isLimited() { 66 return limited; 67 } 68 69 /* 70 * Sets a value indicating if lines were limited. 71 */ setLimited(boolean value)72 public void setLimited(boolean value) { 73 limited = value; 74 } 75 76 /** 77 * Removes the highest line from the instance. 78 * @return a defined value 79 * @throws NoSuchElementException if the instance is empty 80 */ pop()81 public String pop() { 82 return lines.remove(lines.lastKey()); 83 } 84 85 /** 86 * Sets the specified String line for the specified line number, replacing 87 * any previous entry for the same line number. 88 * @param lineno a value 89 * @param line a defined instance 90 * @return the former value or {@code null} 91 */ put(int lineno, String line)92 public String put(int lineno, String line) { 93 if (line == null) { 94 throw new IllegalArgumentException("line is null"); 95 } 96 return lines.put(lineno, line); 97 } 98 99 /** 100 * Creates a new instance with lines merged from this instance and 101 * {@code other}. Any lines in common for the same line number are taken 102 * from this instance rather than {@code other}; and likewise for 103 * {@link #getFooter()}. 104 * <p> 105 * {@link #isLimited()} will be {@code true} if either is {@code true}, but 106 * the value is suspect since it cannot be truly known if the merged result 107 * is actually the unlimited result. 108 * @param other a defined instance 109 * @return a defined instance 110 */ merge(FormattedLines other)111 public FormattedLines merge(FormattedLines other) { 112 FormattedLines res = new FormattedLines(); 113 res.lines.putAll(this.lines); 114 for (Map.Entry<Integer, String> kv : other.lines.entrySet()) { 115 res.lines.putIfAbsent(kv.getKey(), kv.getValue()); 116 } 117 118 res.setFooter(this.footer != null ? this.footer : other.footer); 119 res.setLimited(this.limited || other.limited); 120 return res; 121 } 122 123 @Override toString()124 public String toString() { 125 StringBuilder bld = new StringBuilder(); 126 for (String line : lines.values()) { 127 bld.append(line); 128 } 129 String f = footer; 130 if (f != null && limited) { 131 bld.append(f); 132 } 133 return bld.toString(); 134 } 135 } 136