private ResponseMapping computeResponseMapping(final ArgumentOutput input) { final ImmutableRangeSet<Integer> bannedRegions = docIdToBannedRegions.get(input.docId()); if (bannedRegions == null) { throw new RuntimeException(String.format( "QuoteFilter does not know about document ID %s", input.docId())); } final ImmutableSet.Builder<Response> toDeleteB = ImmutableSet.builder();; for (final Response response : input.responses()) { if (isInQuote(input.docId(), response.baseFiller()) || isInQuote(input.docId(), response.canonicalArgument().charOffsetSpan())) { toDeleteB.add(response); } } final ImmutableSet<Response> toDelete = toDeleteB.build(); log.info("For document {}, filtered out {} responses which were in quoted regions", input.docId(), toDelete.size()); return ResponseMapping.create(ImmutableMap.<Response,Response>of(), toDelete); }
private QuoteFilter(Map<Symbol, ImmutableRangeSet<Integer>> docIdToBannedRegions) { this.docIdToBannedRegions = ImmutableMap.copyOf(docIdToBannedRegions); for (RangeSet<Integer> rs : docIdToBannedRegions.values()) { for (final Range<Integer> r : rs.asRanges()) { checkArgument(r.hasLowerBound()); checkArgument(r.hasUpperBound()); checkArgument(r.lowerEndpoint() >= 0); } } // these ensure we can serialize safely for (Symbol sym : docIdToBannedRegions.keySet()) { final String s = sym.toString(); checkArgument(!s.isEmpty(), "Document IDs may not be empty"); checkArgument(!CharMatcher.WHITESPACE.matchesAnyOf(s), "Document IDs may not contain whitespace: %s", s); } }
public void saveTo(ByteSink sink) throws IOException { final PrintWriter out = new PrintWriter(sink.asCharSink(Charsets.UTF_8).openBufferedStream()); out.println(docIdToBannedRegions.size()); for (final Map.Entry<Symbol, ImmutableRangeSet<Integer>> entry : docIdToBannedRegions .entrySet()) { out.println(entry.getKey()); final List<String> parts = Lists.newArrayList(); for (final Range<Integer> r : entry.getValue().asRanges()) { // we know by construction these ranges are bounded above and below parts.add(String.format("%d-%d", r.lowerEndpoint(), r.upperEndpoint())); } out.println(StringUtils.SpaceJoiner.join(parts)); } out.close(); }
@Test public void testQuotedRegionComputation() throws IOException { final Map<String, ImmutableRangeSet<Integer>> testCases = ImmutableMap.of( "Foo <quote>bar <quote>baz</quote> <quote>meep</quote></quote> blah <quote>another</quote>", ImmutableRangeSet.<Integer>builder().add(Range.closed(4, 60)).add(Range.closed(67, 88)) .build(), "<quote>lalala</quote>", ImmutableRangeSet.of(Range.closed(0, 20)), "No quotes!", ImmutableRangeSet.<Integer>of()); for (final Map.Entry<String, ImmutableRangeSet<Integer>> entry : testCases.entrySet()) { final Symbol docid = Symbol.from("dummy"); final QuoteFilter reference = QuoteFilter.createFromBannedRegions(ImmutableMap.of(docid, entry.getValue())); final QuoteFilter computed = QuoteFilter.createFromOriginalText(ImmutableMap.of(docid, CharSource.wrap(entry.getKey()))); assertEquals(reference, computed); } }
public static FrontendClientMetadata readFrom(final DataInput in) throws IOException, ClassNotFoundException { final ClientIdentifier id = ClientIdentifier.readFrom(in); final int purgedSize = in.readInt(); final Builder<UnsignedLong> b = ImmutableRangeSet.builder(); for (int i = 0; i < purgedSize; ++i) { final byte header = WritableObjects.readLongHeader(in); final UnsignedLong lower = UnsignedLong.fromLongBits(WritableObjects.readFirstLong(in, header)); final UnsignedLong upper = UnsignedLong.fromLongBits(WritableObjects.readSecondLong(in, header)); b.add(Range.closed(lower, upper)); } final int currentSize = in.readInt(); final Collection<FrontendHistoryMetadata> currentHistories = new ArrayList<>(currentSize); for (int i = 0; i < currentSize; ++i) { currentHistories.add(FrontendHistoryMetadata.readFrom(in)); } return new FrontendClientMetadata(id, b.build(), currentHistories); }
private CrontabEntry( RangeSet<Integer> minute, RangeSet<Integer> hour, RangeSet<Integer> dayOfMonth, RangeSet<Integer> month, RangeSet<Integer> dayOfWeek) { checkEnclosed("minute", MINUTE, minute); checkEnclosed("hour", HOUR, hour); checkEnclosed("dayOfMonth", DAY_OF_MONTH, dayOfMonth); checkEnclosed("month", MONTH, month); checkEnclosed("dayOfWeek", DAY_OF_WEEK, dayOfWeek); this.minute = ImmutableRangeSet.copyOf(minute); this.hour = ImmutableRangeSet.copyOf(hour); this.dayOfMonth = ImmutableRangeSet.copyOf(dayOfMonth); this.month = ImmutableRangeSet.copyOf(month); this.dayOfWeek = ImmutableRangeSet.copyOf(dayOfWeek); checkArgument(hasWildcardDayOfMonth() || hasWildcardDayOfWeek(), "Specifying both dayOfWeek and dayOfMonth is not supported."); }
@Test public void testReadWithNoData() throws IOException { newTimeSeriesPartition(Configuration.newBuilder() .dataDirectory(this.testDirectory) .memTimeSeriesSize(MEMTIMESERIES_SIZE) .build()); EasyMock.replay(this.manager, this.listener); Range<Field> range = MILLISECONDS_TIMESTAMP.range("'2013-11-26 12:00:00.000'", "'2013-11-26 14:00:00.000'"); ResourceIterator<Record> iterator = this.partition.read(ImmutableRangeSet.of(range), Filters.<String>noop(), toFilter(range)); Assert.assertFalse(iterator.hasNext()); EasyMock.verify(this.manager, this.listener); }
@Test public void exceptionTest() { final UnresolvedNumber min = UnresolvedNumber.min(); final UnresolvedNumber max = UnresolvedNumber.max(); final EnumPair enumPair = EnumPairBuilder.create("enum1", 1).setDescription("description") .setReference("reference").setUnknownSchemaNodes(mock(UnknownSchemaNode.class)).build(); final RangeSet<Integer> rangeset = ImmutableRangeSet.of(Range.closed(1, 2)); final InvalidRangeConstraintException invalidRangeConstraintException = new InvalidRangeConstraintException( rangeset, "error msg", "other important messages"); assertSame(rangeset, invalidRangeConstraintException.getOffendingRanges()); final InvalidBitDefinitionException invalidBitDefinitionException = new InvalidBitDefinitionException( BIT_A, "error msg", "other important messages"); assertEquals(invalidBitDefinitionException.getOffendingBit(), BIT_A); final InvalidEnumDefinitionException invalidEnumDefinitionException = new InvalidEnumDefinitionException( enumPair, "error msg", "other important messages"); assertEquals(invalidEnumDefinitionException.getOffendingEnum(), enumPair); }
private RexNode compareFloorCeil(SqlKind comparison, RexNode operand, RexLiteral timeLiteral, TimeUnitRange timeUnit, boolean floor) { RangeSet<Calendar> rangeSet = operandRanges.get(operand.toString()); if (rangeSet == null) { rangeSet = ImmutableRangeSet.<Calendar>of().complement(); } final RangeSet<Calendar> s2 = TreeRangeSet.create(); final Calendar c = timestampValue(timeLiteral); final Range<Calendar> range = floor ? floorRange(timeUnit, comparison, c) : ceilRange(timeUnit, comparison, c); s2.add(range); // Intersect old range set with new. s2.removeAll(rangeSet.complement()); operandRanges.put(operand.toString(), ImmutableRangeSet.copyOf(s2)); if (range.isEmpty()) { return rexBuilder.makeLiteral(false); } return toRex(operand, range); }
@Test public void testComplement() { Range range; ImmutableRangeSet.Builder builder; Interval.Difference difference; difference = a.complement(); range = Range.lessThan(2); builder = ImmutableRangeSet.builder().add(range); range = Range.greaterThan(4); builder.add(range); assertEquals(difference.getRanges(), builder.build()); assertEquals(difference.getDimension(), 1); difference = Interval.MAGIC.complement(); builder = ImmutableRangeSet.builder(); assertEquals(difference.getRanges(), builder.build()); assertEquals(difference.getDimension(), 0); difference = Interval.NULL.complement(); range = Range.all(); builder = ImmutableRangeSet.builder().add(range); assertEquals(difference.getRanges(), builder.build()); assertEquals(difference.getDimension(), 0); }
private CharacterClassRangeSet(final ImmutableRangeSet<Integer> rangeSet, boolean containsEOF) { assert rangeSet.isEmpty() || rangeSet.span().lowerEndpoint() >= 0; assert rangeSet.isEmpty() || rangeSet.span().upperEndpoint() < CharacterClassFactory.EOF_INT; if(rangeSet.isEmpty()) { this.min = this.max = containsEOF ? CharacterClassFactory.EOF_INT : -1; } else { this.min = rangeSet.span().lowerEndpoint(); this.max = Math.max(rangeSet.span().upperEndpoint(), containsEOF ? CharacterClassFactory.EOF_INT : -1); } this.rangeSet = rangeSet; this.containsEOF = containsEOF; this.useCachedBitSet = tryOptimize(); }
public boolean isInQuote(Symbol docId, CharOffsetSpan span) { final ImmutableRangeSet<Integer> bannedRegions = docIdToBannedRegions.get(docId); if (bannedRegions == null) { throw new RuntimeException(String.format( "QuoteFilter does not know about document ID %s", docId)); } return inBannedSet(span, bannedRegions); }
public static QuoteFilter createFromOriginalText(Map<Symbol, ? extends CharSource> originalTexts) throws IOException { checkNotNull(originalTexts); final ImmutableMap.Builder<Symbol, ImmutableRangeSet<Integer>> ret = ImmutableMap.builder(); for (final Map.Entry<Symbol, ? extends CharSource> originalTextPair : originalTexts .entrySet()) { final Symbol docID = originalTextPair.getKey(); final CharSource originalTextSource = originalTextPair.getValue(); ret.put(docID, computeQuotedRegions(originalTextSource.read())); } return createFromBannedRegions(ret.build()); }
public static QuoteFilter loadFrom(ByteSource source) throws IOException { final ImmutableList<String> input = source.asCharSource(Charsets.UTF_8).readLines(); if (input.isEmpty()) { throw new IOException("Attempted to load QuoteFilter from empty file"); } final int numEntries = Integer.parseInt(input.get(0)); final int expectedLines = 2 * numEntries + 1; if (input.size() != expectedLines) { throw new IOException(String.format( "Invalid number of lines when loading QuoteFiler. Expected %d, got %d", expectedLines, input.size())); } final ImmutableMap.Builder<Symbol, ImmutableRangeSet<Integer>> ret = ImmutableMap.builder(); int curLine = 1; for (int i = 0; i < numEntries; ++i) { final Symbol docid = Symbol.from(input.get(curLine++)); final ImmutableRangeSet.Builder<Integer> ranges = ImmutableRangeSet.builder(); for (final String part : StringUtils.OnSpaces.split(input.get(curLine++))) { final List<String> endPointStrings = DASH_SPLITTER.splitToList(part); if (endPointStrings.size() != 2) { throw new IOException(String.format("Invalid range serialization %s", part)); } ranges.add(Range.closed(Integer.parseInt(endPointStrings.get(0)), Integer.parseInt(endPointStrings.get(1)))); } ret.put(docid, ranges.build()); } return QuoteFilter.createFromBannedRegions(ret.build()); }
@Test public void testSerialization() throws IOException { final QuoteFilter reference = QuoteFilter.createFromBannedRegions( ImmutableMap.of( Symbol.from("dummy"), ImmutableRangeSet.<Integer>builder().add(Range.closed(4, 60)).add(Range.closed(67, 88)) .build(), Symbol.from("dummy2"), ImmutableRangeSet.of(Range.closed(0, 20)))); final ByteArraySink sink = new ByteArraySink(); reference.saveTo(sink); final ByteSource source = ByteSource.wrap(sink.toByteArray()); final Object restored = QuoteFilter.loadFrom(source); assertEquals(reference, restored); }
CommandLineOptions( ImmutableList<String> files, boolean inPlace, ImmutableRangeSet<Integer> lines, ImmutableList<Integer> offsets, ImmutableList<Integer> lengths, boolean aosp, boolean version, boolean help, boolean stdin, boolean fixImportsOnly, boolean removeJavadocOnlyImports, boolean sortImports, boolean removeUnusedImports) { this.files = files; this.inPlace = inPlace; this.lines = lines; this.offsets = offsets; this.lengths = lengths; this.aosp = aosp; this.version = version; this.help = help; this.stdin = stdin; this.fixImportsOnly = fixImportsOnly; this.removeJavadocOnlyImports = removeJavadocOnlyImports; this.sortImports = sortImports; this.removeUnusedImports = removeUnusedImports; }
public FrontendHistoryMetadata(final long historyId, final long cookie, final boolean closed, final Map<UnsignedLong, Boolean> closedTransactions, final RangeSet<UnsignedLong> purgedTransactions) { this.historyId = historyId; this.cookie = cookie; this.closed = closed; this.closedTransactions = ImmutableMap.copyOf(closedTransactions); this.purgedTransactions = ImmutableRangeSet.copyOf(purgedTransactions); }
/** * Performs {@link #toRange(IRange)} for a collection of ranges, and convert the result to a set * of integers. * * @param ranges Ranges to convert. * @return A set representing {@code ranges}. */ public static Set<Integer> rangesToInstanceIds(Iterable<IRange> ranges) { ImmutableRangeSet.Builder<Integer> instanceIds = ImmutableRangeSet.builder(); for (IRange range : ranges) { instanceIds.add(toRange(range)); } return instanceIds.build().asSet(DiscreteDomain.integers()); }
/** * Creates a range set representing all instance IDs represented by a set of instance * configurations included in a job update. * * @param configs Job update components. * @return A range set representing the instance IDs mentioned in instance groupings. */ public static ImmutableRangeSet<Integer> getInstanceIds(Set<IInstanceTaskConfig> configs) { ImmutableRangeSet.Builder<Integer> builder = ImmutableRangeSet.builder(); for (IInstanceTaskConfig config : configs) { for (IRange range : config.getInstances()) { builder.add(Range.closed(range.getFirst(), range.getLast())); } } return builder.build(); }
private RangeSet<Integer> parseMinute() { RangeSet<Integer> minutes = TreeRangeSet.create(); for (String component : getComponents(rawMinute)) { minutes.addAll(parseComponent(MINUTE, component)); } return ImmutableRangeSet.copyOf(minutes); }
private RangeSet<Integer> parseHour() { RangeSet<Integer> hours = TreeRangeSet.create(); for (String component : getComponents(rawHour)) { hours.addAll(parseComponent(HOUR, component)); } return ImmutableRangeSet.copyOf(hours); }
private RangeSet<Integer> parseDayOfWeek() { RangeSet<Integer> daysOfWeek = TreeRangeSet.create(); for (String component : getComponents(rawDayOfWeek)) { daysOfWeek.addAll(parseComponent(DAY_OF_WEEK, replaceNameAliases(component, DAY_NAMES))); } return ImmutableRangeSet.copyOf(daysOfWeek); }
private RangeSet<Integer> parseMonth() { RangeSet<Integer> months = TreeRangeSet.create(); for (String component : getComponents(rawMonth)) { months.addAll(parseComponent(MONTH, replaceNameAliases(component, MONTH_NAMES))); } return ImmutableRangeSet.copyOf(months); }
private RangeSet<Integer> parseDayOfMonth() { RangeSet<Integer> daysOfMonth = TreeRangeSet.create(); for (String component : getComponents(rawDayOfMonth)) { daysOfMonth.addAll(parseComponent(DAY_OF_MONTH, component)); } return ImmutableRangeSet.copyOf(daysOfMonth); }
/** Creates an IDN table given the lines from text file. */ static IdnTable createFrom( String language, Iterable<String> data, Optional<LanguageValidator> languageValidator) { ImmutableRangeSet.Builder<Integer> rangeSet = new ImmutableRangeSet.Builder<>(); URI url = null; URI policy = null; for (String line : data) { // Remove leading and trailing whitespace. line = line.trim(); // Handle special comment lines. if (line.startsWith(URL_LINE_PREFIX)) { url = URI.create(line.substring(URL_LINE_PREFIX.length())); } else if (line.startsWith(POLICY_LINE_PREFIX)) { policy = URI.create(line.substring(POLICY_LINE_PREFIX.length())); } // Skip empty and comment lines. if (line.isEmpty() || line.startsWith("#")) { continue; } int codepoint = readCodepoint(line); rangeSet.add(Range.singleton(codepoint)); } return new IdnTable(language, url, policy, rangeSet.build(), languageValidator); }
/** * @see #fromRangeSet(RangeSet) */ @SafeVarargs public static DigitMapping fromRangeSet(Range<Character>... ranges) { ImmutableRangeSet.Builder<Character> builder = ImmutableRangeSet.builder(); for (Range<Character> range : ranges) { builder.add(range); } return fromRangeSet(builder.build()); }
CommandLineOptions( ImmutableList<String> files, boolean inPlace, ImmutableRangeSet<Integer> lines, ImmutableList<Integer> offsets, ImmutableList<Integer> lengths, boolean aosp, boolean version, boolean help, boolean stdin, boolean fixImportsOnly, boolean sortImports, boolean removeUnusedImports, boolean dryRun, boolean setExitIfChanged) { this.files = files; this.inPlace = inPlace; this.lines = lines; this.offsets = offsets; this.lengths = lengths; this.aosp = aosp; this.version = version; this.help = help; this.stdin = stdin; this.fixImportsOnly = fixImportsOnly; this.sortImports = sortImports; this.removeUnusedImports = removeUnusedImports; this.dryRun = dryRun; this.setExitIfChanged = setExitIfChanged; }
/** * Converts the specified list into a range set. * * @param buffers the token restriction values * @return the range set corresponding to the specified list */ private RangeSet<Token> toRangeSet(List<ByteBuffer> buffers) { ImmutableRangeSet.Builder<Token> builder = ImmutableRangeSet.builder(); for (ByteBuffer buffer : buffers) builder.add(Range.singleton(deserializeToken(buffer))); return builder.build(); }
@SuppressWarnings("unchecked") private static <T extends Number & Comparable<T>> RangeSet<T> ensureTypedRanges(final List<ValueRange> ranges, final Class<? extends Number> clazz) { final Builder<T> builder = ImmutableRangeSet.builder(); for (ValueRange range : ranges) { if (!clazz.isInstance(range.lowerBound()) || !clazz.isInstance(range.upperBound())) { return typedRanges(ranges, clazz); } builder.add(Range.closed((T) range.lowerBound(), (T)range.upperBound())); } return builder.build(); }
@SuppressWarnings("unchecked") private static <T extends Number & Comparable<T>> RangeSet<T> typedRanges(final List<ValueRange> ranges, final Class<? extends Number> clazz) { final Function<Number, ? extends Number> function = NumberUtil.converterTo(clazz); Preconditions.checkArgument(function != null, "Unsupported range class %s", clazz); final Builder<T> builder = ImmutableRangeSet.builder(); for (ValueRange range : ranges) { if (!clazz.isInstance(range.lowerBound()) || !clazz.isInstance(range.upperBound())) { final Number min; final Number max; try { min = function.apply(range.lowerBound()); max = function.apply(range.upperBound()); } catch (NumberFormatException e) { throw new IllegalArgumentException(String.format("Constraint %s does not fit into range of %s", range, clazz.getSimpleName()), e); } builder.add(Range.closed((T)min, (T)max)); } else { builder.add(Range.closed((T) range.lowerBound(), (T)range.upperBound())); } } return builder.build(); }
/** * Set a new length constraint. * * @param constraint Constraint metadata * @param ranges Allowed ranges * @throws IllegalStateException if the constraint has already been set * @throws InvalidLengthConstraintException if one of the proposed ranges does not overlap with supertype * @throws NullPointerException if any of the arguments is null */ public final void setLengthConstraint(final @NonNull ConstraintMetaDefinition constraint, final @NonNull List<ValueRange> ranges) throws InvalidLengthConstraintException { Preconditions.checkState(lengthConstraint == null, "Length constraint already defined as %s", lengthConstraint); final LengthConstraint baseLengths = findLenghts(); if (ranges.isEmpty()) { lengthConstraint = baseLengths; return; } // Run through alternatives and resolve them against the base type requireNonNull(constraint); final Builder<Integer> builder = ImmutableRangeSet.builder(); final Range<Integer> span = baseLengths.getAllowedRanges().span(); for (ValueRange c : ranges) { builder.add(Range.closed(resolveLength(c.lowerBound(), span), resolveLength(c.upperBound(), span))); } // Now verify if new ranges are strict subset of base ranges final RangeSet<Integer> allowed = builder.build(); final RangeSet<Integer> baseRanges = baseLengths.getAllowedRanges(); for (Range<Integer> range : allowed.asRanges()) { if (!baseRanges.encloses(range)) { throw new InvalidLengthConstraintException("Range %s is not a subset of parent constraint %s", range, baseRanges); } } lengthConstraint = new ResolvedLengthConstraint(constraint, allowed); touch(); }
/** * Construct a new Difference, which may have zero, one, or two non-null * , nonempty, non-overlapping interval ranges in the same dimension. * @param that interval * @param other interval * @see ImmutableRangeSet#add(com.google.common.collect.Range) */ private Difference(final Interval<C> that, final Interval<C> other) { ImmutableRangeSet.Builder builder = ImmutableRangeSet.builder(); if(that.dimension == other.dimension) { dimension = that.dimension; } else { dimension = 0; } if(that.overlaps(other)) { dimension = that.getDimension(); builder.add(that.coalesce(other).toRange()); } else { if(!that.hasNone() && !that.range.isEmpty()) { dimension = that.dimension; builder.add(that.range); } if(!other.hasNone() && !other.range.isEmpty()) { if(dimension == 0) { dimension = other.dimension; } if(dimension == other.dimension) { builder.add(other.range); } } } ranges = builder.build(); }
public static Vlan parse(String vlan) { if (!PATTERN.matcher(vlan).matches()) { throw new IllegalArgumentException("invalid VLAN range: " + vlan); } ImmutableRangeSet.Builder<Integer> vlanRanges = ImmutableRangeSet.builder(); asList(vlan.split(",")).stream() .map(part -> parsePart(part).canonical(integers())) .forEach(vlanRanges::add); return new Vlan(vlanRanges.build()); }
public Vlan subtract(Set<Integer> vlanIds) { ImmutableRangeSet.Builder<Integer> builder = ImmutableRangeSet.builder(); removeValuesFromRangeSet(vlanIds).asRanges().stream() .map(r -> r.canonical(integers())) .filter(r -> !r.isEmpty()) .forEach(builder::add); return new Vlan(builder.build()); }
protected final CharacterClassRangeSet addRange(int from, int to) { final RangeSet<Integer> mutableRangeSet = TreeRangeSet.create(rangeSet); mutableRangeSet.add(Range.closed(from, Math.min(255, to))); return new CharacterClassRangeSet(ImmutableRangeSet.copyOf(mutableRangeSet), containsEOF || to == CharacterClassFactory.EOF_INT); }
protected final CharacterClassRangeSet addSingle(int character) { final RangeSet<Integer> mutableRangeSet = TreeRangeSet.create(rangeSet); if(character < CharacterClassFactory.EOF_INT) mutableRangeSet.add(Range.singleton(character)); return new CharacterClassRangeSet(ImmutableRangeSet.copyOf(mutableRangeSet), containsEOF || character == CharacterClassFactory.EOF_INT); }
protected final CharacterClassRangeSet removeSingle(int character) { final RangeSet<Integer> mutableRangeSet = TreeRangeSet.create(rangeSet); if(character < CharacterClassFactory.EOF_INT) mutableRangeSet.remove(Range.open(character - 1, character + 1)); return new CharacterClassRangeSet(ImmutableRangeSet.copyOf(mutableRangeSet), containsEOF && character != CharacterClassFactory.EOF_INT); }
public CharacterClassRangeSet rangeSetIntersection(CharacterClassRangeSet other) { final RangeSet<Integer> mutableRangeSet = TreeRangeSet.create(); for(Range<Integer> range : this.rangeSet.asRanges()) { mutableRangeSet.addAll(other.rangeSet.subRangeSet(range)); } boolean containsEOF = this.containsEOF && other.containsEOF; return new CharacterClassRangeSet(ImmutableRangeSet.copyOf(mutableRangeSet), containsEOF); }
/** * Given the string contents of a document, will return the offset ranges of those portions within * <quote> tags. This does not pay attention to the attributes of the quote tags. */ public static ImmutableRangeSet<Integer> computeQuotedRegions(String s) { checkNotNull(s); final ImmutableRangeSet.Builder<Integer> ret = ImmutableRangeSet.builder(); // current search position int curPos = 0; // search for first opening <quote> tag int regionStart = StringUtils.earliestIndexOfAny(s, BANNED_REGION_STARTS, curPos); // if we found a <quote> tag while (regionStart != -1) { curPos = regionStart; int nestingCount = 1; // until we find the matching </quote> tag.. while (nestingCount > 0) { final int nextStart = StringUtils.earliestIndexOfAny(s, BANNED_REGION_STARTS, curPos + 1); final int nextEnd = s.indexOf(BANNED_REGION_END, curPos + 1); if (nextEnd == -1) { // (a) uh-oh, we reached the end without ever finding a match throw new RuntimeException( String.format("<quote> tag opened at %d is never closed.", regionStart)); } else if (nextStart == -1 || nextEnd < nextStart) { // (b) we find a </quote> before another <quote>, so // we reduce the nesting level and remember the location // of the closing tag --nestingCount; curPos = nextEnd; } else if (nextEnd > nextStart) { // (c) we found another <quote> before the end of the current // <quote>, so there must be nesting. ++nestingCount; curPos = nextStart; } else { throw new RuntimeException("It is impossible for nextEnd == nextStart"); } } // the only way we successfully exited is case (b) // where curPos is the beginning of the </quote> tag ret.add(Range.closed(regionStart, curPos + BANNED_REGION_END.length() - 1)); regionStart = StringUtils.earliestIndexOfAny(s, BANNED_REGION_STARTS, curPos + 1); } return ret.build(); }
protected Map<Symbol, ImmutableRangeSet<Integer>> docIdToBannedRegions() { return docIdToBannedRegions; }