List of usage examples for com.google.common.collect Iterables getLast
public static <T> T getLast(Iterable<T> iterable)
From source file:com.opengamma.integration.viewer.status.impl.ViewStatusResultAggregatorImpl.java
private List<List<Object>> createRowData(final Map<List<String>, Set<String>> fixedRow2Columns, final Set<String> extraColumns, List<ViewColumnType> columnTypes) { List<List<String>> rows = Lists.newArrayList(fixedRow2Columns.keySet()); Comparator<List<String>> rowComparator = new Comparator<List<String>>() { @Override//from www .j a v a 2 s. com public int compare(List<String> left, List<String> right) { int compare = 0; for (int i = 0; i < left.size(); i++) { compare = left.get(i).compareTo(right.get(i)); if (compare != 0) { return compare; } } return compare; } }; Collections.sort(rows, rowComparator); List<List<Object>> processedRows = Lists.newArrayListWithCapacity(rows.size()); String[] currentRow = new String[Iterables.getFirst(rows, Lists.newArrayList()).size()]; for (List<String> row : rows) { List<Object> processedRow = Lists.newArrayList(); Iterable<String> columns = Iterables.limit(row, row.size() - 1); int count = 0; for (String col : columns) { if (currentRow[count] == null || !col.equals(currentRow[count])) { currentRow[count] = col; processedRow.add(col); } else { processedRow.add(EMPTY_STR); } count++; } processedRow.add(Iterables.getLast(row)); for (String col : extraColumns) { List<String> keyMemebers = Lists.newArrayList(row); keyMemebers.add(col); ViewStatus status = getStatus(keyFromRowValues(keyMemebers, columnTypes)); if (status == null) { processedRow.add(EMPTY_STR); } else { processedRow.add(status); } } processedRows.add(processedRow); } return processedRows; }
From source file:com.google.errorprone.bugpatterns.JUnit3FloatingPointComparisonWithoutDelta.java
/** * Gets the index of where to insert the delta argument. */// w ww .ja v a 2s . c om private int getDeltaInsertionIndex(MethodInvocationTree methodInvocationTree, VisitorState state) { JCTree lastArgument = (JCTree) Iterables.getLast(methodInvocationTree.getArguments()); return state.getEndPosition(lastArgument); }
From source file:google.registry.xml.XmlTestUtils.java
/** * Deeply explore the object and normalize values so that things we consider equal compare so. * The return value consists of two parts: the updated key and the value. The value is * straightforward enough: it is the rendering of the subtree to be attached at the current point. * The key is more complicated, because of namespaces. When an XML element specifies namespaces * using xmlns attributes, those namespaces apply to the element as well as all of its * descendants. That means that, when prefixing the element name with the full namespace path, * as required to do proper comparison, the element name depends on its children. When looping * through a JSONObject map, we can't just recursively generate the value and store it using the * key. We may have to update the key as well, to get the namespaces correct. A returned key of * null indicates that we should use the existing key. A non-null key indicates that we should * replace the existing key./*from ww w . j a v a 2 s . c o m*/ * * @param elementName the name under which the current subtree was found, or null if the current * subtree's name is nonexistent or irrelevant * @param obj the current subtree * @param path the (non-namespaced) element path used for ignoredPaths purposes * @param ignoredPaths the set of paths whose values should be set to IGNORED * @param nsMap the inherited namespace identifier-to-URI map * @return the key under which the rendered subtree should be stored (or null), and the rendered * subtree */ private static Map.Entry<String, Object> normalize(@Nullable String elementName, Object obj, @Nullable String path, Set<String> ignoredPaths, Map<String, String> nsMap) throws Exception { if (obj instanceof JSONObject) { JSONObject jsonObject = (JSONObject) obj; Map<String, Object> map = new HashMap<>(); String[] names = JSONObject.getNames(jsonObject); if (names != null) { // Separate all elements and keys into namespace specifications, which we must process // first, and everything else. ImmutableList.Builder<String> namespacesBuilder = new ImmutableList.Builder<>(); ImmutableList.Builder<String> othersBuilder = new ImmutableList.Builder<>(); for (String key : names) { (key.startsWith("xmlns") ? namespacesBuilder : othersBuilder).add(key); } // First, handle all namespace specifications, updating our ns-to-URI map. Use a HashMap // rather than an ImmutableMap.Builder so that we can override existing map entries. HashMap<String, String> newNsMap = new HashMap<>(); newNsMap.putAll(nsMap); for (String key : namespacesBuilder.build()) { // Parse the attribute name, of the form xmlns:nsid, and extract the namespace identifier. // If there's no colon, we are setting the default namespace. List<String> components = Splitter.on(':').splitToList(key); String ns = (components.size() >= 2) ? components.get(1) : ""; newNsMap.put(ns, jsonObject.get(key).toString()); } nsMap = ImmutableMap.copyOf(newNsMap); // Now, handle the non-namespace items, recursively transforming the map and mapping all // namespaces to the full URI for proper comparison. for (String key : othersBuilder.build()) { String simpleKey = Iterables.getLast(Splitter.on(':').split(key)); String newPath = (path == null) ? simpleKey : (path + "." + simpleKey); String mappedKey; Object value; if (ignoredPaths.contains(newPath)) { mappedKey = null; // Set ignored fields to a value that will compare equal. value = "IGNORED"; } else { Map.Entry<String, Object> simpleEntry = normalize(key, jsonObject.get(key), newPath, ignoredPaths, nsMap); mappedKey = simpleEntry.getKey(); value = simpleEntry.getValue(); } if (mappedKey == null) { // Note that this does not follow the XML rules exactly. I read somewhere that attribute // names, unlike element names, never use the default namespace. But after // JSONification, we cannot distinguish between attributes and child elements, so we // apply the default namespace to everything. Hopefully that will not cause a problem. mappedKey = key.equals("content") ? key : mapName(key, nsMap, true); } map.put(mappedKey, value); } } // Map the namespace of the element name of the map we are normalizing. elementName = mapName(elementName, nsMap, true); // If a node has both text content and attributes, the text content will end up under a key // called "content". If that's the only thing left (which will only happen if there was an // "xmlns:*" key that we removed), treat the node as just text and recurse. if (map.size() == 1 && map.containsKey("content")) { return new AbstractMap.SimpleEntry<>(elementName, normalize(null, jsonObject.get("content"), path, ignoredPaths, nsMap).getValue()); } // The conversion to JSON converts <a/> into "" and the semantically equivalent <a></a> into // an empty map, so normalize that here. return new AbstractMap.SimpleEntry<>(elementName, map.isEmpty() ? "" : map); } if (obj instanceof JSONArray) { // Another problem resulting from JSONification: If the array contains elements whose names // are the same before URI expansion, but different after URI expansion, because they use // xmlns attribute that define the namespaces differently, we will screw up. Again, hopefully // that doesn't happen much. The reverse is also true: If the array contains names that are // different before URI expansion, but the same after, we may have a problem, because the // elements will wind up in different JSONArrays as a result of JSONification. We wave our // hands and just assume that the URI expansion of the first element holds for all others. Set<Object> set = new HashSet<>(); String mappedKey = null; for (int i = 0; i < ((JSONArray) obj).length(); ++i) { Map.Entry<String, Object> simpleEntry = normalize(null, ((JSONArray) obj).get(i), path, ignoredPaths, nsMap); if (i == 0) { mappedKey = simpleEntry.getKey(); } set.add(simpleEntry.getValue()); } return new AbstractMap.SimpleEntry<String, Object>(mappedKey, set); } if (obj instanceof Number) { return new AbstractMap.SimpleEntry<String, Object>(null, obj.toString()); } if (obj instanceof Boolean) { return new AbstractMap.SimpleEntry<String, Object>(null, ((Boolean) obj) ? "1" : "0"); } if (obj instanceof String) { // Turn stringified booleans into integers. Both are acceptable as xml boolean values, but // we use "true" and "false" whereas the samples use "1" and "0". if (obj.equals("true")) { return new AbstractMap.SimpleEntry<String, Object>(null, "1"); } if (obj.equals("false")) { return new AbstractMap.SimpleEntry<String, Object>(null, "0"); } String string = obj.toString(); // We use a slightly different datetime format (both legal) than the samples, so normalize // both into Datetime objects. try { return new AbstractMap.SimpleEntry<String, Object>(null, ISODateTimeFormat.dateTime().parseDateTime(string).toDateTime(UTC)); } catch (IllegalArgumentException e) { // It wasn't a DateTime. } try { return new AbstractMap.SimpleEntry<String, Object>(null, ISODateTimeFormat.dateTimeNoMillis().parseDateTime(string).toDateTime(UTC)); } catch (IllegalArgumentException e) { // It wasn't a DateTime. } try { if (!InternetDomainName.isValid(string)) { // It's not a domain name, but it is an InetAddress. Ergo, it's an ip address. return new AbstractMap.SimpleEntry<String, Object>(null, InetAddresses.forString(string)); } } catch (IllegalArgumentException e) { // Not an ip address. } return new AbstractMap.SimpleEntry<String, Object>(null, string); } return new AbstractMap.SimpleEntry<>(null, checkNotNull(obj)); }
From source file:org.glowroot.ui.GaugeValueJsonService.java
private List<GaugeValue> getGaugeValues(String agentRollupId, long from, long to, String gaugeName, int rollupLevel) throws Exception { List<GaugeValue> gaugeValues = gaugeValueRepository.readGaugeValues(agentRollupId, gaugeName, from, to, rollupLevel);//from w w w.j a v a 2 s. c o m if (rollupLevel == 0) { return gaugeValues; } long nonRolledUpFrom = from; if (!gaugeValues.isEmpty()) { nonRolledUpFrom = Iterables.getLast(gaugeValues).getCaptureTime() + 1; } List<GaugeValue> orderedNonRolledUpGaugeValues = Lists.newArrayList(); int lowestLevel = agentRollupId.endsWith("::") ? 1 : 0; orderedNonRolledUpGaugeValues.addAll( gaugeValueRepository.readGaugeValues(agentRollupId, gaugeName, nonRolledUpFrom, to, lowestLevel)); gaugeValues = Lists.newArrayList(gaugeValues); long fixedIntervalMillis = configRepository.getRollupConfigs().get(rollupLevel - 1).intervalMillis(); gaugeValues.addAll(rollUpGaugeValues(orderedNonRolledUpGaugeValues, gaugeName, new RollupCaptureTimeFn(fixedIntervalMillis))); return gaugeValues; }
From source file:org.sonar.java.checks.LeftCurlyBraceBaseTreeVisitor.java
private static SyntaxToken getLastTokenFromSignature(MethodTree methodTree) { if (methodTree.throwsClauses().isEmpty()) { return methodTree.closeParenToken(); } else {//from w w w . jav a 2s . c om return getIdentifierToken(Iterables.getLast(methodTree.throwsClauses())); } }
From source file:it.anyplace.sync.bep.IndexBrowser.java
private void preloadFileInfoForCurrentPath() { logger.debug("trigger preload for folder = '{}'", folder); synchronized (preloadJobsLock) { if (preloadJobs.contains(currentPath)) { preloadJobs.remove(currentPath); preloadJobs.add(currentPath); ///add last return; // no need to trigger job } else {// w w w . j a v a 2 s. c om preloadJobs.add(currentPath); executorService.submit(new Runnable() { @Override public void run() { String preloadPath; synchronized (preloadJobsLock) { checkArgument(!preloadJobs.isEmpty()); preloadPath = Iterables.getLast(preloadJobs); //pop last job } logger.info("folder preload BEGIN for folder = '{}' path = '{}'", folder, preloadPath); getFileInfoByAbsolutePath(preloadPath); if (!PathUtils.isRoot(preloadPath)) { String parent = getParentPath(preloadPath); getFileInfoByAbsolutePath(parent); listFiles(parent); } for (FileInfo record : listFiles(preloadPath)) { if (!equal(record.getPath(), PARENT_FILE_INFO.getPath()) && record.isDirectory()) { listFiles(record.getPath()); } } logger.info("folder preload END for folder = '{}' path = '{}'", folder, preloadPath); synchronized (preloadJobsLock) { preloadJobs.remove(preloadPath); if (isCacheReady()) { logger.info("cache ready, notify listeners"); preloadJobsLock.notifyAll(); } else { logger.info("still {} job[s] left in cache loader", preloadJobs.size()); executorService.submit(this); } } } }); } } }
From source file:org.apache.gobblin.instrumented.Instrumented.java
/** * Generates a new {@link org.apache.gobblin.metrics.MetricContext} with the parent and tags taken from the reference context. * Allows replacing {@link org.apache.gobblin.metrics.Tag} with new input tags. * This method will not copy any {@link org.apache.gobblin.metrics.Metric} contained in the reference {@link org.apache.gobblin.metrics.MetricContext}. * * @param context Reference {@link org.apache.gobblin.metrics.MetricContext}. * @param newTags New {@link org.apache.gobblin.metrics.Tag} to apply to context. Repeated keys will override old tags. * @param name Name of the new {@link org.apache.gobblin.metrics.MetricContext}. * If absent or empty, will modify old name by adding a random integer at the end. * @return Generated {@link org.apache.gobblin.metrics.MetricContext}. */// w ww . j a v a 2 s . com public static MetricContext newContextFromReferenceContext(MetricContext context, List<Tag<?>> newTags, Optional<String> name) { String newName = name.orNull(); if (Strings.isNullOrEmpty(newName)) { UUID uuid = UUID.randomUUID(); String randomIdPrefix = "uuid:"; String oldName = context.getName(); List<String> splitName = Strings.isNullOrEmpty(oldName) ? Lists.<String>newArrayList() : Lists.newArrayList(Splitter.on(".").splitToList(oldName)); if (splitName.size() > 0 && StringUtils.startsWith(Iterables.getLast(splitName), randomIdPrefix)) { splitName.set(splitName.size() - 1, String.format("%s%s", randomIdPrefix, uuid.toString())); } else { splitName.add(String.format("%s%s", randomIdPrefix, uuid.toString())); } newName = Joiner.on(".").join(splitName); } MetricContext.Builder builder = context.getParent().isPresent() ? context.getParent().get().childBuilder(newName) : MetricContext.builder(newName); return builder.addTags(context.getTags()).addTags(newTags).build(); }
From source file:edu.harvard.med.screensaver.ui.libraries.LibraryCopySearchResults.java
@Override protected List<TableColumn<Copy, ?>> buildColumns() { List<TableColumn<Copy, ?>> columns = Lists.newArrayList(); columns.add(new TextEntityColumn<Copy>(Copy.library, "Library", "The library that this copy represents", TableColumn.UNGROUPED) { @Override//from w w w . ja v a 2s .co m public String getCellValue(Copy copy) { return copy.getLibrary().getLibraryName(); } @Override public boolean isCommandLink() { return true; } @Override public Object cellAction(Copy copy) { return _libraryViewer.viewEntity(copy.getLibrary()); } }); Iterables.getLast(columns).setVisible(!isNested()); columns.add(new EnumEntityColumn<Copy, ScreenType>(RelationshipPath.from(Copy.class).toProperty("library"), "Screen Type", "'RNAi' or 'Small Molecule'", TableColumn.UNGROUPED, ScreenType.values()) { @Override public ScreenType getCellValue(Copy copy) { return copy.getLibrary().getScreenType(); } }); Iterables.getLast(columns).setVisible(false); String names = Joiner.on("','").join(StringUtils.getVocabularyTerms(LibraryType.values())); columns.add(new EnumEntityColumn<Copy, LibraryType>(RelationshipPath.from(Copy.class).toProperty("library"), "Library Type", names, TableColumn.UNGROUPED, LibraryType.values()) { @Override public LibraryType getCellValue(Copy copy) { return copy.getLibrary().getLibraryType(); } }); Iterables.getLast(columns).setVisible(false); columns.add(new TextEntityColumn<Copy>(PropertyPath.from(Copy.class).toProperty("name"), "Copy Name", "The name of the the copy", TableColumn.UNGROUPED) { @Override public String getCellValue(Copy copy) { return copy.getName(); } @Override public boolean isCommandLink() { return true; } @Override public Object cellAction(Copy copy) { if (isNested()) { LibraryCopySearchResults libraryCopySearchResults = (LibraryCopySearchResults) _libraryCopyViewer .getContextualSearchResults(); libraryCopySearchResults.searchCopiesByLibrary(copy.getLibrary()); libraryCopySearchResults.findEntity(copy); return BROWSE_LIBRARY_COPIES; } return viewSelectedEntity(); } }); ((TextEntityColumn<Copy>) Iterables.getLast(columns)).addRelationshipPath(Copy.library); columns.add(new EnumEntityColumn<Copy, CopyUsageType>(PropertyPath.from(Copy.class).toProperty("usageType"), "Usage Type", "The usage type of the copy", TableColumn.UNGROUPED, CopyUsageType.values()) { @Override public CopyUsageType getCellValue(Copy copy) { return copy.getUsageType(); } }); columns.add(new TextEntityColumn<Copy>(PropertyPath.from(Copy.class).toProperty("primaryPlateLocation"), "Primary Plate Location", "The most common plate location for plates of this copy", TableColumn.UNGROUPED) { @Override public String getCellValue(Copy copy) { if (copy.getPrimaryPlateLocation() == null) { return null; } return copy.getPrimaryPlateLocation().toDisplayString(); } }); columns.add(new IntegerEntityColumn<Copy>(PropertyPath.from(Copy.class).toProperty("plateLocationsCount"), "Plate Locations", "The number different plate locations found for plates of this copy", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getPlateLocationsCount(); } }); columns.add(new EnumEntityColumn<Copy, PlateStatus>( PropertyPath.from(Copy.class).toProperty("primaryPlateStatus"), "Primary Plate Status", "The most common plate status for plates of this copy", TableColumn.UNGROUPED, PlateStatus.values()) { @Override public PlateStatus getCellValue(Copy copy) { return copy.getPrimaryPlateStatus(); } }); buildConcentrationColumns(columns); columns.add(new IntegerEntityColumn<Copy>(PropertyPath.from(Copy.class).toProperty("platesAvailable"), "Plates Available", "The number of plates with a status of \"Available\"", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getPlatesAvailable(); } }); columns.add(new FixedDecimalColumn<Copy>("Plate Screening Count Average", "The average number of times this copy's plates have been screened, ignoring replicates", TableColumn.UNGROUPED) { @Override public BigDecimal getCellValue(Copy copy) { if (copy.getScreeningStatistics().getPlateCount() == 0) return null; if (copy.getScreeningStatistics().getPlateScreeningCount() == 0) return BigDecimal.ZERO; BigDecimal val = new BigDecimal(copy.getScreeningStatistics().getPlateScreeningCount()).divide( new BigDecimal(copy.getScreeningStatistics().getPlateCount()), DECIMAL_SCALE, RoundingMode.CEILING); return val; } }); columns.add(new VolumeColumn<Copy>("Average Plate Remaining Volume", "The average well volume remaining across all library screening plates of this copy", TableColumn.UNGROUPED) { @Override public Volume getCellValue(Copy copy) { return getNullSafeVolumeStatistics(copy).getAverageRemaining(); } }); columns.add(new VolumeColumn<Copy>("Min Plate Remaining Volume", "The minimum well volume remaining across all library screening plates of this copy", TableColumn.UNGROUPED) { @Override public Volume getCellValue(Copy copy) { return getNullSafeVolumeStatistics(copy).getMinRemaining(); } }); columns.add(new VolumeColumn<Copy>("Max Plate Remaining Volume", "The maximum well volume remaining across all library screening plates of this copy", TableColumn.UNGROUPED) { @Override public Volume getCellValue(Copy copy) { return getNullSafeVolumeStatistics(copy).getMaxRemaining(); } }); columns.add(new DateColumn<Copy>("Last Date Screened", "The date the copy was last screened", TableColumn.UNGROUPED) { @Override public LocalDate getDate(Copy copy) { return copy.getScreeningStatistics().getLastDateScreened(); } }); columns.add(new DateColumn<Copy>("First Date Screened", "The date the copy was first screened", TableColumn.UNGROUPED) { @Override public LocalDate getDate(Copy copy) { return copy.getScreeningStatistics().getFirstDateScreened(); } }); columns.add( new DateEntityColumn<Copy>(PropertyPath.from(Copy.class).toProperty("datePlated"), "Date Plated", "The earliest date on which a plate of this copy was created", TableColumn.UNGROUPED) { @Override public LocalDate getDate(Copy copy) { return copy.getDatePlated(); } }); columns.add(new IntegerEntityColumn<Copy>(Copy.library.toProperty("startPlate"), "Start Plate", "The first plate number of the library", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getLibrary().getStartPlate(); } }); Iterables.getLast(columns).setVisible(!isNested()); columns.add(new IntegerEntityColumn<Copy>(Copy.library.toProperty("startPlate"), "End Plate", "The last plate number of the library", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getLibrary().getEndPlate(); } }); Iterables.getLast(columns).setVisible(!isNested()); columns.add(new IntegerEntityColumn<Copy>(Copy.library, "Library Plate Count", "The number of plates in the library", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getLibrary().getEndPlate() - copy.getLibrary().getStartPlate() + 1; } }); Iterables.getLast(columns).setVisible(false); columns.add(new IntegerColumn<Copy>("Copy Plate Count", "The number of plates in this copy", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getScreeningStatistics().getPlateCount(); } @Override public boolean isCommandLink() { return true; } @Override public Object cellAction(Copy copy) { _libraryCopyPlateSearchResults.searchPlatesForCopy(copy); return BROWSE_LIBRARY_COPY_PLATES; } }); columns.add(new IntegerColumn<Copy>("Assay Plate Count", "The number of assay plates screened for this copy", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getScreeningStatistics().getAssayPlateCount(); } }); columns.add(new IntegerColumn<Copy>("Screening Count", "The total number of times this copy has been screened, ignoring replicates", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getScreeningStatistics().getScreeningCount(); } @Override public boolean isCommandLink() { return true; } @Override public Object cellAction(Copy copy) { _activitesBrowser.searchLibraryScreeningActivitiesForCopy(copy); return BROWSE_ACTIVITIES; } }); columns.add(new IntegerColumn<Copy>("Plate Screening Count", "The total number of times individual plates from this copy have been screened, ignoring replicates", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getScreeningStatistics().getPlateScreeningCount(); } }); Iterables.getLast(columns).setVisible(false); columns.add(new IntegerColumn<Copy>("Data Loading Count", "The number of screen results loaded for screens of this copy", TableColumn.UNGROUPED) { @Override public Integer getCellValue(Copy copy) { return copy.getScreeningStatistics().getDataLoadingCount(); } }); columns.add(new DateColumn<Copy>("First Date Data Loaded", "The date of the first screen result data loading activity", TableColumn.UNGROUPED) { @Override public LocalDate getDate(Copy copy) { return copy.getScreeningStatistics().getFirstDateDataLoaded(); } }); Iterables.getLast(columns).setVisible(false); columns.add(new DateColumn<Copy>("Last Date Data Loaded", "The date of the last screen result data loading activity", TableColumn.UNGROUPED) { @Override public LocalDate getDate(Copy copy) { return copy.getScreeningStatistics().getLastDateDataLoaded(); } }); Iterables.getLast(columns).setVisible(false); return columns; }
From source file:org.atlasapi.remotesite.bbc.SlashProgrammesVersionRdf.java
public DateTime lastTransmitted() { if (broadcasts == null || broadcasts.isEmpty()) { return null; }//w ww . j ava2 s . c o m Collections.sort(broadcasts, new ByTransmissionDateComparator()); return Iterables.getLast(broadcasts).broadcastDateTime(); }
From source file:com.google.template.soy.jbcsrc.PrintDirectives.java
private static AppendableAndOptions applyStreamingPrintDirectivesTo(List<DirectiveWithArgs> directivesToApply, Expression appendable, JbcSrcPluginContext context, TemplateVariableManager variableManager) { final List<LocalVariable> closeables = new ArrayList<>(); final List<Variable> appendableVars = new ArrayList<>(); Scope scope = variableManager.enterScope(); AppendableAndOptions prev = AppendableAndOptions.create(appendable); Variable prevVar = scope.createTemporary("tmp_appendable", appendable); appendableVars.add(prevVar);//from w w w . j ava2 s . c om // Apply the directives to the appendable in reverse // since we are wrapping the directives around the appendable we need to wrap the underlying // appendable with the last directive first. so iterate in reverse order. for (DirectiveWithArgs directiveToApply : Lists.reverse(directivesToApply)) { AppendableAndOptions curr = directiveToApply.apply(context, prevVar.local()); Variable currVar = scope.createTemporary("tmp_appendable", curr.appendable()); appendableVars.add(currVar); if (curr.closeable()) { closeables.add(currVar.local()); } prev = curr; prevVar = currVar; } // Check if we need to apply a wrapper to make sure close propagates to all the right places // this is necessary if there are multiple closeable wrappers. final Expression appendableExpression; final boolean closeable; if (closeables.isEmpty()) { appendableExpression = prev.appendable(); closeable = false; } else if (closeables.size() == 1 && prev.closeable()) { // there is exactly one closeable and it is first, we don't need a wrapper appendableExpression = prev.appendable(); closeable = true; } else { // there is either more than one closeable, or it is not the first one, so we need a wrapper // We need to reverse the list of closeables so that we close them in the correct order. for // example, given '|foo|bar' we will first wrap the delegate with bar and then with foo but we // need to close foo first. appendableExpression = RUNTIME_PROPAGATE_CLOSE.invoke(Iterables.getLast(appendableVars).local(), BytecodeUtils.asImmutableList(Lists.reverse(closeables))); closeable = true; } final Statement exitScope = scope.exitScope(); Expression result = new Expression(appendableExpression.resultType()) { @Override protected void doGen(CodeBuilder adapter) { for (Variable var : appendableVars) { var.initializer().gen(adapter); } appendableExpression.gen(adapter); exitScope.gen(adapter); } }; if (closeable) { return AppendableAndOptions.createCloseable(result); } else { return AppendableAndOptions.create(result); } }