text:
package com.google.cloud.dataflow.sdk.io;

import com.google.api.client.util.Preconditions;
import com.google.cloud.dataflow.sdk.options.PipelineOptions;
import com.google.cloud.dataflow.sdk.util.IOChannelFactory;
import com.google.cloud.dataflow.sdk.util.IOChannelUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;

import org.joda.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

/**
 * A common base class for all file-based {@link Source}s. Extend this class to implement your own
 * file-based custom source.
 *
 *
A file-based {@code Source} is a {@code Source} backed by a file pattern defined as a Java
 * glob, a single file, or a offset range for a single file. See {@link OffsetBasedSource} and
 * {@link com.google.cloud.dataflow.sdk.io.range.RangeTracker} for semantics of offset ranges.
 *
 *
This source stores a {@code String} that is an {@link IOChannelFactory} specification for a
 * file or file pattern. There should be an {@code IOChannelFactory} defined for the file
 * specification provided. Please refer to {@link IOChannelUtils} and {@link IOChannelFactory} for
 * more information on this.
 *
 *
In addition to the methods left abstract from {@code BoundedSource}, subclasses must implement
 * methods to create a sub-source and a reader for a range of a single file -
 * {@link #createForSubrangeOfFile} and {@link #createSingleFileReader}. Please refer to
 * {@link XmlSource} for an example implementation of {@code FileBasedSource}.
 *
 * @param <T> Type of records represented by the source.
 */
public abstract class FileBasedSource<T> extends OffsetBasedSource<T> {
  private static final long serialVersionUID = 0;
  private static final Logger LOG = LoggerFactory.getLogger(FileBasedSource.class);
  private static final float FRACTION_OF_FILES_TO_STAT = 0.01f;

  // Package-private for testing
  static final int MAX_NUMBER_OF_FILES_FOR_AN_EXACT_STAT = 100;

  // Size of the thread pool to be used for sending requests to GCS.
  // Package-private for testing.
  static final int SPLITTING_THREAD_POOL_SIZE = 128;

  private final String fileOrPatternSpec;
  private final Mode mode;

  // Thread pool to be used for parallelizing requests to GCS.
  private static ListeningExecutorService service =
      MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(SPLITTING_THREAD_POOL_SIZE));

  /**
   * A given {@code FileBasedSource} represents a file resource of one of these types.
   */
  public enum Mode {
    FILEPATTERN,
    SINGLE_FILE_OR_SUBRANGE
  }

  /**
   * Create a {@code FileBaseSource} based on a file or a file pattern specification. This
   * constructor must be used when creating a new {@code FileBasedSource} for a file pattern.
   *
   *
 See {@link OffsetBasedSource} for a detailed description of {@code minBundleSize}.
   *
   * @param fileOrPatternSpec {@link IOChannelFactory} specification of file or file pattern
   *        represented by the {@link FileBasedSource}.
   * @param minBundleSize minimum bundle size in bytes.
   */
  public FileBasedSource(String fileOrPatternSpec, long minBundleSize) {
    super(0, Long.MAX_VALUE, minBundleSize);
    mode = Mode.FILEPATTERN;
    this.fileOrPatternSpec = fileOrPatternSpec;
  }

  /**
   * Create a {@code FileBasedSource} based on a single file. This constructor must be used when
   * creating a new {@code FileBasedSource} for a subrange of a single file.
   * Additionally, this constructor must be used to create new {@code FileBasedSource}s when
   * subclasses implement the method {@link #createForSubrangeOfFile}.
   *
   *
 See {@link OffsetBasedSource} for detailed descriptions of {@code minBundleSize},
   * {@code startOffset}, and {@code endOffset}.
   *
   * @param fileName {@link IOChannelFactory} specification of the file represented by the
   *        {@link FileBasedSource}.
   * @param minBundleSize minimum bundle size in bytes.
   * @param startOffset starting byte offset.
   * @param endOffset ending byte offset. If the specified value {@code >= #getMaxEndOffset()} it
   *        implies {@code #getMaxEndOffSet()}.
   */
  public FileBasedSource(String fileName, long minBundleSize,
      long startOffset, long endOffset) {
    super(startOffset, endOffset, minBundleSize);
    mode = Mode.SINGLE_FILE_OR_SUBRANGE;
    this.fileOrPatternSpec = fileName;
  }

  public final String getFileOrPatternSpec() {
    return fileOrPatternSpec;
  }

  public final Mode getMode() {
    return mode;
  }

  @Override
  public final FileBasedSource<T> createSourceForSubrange(long start, long end) {
    Preconditions.checkArgument(mode != Mode.FILEPATTERN,
        "Cannot split a file pattern based source based on positions");
    Preconditions.checkArgument(start >= getStartOffset(), "Start offset value " + start
        + " of the subrange cannot be smaller than the start offset value " + getStartOffset()
        + " of the parent source");
    Preconditions.checkArgument(end <= getEndOffset(), "End offset value " + end
        + " of the subrange cannot be larger than the end offset value " + getEndOffset()
        + " of the parent source");

    FileBasedSource<T> source = createForSubrangeOfFile(fileOrPatternSpec, start, end);
    if (start > 0 || end != Long.MAX_VALUE) {
      Preconditions.checkArgument(source.getMode() == Mode.SINGLE_FILE_OR_SUBRANGE,
          "Source created for the range [" + start + "," + end + ")"
          + " must be a subrange source");
    }
    return source;
  }

  /**
   * Creates and returns a new {@code FileBasedSource} of the same type as the current
   * {@code FileBasedSource} backed by a given file and an offset range. When current source is
   * being split, this method is used to generate new sub-sources. When creating the source
   * subclasses must call the constructor {@link #FileBasedSource(String, long, long, long)} of
   * {@code FileBasedSource} with corresponding parameter values passed here.
   *
   * @param fileName file backing the new {@code FileBasedSource}.
   * @param start starting byte offset of the new {@code FileBasedSource}.
   * @param end ending byte offset of the new {@code FileBasedSource}. May be Long.MAX_VALUE,
   *        in which case it will be inferred using {@link #getMaxEndOffset}.
   */
  public abstract FileBasedSource<T> createForSubrangeOfFile(String fileName, long start, long end);

  /**
   * Creates and returns an instance of a {@code FileBasedReader} implementation for the current
   * source assuming the source represents a single file. File patterns will be handled by
   * {@code FileBasedSource} implementation automatically.
   */
  public abstract FileBasedReader<T> createSingleFileReader(PipelineOptions options);

  @Override
  public final long getEstimatedSizeBytes(PipelineOptions options) throws Exception {
    // This implementation of method getEstimatedSizeBytes is provided to simplify subclasses. Here
    // we perform the size estimation of files and file patterns using the interface provided by
    // IOChannelFactory.

    IOChannelFactory factory = IOChannelUtils.getFactory(fileOrPatternSpec);
    if (mode == Mode.FILEPATTERN) {
      // TODO Implement a more efficient parallel/batch size estimation mechanism for file patterns.
      long startTime = System.currentTimeMillis();
      long totalSize = 0;
      Collection<String> inputs = factory.match(fileOrPatternSpec);
      if (inputs.size() <= MAX_NUMBER_OF_FILES_FOR_AN_EXACT_STAT) {
        totalSize = getExactTotalSizeOfFiles(inputs, factory);
        LOG.debug("Size estimation of all files of pattern " + fileOrPatternSpec + " took "
           + (System.currentTimeMillis() - startTime) + " ms");
      } else {
        totalSize = getEstimatedSizeOfFilesBySampling(inputs, factory);
        LOG.debug("Size estimation of pattern " + fileOrPatternSpec + " by sampling took "
           + (System.currentTimeMillis() - startTime) + " ms");
      }
      return totalSize;
    } else {
      long start = getStartOffset();
      long end = Math.min(getEndOffset(), getMaxEndOffset(options));
      return end - start;
    }
  }

  // Get the exact total size of the given set of files.
  private static long getExactTotalSizeOfFiles(
      Collection<String> files, IOChannelFactory ioChannelFactory) throws IOException {
    long totalSize = 0;
    for (String file : files) {
      totalSize += ioChannelFactory.getSizeBytes(file);
    }
    return totalSize;
  }

  // Estimate the total size of the given set of files through sampling and extrapolation.
  // Currently we use uniform sampling which requires a linear sampling size for a reasonable
  // estimate.
  // TODO: Implement a more efficient sampling mechanism.
  private static long getEstimatedSizeOfFilesBySampling(
      Collection<String> files, IOChannelFactory ioChannelFactory) throws IOException {
    int sampleSize = (int) (FRACTION_OF_FILES_TO_STAT * files.size());
    sampleSize = Math.max(MAX_NUMBER_OF_FILES_FOR_AN_EXACT_STAT, sampleSize);

    List<String> selectedFiles = new ArrayList<String>(files);
    Collections.shuffle(selectedFiles);
    selectedFiles = selectedFiles.subList(0, sampleSize);

    return files.size() * getExactTotalSizeOfFiles(selectedFiles, ioChannelFactory)
        / selectedFiles.size();
  }

  private ListenableFuture<List<? extends FileBasedSource<T>>> createFuture(final String file,
      final long desiredBundleSizeBytes, final PipelineOptions options,
      ListeningExecutorService service) {
    return service.submit(new Callable<List<? extends FileBasedSource<T>>>() {
      @Override
      public List<? extends FileBasedSource<T>> call() throws Exception {
        return createForSubrangeOfFile(file, 0, Long.MAX_VALUE)
            .splitIntoBundles(desiredBundleSizeBytes, options);
      }
    });
  }

  @Override
  public final List<? extends FileBasedSource<T>> splitIntoBundles(
      long desiredBundleSizeBytes, PipelineOptions options) throws Exception {
    // This implementation of method splitIntoBundles is provided to simplify subclasses. Here we
    // split a FileBasedSource based on a file pattern to FileBasedSources based on full single
    // files. For files that can be efficiently seeked, we further split FileBasedSources based on
    // those files to FileBasedSources based on sub ranges of single files.

    if (mode == Mode.FILEPATTERN) {
      long startTime = System.currentTimeMillis();
      List<ListenableFuture<List<? extends FileBasedSource<T>>>> futures = new ArrayList<>();

      for (final String file : FileBasedSource.expandFilePattern(fileOrPatternSpec)) {
        futures.add(createFuture(file, desiredBundleSizeBytes, options, service));
      }
      List<? extends FileBasedSource<T>> splitResults =
          ImmutableList.copyOf(Iterables.concat(Futures.allAsList(futures).get()));

      LOG.debug("Splitting the source based on file pattern " + fileOrPatternSpec + " took "
          + (System.currentTimeMillis() - startTime) + " ms");
      return splitResults;
    } else {
      if (isSplittable()) {
        List<FileBasedSource<T>> splitResults = new ArrayList<>();
        for (OffsetBasedSource<T> split :
            super.splitIntoBundles(desiredBundleSizeBytes, options)) {
          splitResults.add((FileBasedSource<T>) split);
        }
        return splitResults;
      } else {
        LOG.debug("The source for file " + fileOrPatternSpec
            + " is not split into sub-range based sources since the file is not seekable");
        return ImmutableList.of(this);
      }
    }
  }

  /**
   * Determines whether a file represented by this source is can be split into bundles.
   *
   *
By default, a file is splittable if it is on a file system that supports efficient read
   * seeking. Subclasses may override to provide different behavior.
   */
  protected boolean isSplittable() throws Exception {
    // We split a file-based source into subranges only if the file is efficiently seekable.
    // If a file is not efficiently seekable it would be highly inefficient to create and read a
    // source based on a subrange of that file.
    IOChannelFactory factory = IOChannelUtils.getFactory(fileOrPatternSpec);
    return factory.isReadSeekEfficient(fileOrPatternSpec);
  }

  @Override
  public final BoundedReader<T> createReader(PipelineOptions options) throws IOException {
    // Validate the current source prior to creating a reader for it.
    this.validate();

    if (mode == Mode.FILEPATTERN) {
      long startTime = System.currentTimeMillis();
      Collection<String> files = FileBasedSource.expandFilePattern(fileOrPatternSpec);
      List<FileBasedReader<T>> fileReaders = new ArrayList<>();
      for (String fileName : files) {
        long endOffset;
        try {
          endOffset = IOChannelUtils.getFactory(fileName).getSizeBytes(fileName);
        } catch (IOException e) {
          LOG.warn("Failed to get size of " + fileName, e);
          endOffset = Long.MAX_VALUE;
        }
        fileReaders.add(
            createForSubrangeOfFile(fileName, 0, endOffset).createSingleFileReader(options));
      }
      LOG.debug("Creating a reader for file pattern " + fileOrPatternSpec + " took "
          + (System.currentTimeMillis() - startTime) + " ms");
      return new FilePatternReader(this, fileReaders);
    } else {
      return createSingleFileReader(options);
    }
  }

  @Override
  public String toString() {
    switch (mode) {
      case FILEPATTERN:
        return fileOrPatternSpec;
      case SINGLE_FILE_OR_SUBRANGE:
        return fileOrPatternSpec + " range " + super.toString();
      default:
        throw new IllegalStateException("Unexpected mode: " + mode);
    }
  }

  @Override
  public void validate() {
    super.validate();
    switch (mode) {
      case FILEPATTERN:
        Preconditions.checkArgument(getStartOffset() == 0,
            "FileBasedSource is based on a file pattern or a full single file "
            + "but the starting offset proposed " + getStartOffset() + " is not zero");
        Preconditions.checkArgument(getEndOffset() == Long.MAX_VALUE,
            "FileBasedSource is based on a file pattern or a full single file "
            + "but the ending offset proposed " + getEndOffset() + " is not Long.MAX_VALUE");
        break;
      case SINGLE_FILE_OR_SUBRANGE:
        // Nothing more to validate.
        break;
      default:
        throw new IllegalStateException("Unknown mode: " + mode);
    }
  }

  @Override
  public final long getMaxEndOffset(PipelineOptions options) throws Exception {
    if (mode == Mode.FILEPATTERN) {
      throw new IllegalArgumentException("Cannot determine the exact end offset of a file pattern");
    }
    if (getEndOffset() == Long.MAX_VALUE) {
      IOChannelFactory factory = IOChannelUtils.getFactory(fileOrPatternSpec);
      return factory.getSizeBytes(fileOrPatternSpec);
    } else {
      return getEndOffset();
    }
  }

  private static Collection<String> expandFilePattern(String fileOrPatternSpec) throws IOException {
    IOChannelFactory factory = IOChannelUtils.getFactory(fileOrPatternSpec);
    Collection<String> matches = factory.match(fileOrPatternSpec);
    LOG.info("Matched {} files for pattern {}", matches.size(), fileOrPatternSpec);
    return matches;
  }

  /**
   * A {@link Source.Reader reader} that implements code common to readers of
   * {@code FileBasedSource}s.
   *
   *
Seekability

   *
   *
This reader uses a {@link ReadableByteChannel} created for the file represented by the
   * corresponding source to efficiently move to the correct starting position defined in the
   * source. Subclasses of this reader should implement {@link #startReading} to get access to this
   * channel. If the source corresponding to the reader is for a subrange of a file the
   * {@code ReadableByteChannel} provided is guaranteed to be an instance of the type
   * {@link SeekableByteChannel}, which may be used by subclass to traverse back in the channel to
   * determine the correct starting position.
   *
   *
Reading Records

   *
   *
Sequential reading is implemented using {@link #readNextRecord}.
   *
   *
Then {@code FileBasedReader} implements "reading a range [A, B)" in the following way.
   *

   *
{@link #start} opens the file
   *
{@link #start} seeks the {@code SeekableByteChannel} to A (reading offset ranges for
   * non-seekable files is not supported) and calls {@code startReading()}
   *
{@link #start} calls {@link #advance} once, which, via {@link #readNextRecord},
   * locates the first record which is at a split point AND its offset is at or after A.
   * If this record is at or after B, {@link #advance} returns false and reading is finished.
   *
if the previous advance call returned {@code true} sequential reading starts and
   * {@code advance()} will be called repeatedly
   *

   * {@code advance()} calls {@code readNextRecord()} on the subclass, and stops (returns false) if
   * the new record is at a split point AND the offset of the new record is at or after B.
   *
   *
Thread Safety

   *
   *
 Since this class implements {@link Source.Reader} it guarantees thread safety. Abstract
   * methods defined here will not be accessed by more than one thread concurrently.
   */
  public abstract static class FileBasedReader<T> extends OffsetBasedReader<T> {
    private ReadableByteChannel channel = null;

    /**
     * Subclasses should not perform IO operations at the constructor. All IO operations should be
     * delayed until the {@link #startReading} method is invoked.
     */
    public FileBasedReader(FileBasedSource<T> source) {
      super(source);
      Preconditions.checkArgument(source.getMode() != Mode.FILEPATTERN,
          "FileBasedReader does not support reading file patterns");
    }

    @Override
    public FileBasedSource<T> getCurrentSource() {
      return (FileBasedSource<T>) super.getCurrentSource();
    }

    @Override
    protected final boolean startImpl() throws IOException {
      FileBasedSource<T> source = getCurrentSource();
      IOChannelFactory factory = IOChannelUtils.getFactory(source.getFileOrPatternSpec());
      this.channel = factory.open(source.getFileOrPatternSpec());

      if (channel instanceof SeekableByteChannel) {
        SeekableByteChannel seekChannel = (SeekableByteChannel) channel;
        seekChannel.position(source.getStartOffset());
      } else {
        // Channel is not seekable. Must not be a subrange.
        Preconditions.checkArgument(source.mode != Mode.SINGLE_FILE_OR_SUBRANGE,
            "Subrange-based sources must only be defined for file types that support seekable "
            + " read channels");
        Preconditions.checkArgument(source.getStartOffset() == 0, "Start offset "
            + source.getStartOffset()
            + " is not zero but channel for reading the file is not seekable.");
      }

      startReading(channel);

      // Advance once to load the first record.
      return advanceImpl();
    }

    @Override
    protected final boolean advanceImpl() throws IOException {
      return readNextRecord();
    }

    /**
     * Closes any {@link ReadableByteChannel} created for the current reader. This implementation is
     * idempotent. Any {@code close()} method introduced by a subclass must be idempotent and must
     * call the {@code close()} method in the {@code FileBasedReader}.
     */
    @Override
    public void close() throws IOException {
      if (channel != null) {
        channel.close();
      }
    }

    /**
     * Performs any initialization of the subclass of {@code FileBasedReader} that involves IO
     * operations. Will only be invoked once and before that invocation the base class will seek the
     * channel to the source's starting offset.
     *
     *
Provided {@link ReadableByteChannel} is for the file represented by the source of this
     * reader. Subclass may use the {@code channel} to build a higher level IO abstraction, e.g., a
     * BufferedReader or an XML parser.
     *
     *
If the corresponding source is for a subrange of a file, {@code channel} is guaranteed to
     * be an instance of the type {@link SeekableByteChannel}.
     *
     *
After this method is invoked the base class will not be reading data from the channel or
     * adjusting the position of the channel. But the base class is responsible for properly closing
     * the channel.
     *
     * @param channel a byte channel representing the file backing the reader.
     */
    protected abstract void startReading(ReadableByteChannel channel) throws IOException;

    /**
     * Reads the next record from the channel provided by {@link #startReading}. Methods
     * {@link #getCurrent}, {@link #getCurrentOffset}, and {@link #isAtSplitPoint()} should return
     * the corresponding information about the record read by the last invocation of this method.
     *
     *
Note that this method will be called the same way for reading the first record in the
     * source (file or offset range in the file) and for reading subsequent records. It is up to the
     * subclass to do anything special for locating and reading the first record, if necessary.
     *
     * @return {@code true} if a record was successfully read, {@code false} if the end of the
     *         channel was reached before successfully reading a new record.
     */
    protected abstract boolean readNextRecord() throws IOException;
  }

  // An internal Reader implementation that concatenates a sequence of FileBasedReaders.
  private class FilePatternReader extends BoundedReader<T> {
    private final FileBasedSource<T> source;
    private final List<FileBasedReader<T>> fileReaders;
    final ListIterator<FileBasedReader<T>> fileReadersIterator;
    FileBasedReader<T> currentReader = null;

    public FilePatternReader(FileBasedSource<T> source, List<FileBasedReader<T>> fileReaders) {
      this.source = source;
      this.fileReaders = fileReaders;
      this.fileReadersIterator = fileReaders.listIterator();
    }

    @Override
    public boolean start() throws IOException {
      return startNextNonemptyReader();
    }

    @Override
    public boolean advance() throws IOException {
      Preconditions.checkState(currentReader != null, "Call start() before advance()");
      if (currentReader.advance()) {
        return true;
      }
      return startNextNonemptyReader();
    }

    private boolean startNextNonemptyReader() throws IOException {
      while (fileReadersIterator.hasNext()) {
        currentReader = fileReadersIterator.next();
        if (currentReader.start()) {
          return true;
        }
        currentReader.close();
      }
      return false;
    }

    @Override
    public T getCurrent() throws NoSuchElementException {
      // A NoSuchElement will be thrown by the last FileBasedReader if getCurrent() is called after
      // advance() returns false.
      return currentReader.getCurrent();
    }

    @Override
    public Instant getCurrentTimestamp() throws NoSuchElementException {
      // A NoSuchElement will be thrown by the last FileBasedReader if getCurrentTimestamp()
      // is called after advance() returns false.
      return currentReader.getCurrentTimestamp();
    }

    @Override
    public void close() throws IOException {
      // Close all readers that may have not yet been closed.
      // If this reader has not been started, currentReader is null.
      if (currentReader != null) {
        currentReader.close();
      }
      while (fileReadersIterator.hasNext()) {
        fileReadersIterator.next().close();
      }
    }

    @Override
    public FileBasedSource<T> getCurrentSource() {
      return source;
    }

    @Override
    public FileBasedSource<T> splitAtFraction(double fraction) {
      // Unsupported. TODO: implement.
      LOG.debug("Dynamic splitting of FilePatternReader is unsupported.");
      return null;
    }

    @Override
    public Double getFractionConsumed() {
      if (currentReader == null) {
        return 0.0;
      }
      if (fileReaders.isEmpty()) {
        return 1.0;
      }
      int index = fileReadersIterator.previousIndex();
      int numReaders = fileReaders.size();
      if (index == numReaders) {
        return 1.0;
      }
      double before = 1.0 * index / numReaders;
      double after = 1.0 * (index + 1) / numReaders;
      Double fractionOfCurrentReader = currentReader.getFractionConsumed();
      if (fractionOfCurrentReader == null) {
        return before;
      }
      return before + fractionOfCurrentReader * (after - before);
    }
  }
}


text:
<?xml version='1.0'?>
<highlighters>

<highlighter type='multiline-comment'>
  <start>{-</start>
  <end>-}</end>
</highlighter>

<highlighter type='oneline-comment'>
--
</highlighter>

<highlighter type='string'>
  <style>literal</style>
  <string>"</string>
  <escape>\</escape>
  <spanNewLines/>
</highlighter>

<highlighter type="number">
  <style>literal</style>
  <point>.</point>
  <exponent>e</exponent>
  <ignoreCase />
</highlighter>

<highlighter type='keywords'>
  <style>literal</style>
  <keyword>true</keyword>
  <keyword>null</keyword>
  <keyword>false</keyword>
</highlighter>

<highlighter type='keywords'>
  <keyword>as</keyword>
  <keyword>def</keyword>
  <keyword>else</keyword>
  <keyword>if</keyword>
  <keyword>import</keyword>
  <keyword>include</keyword>
  <keyword>lambda</keyword>
  <keyword>signal</keyword>
  <keyword>stop</keyword>
  <keyword>then</keyword>
  <keyword>type</keyword>
  <keyword>val</keyword>
</highlighter>

<!-- operators -->
<highlighter type='regex'>
  <style>operator</style>
  <pattern><![CDATA[\|\||<=|>=|<:|:>|:=|\?|-|~|\*\*|\*|/|%|:|=|/=|&&|\+]]></pattern>
</highlighter>

<highlighter type='regex'>
  <style>combinator</style>
  <pattern><![CDATA[(?<=\s)(<|>)((?=\S)|$)|((?<=\S)|^)(<|>)(?=\s([^=]|$))|\||;|\bFATBAR\b]]></pattern>
</highlighter>

<!-- site calls -->
<highlighter type='regex'>
  <style>site</style>
  <pattern>\b\w+\b(?=\s*[(\[])</pattern>
</highlighter>

<highlighter type='regex'>
  <style>variable</style>
  <pattern>\b\w+\b</pattern>
</highlighter>

</highlighters>

redpajama_set_name: RedPajamaGithub


text:
package org.jetbrains.plugins.scala.annotator.createFromUsage

import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import org.jetbrains.plugins.scala.ScalaBundle
import org.jetbrains.plugins.scala.extensions.PsiElementExt
import org.jetbrains.plugins.scala.lang.psi.api.expr.ScReferenceExpression
import org.jetbrains.plugins.scala.lang.psi.api.statements.ScFunctionDefinition
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.ScClass
import org.jetbrains.plugins.scala.lang.refactoring.introduceParameter.ScalaIntroduceParameterHandler

final class CreateParameterQuickFix(ref: ScReferenceExpression) extends CreateFromUsageQuickFixBase(ref) {
  override def getText: String = ScalaBundle.message("create.parameter.named", ref.nameId.getText)

  override def getFamilyName: String = ScalaBundle.message("family.name.create.parameter")

  override def isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean =
    super.isAvailable(project, editor, file) &&
      ref.qualifier.isEmpty &&
      ref.parentOfType(Seq(classOf[ScFunctionDefinition], classOf[ScClass])).isDefined

  override protected def invokeInner(project: Project, editor: Editor, file: PsiFile): Unit = {
    val handler = new ScalaIntroduceParameterHandler
    editor.getSelectionModel.setSelection(ref.startOffset, ref.endOffset)

    val dataContext = editor match {
      case e: EditorEx => e.getDataContext
      case _ => DataContext.EMPTY_CONTEXT
    }

    handler.invoke(file)(project, editor, dataContext)
  }

  // TODO: Add preview (SCL-20398)
  override def generatePreview(project: Project, editor: Editor, file: PsiFile): IntentionPreviewInfo =
    IntentionPreviewInfo.EMPTY
}


text:
package keycache

import (
	"sync"
	"time"

	"github.com/grafana/metrictank/schema"
)

// SubKey is the last 15 bytes of a 16 byte Key
// We can track Key-identified metrics with a SubKey because
// we shard by the first byte of the Key.
type SubKey [15]byte

// Shard tracks for each SubKey when it was last seen
// we know the last seen timestamp with ~10 minute precision
// because all SubKey's Duration's are relative to the ref
type Shard struct {
	sync.Mutex
	ref  Ref
	data map[SubKey]Duration
}

// NewShard creates a new shard
func NewShard(ref Ref) Shard {
	return Shard{
		ref:  ref,
		data: make(map[SubKey]Duration),
	}
}

// Touch marks the key as seen and returns whether it was seen before
// callers should assure that t >= ref and t-ref <= 42 hours
func (s *Shard) Touch(key schema.Key, t time.Time) bool {
	var sub SubKey
	copy(sub[:], key[1:])
	s.Lock()
	_, ok := s.data[sub]
	s.data[sub] = NewDuration(s.ref, t)
	s.Unlock()
	return ok
}

// Len returns the length of the shard
func (s *Shard) Len() int {
	s.Lock()
	l := len(s.data)
	s.Unlock()
	return l
}

// Prune removes stale entries from the shard.
// for this to work effectively,
// call this with a frequency > 10 min and < 42 hours
func (s *Shard) Prune(now time.Time, cutoff Duration) int {

	s.Lock()
	defer s.Unlock()

	// establish the new reference.
	// any values older will be pruned
	// any values newer or equal will have their duration adjusted relative to newRef
	newref := NewRef(now) - Ref(cutoff)

	// in this case, nothing we can do.
	// this happens when:
	// caller prunes too often (more frequently than every 10 minutes)
	// clock was adjusted and we went back in time
	// the cutoff has increased from one call to the next
	if newref <= s.ref {
		return len(s.data)
	}

	// if we went further ahead in time than our bookkeeping resolution
	// prune everything
	// this happens when:
	// clock jumps ahead
	// missed ticker reads
	// poorly configured prune interval
	if newref > s.ref+255 {
		s.data = make(map[SubKey]Duration)
		return 0
	}

	// now that we know for sure that s.ref < newref <= s.ref+255
	// or 0 < newref - s.ref <= 255                                                     (1)
	// we can do precise pruning

	// the amount to subtract of a duration for it to be based on the new reference
	subtract := Duration(newref - s.ref)

	for subkey, duration := range s.data {
		// remove entry if it is too old, e.g. if:
		// newref > "timestamp of the entry in 10minutely buckets"
		// newref > s.ref + duration                                                (2)
		if newref > s.ref+Ref(duration) {
			delete(s.data, subkey)
			continue
		}

		// adjust the duration to be based on the new reference
		// for this to be correct we must assert that there is no underflow,
		// ie. that: duration - subtract >= 0
		// because of (2) we know that:
		// newref <= s.ref+duration
		// iow duration >= newref - s.ref
		// iow duration >= subtract
		// iow duration - bustract >=0 (QED)
		s.data[subkey] = duration - subtract
	}
	s.ref = newref
	return len(s.data)
}


text:
import os
import re
from setuptools import setup

setup_dir = os.path.dirname(__file__)

with open(os.path.join(setup_dir, 'varsity.py'), 'rb') as f:
    version = re.search(r'^__version__ = \'(\d+\.(?:\d+\.)*\d+)\'', f.read().decode('utf8'), re.M).group(1)

setup(
    name='varsity',
    version=version,
    author='Brent Tubbs',
    author_email='brent.tubbs@gmail.com',
    url='http://github.com/btubbs/varsity',
    description=('A library for defining, parsing, and validating settings '
                 'passed as environment variables'),
    long_description=open('README.rst').read(),
    py_modules=['varsity'],
    include_package_data=True,
    zip_safe=False,
    license='BSD',
    install_requires=['attrdict'],
    classifiers=[
        'Development Status :: 4 - Beta',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.5',
    ],
)


text:
import re,urlparse,json,xbmcgui
from liveresolver.modules import client
from liveresolver.modules.log_utils import log

def resolve(url):
    try:
        if '/vod/' in url:
            url = re.compile('/(\d+)').findall(url)[-1]
            url = 'http://www.filmon.com/vod/info/%s' % url
        elif '/tv/' in url:
            url = url.replace('/tv/', '/channel/')
        elif not '/channel/' in url:
            raise Exception()

        headers = {'X-Requested-With': 'XMLHttpRequest'}

        log('Filmon: Getting cookie...')
        cookie = client.request(url, output='cookie')

        log('Filmon: Getting channel id...')
        cid = client.request(url, headers=headers)
        cid = json.loads(cid)['id']

        headers = {'X-Requested-With': 'XMLHttpRequest', 'Referer': url}

        url = 'http://www.filmon.com/ajax/getChannelInfo?channel_id=%s' % cid
        log('Filmon: Getting streams...')
        result = client.request(url, cookie=cookie, headers=headers)

        result = json.loads(result)
        try:
            result = result['streams']
        except:
            result = result['data']['streams']
            result = [i[1] for i in result.items()]

        log('Filmon: Selecting stream url...')
        url = [(i['url'], int(i['watch-timeout'])) for i in result]
        url = [i for i in url if '.m3u8' in i[0]]

        url.sort()
        url = url[-1][0]
        return url
    except:
        return


text:
<!doctype html>

    <title>WebGL Demos</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

samples.html

samples2.html

hyperbolic.html

surface.html

explicit.html

ico.html

quadric.html

cubic.html

inversion.html

clifford.html


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Folia geobot. phytotax. 16(2): 210 (1981)

#### Original name
Sporidesmium doliiforme Minter & Hol.-Jech., 1981

### Remarks
null


text:
import { SourceType } from 'coffee-lex';
import SourceToken from 'coffee-lex/dist/SourceToken';
import NodePatcher from '../../../patchers/NodePatcher';
import { PatcherContext } from '../../../patchers/types';
import notNull from '../../../utils/notNull';
import BlockPatcher from './BlockPatcher';
import BreakPatcher from './BreakPatcher';

export default class SwitchCasePatcher extends NodePatcher {
  conditions: Array<NodePatcher>;
  consequent: NodePatcher | null;

  negated: boolean;

  constructor(patcherContext: PatcherContext, conditions: Array<NodePatcher>, consequent: NodePatcher) {
    super(patcherContext);
    this.conditions = conditions;
    this.consequent = consequent;
    this.negated = false;
  }

  initialize(): void {
    this.conditions.forEach((condition) => condition.setRequiresExpression());
  }

  patchAsStatement(): void {
    const lastCondition = this.conditions[this.conditions.length - 1];

    // `when a, b, c then d` → `a, b, c then d`
    //  ^^^^^
    const whenToken = this.getWhenToken();
    this.remove(whenToken.start, this.conditions[0].outerStart);

    // `a, b, c then d` → `a b c then d`
    //   ^  ^
    this.getCommaTokens().forEach((comma) => {
      this.remove(comma.start, comma.end);
    });

    this.conditions.forEach((condition) => {
      // `a b c then d` → `case a: case b: case c: then d`
      //                   ^^^^^ ^^^^^^^ ^^^^^^^ ^
      this.insert(condition.outerStart, 'case ');
      if (this.negated) {
        condition.negate();
      }
      condition.patch({ leftBrace: false, rightBrace: false });
      this.insert(condition.outerEnd, ':');
    });

    // `case a: case b: case c: then d → `case a: case b: case c: d`
    //                          ^^^^^
    const thenToken = this.getThenToken();
    if (thenToken) {
      if (this.consequent !== null) {
        this.remove(thenToken.start, this.consequent.outerStart);
      } else {
        this.remove(lastCondition.outerEnd, thenToken.end);
      }
    }

    if (this.consequent !== null) {
      this.consequent.patch({ leftBrace: false, rightBrace: false });
    }

    const implicitReturnWillBreak =
      this.implicitlyReturns() &&
      this.implicitReturnPatcher().implicitReturnWillBreak() &&
      (!this.consequent || this.consequent.allCodePathsPresent());
    const shouldAddBreak = !this.hasExistingBreak() && !implicitReturnWillBreak;
    if (shouldAddBreak) {
      if (thenToken) {
        // `case a: case b: case c: then d → `case a: case b: case c: d break`
        //                                                             ^^^^^^
        if (this.consequent !== null) {
          this.insert(this.consequent.contentEnd, ' break');
        } else {
          this.insert(lastCondition.outerEnd, `\n${this.getIndent(1)}break`);
        }
      } else {
        this.appendLineAfter('break', 1);
      }
    }
  }

  setImplicitlyReturns(): void {
    super.setImplicitlyReturns();
    if (this.consequent !== null) {
      this.consequent.setImplicitlyReturns();
    }
  }

  patchAsExpression(): void {
    this.patchAsStatement();
  }

  /**
   * Don't actually negate the conditions until just before patching, since
   * otherwise we might accidentally overwrite a ! character that gets inserted.
   */
  negate(): void {
    this.negated = !this.negated;
  }

  /**
   * @private
   */
  getWhenToken(): SourceToken {
    const whenToken = this.sourceTokenAtIndex(this.contentStartTokenIndex);
    if (!whenToken) {
      throw this.error(`bad token index for start of 'when'`);
    }
    if (whenToken.type !== SourceType.WHEN) {
      throw this.error(`unexpected ${SourceType[whenToken.type]} at start of 'switch' case`);
    }
    return whenToken;
  }

  /**
   * @private
   */
  getCommaTokens(): Array<SourceToken> {
    const result: Array<SourceToken> = [];
    for (let i = 1; i < this.conditions.length; i++) {
      const left = this.conditions[i - 1];
      const right = this.conditions[i];
      const commaIndex = this.indexOfSourceTokenBetweenPatchersMatching(
        left,
        right,
        (token) => token.type === SourceType.COMMA
      );
      if (!commaIndex) {
        throw this.error(`unable to find comma between 'when' conditions`, left.contentEnd, right.contentStart);
      }
      result.push(notNull(this.sourceTokenAtIndex(commaIndex)));
    }
    return result;
  }

  /**
   * @private
   */
  hasExistingBreak(): boolean {
    if (!(this.consequent instanceof BlockPatcher)) {
      return false;
    }
    const lastStatement = this.consequent.statements[this.consequent.statements.length - 1];
    return lastStatement && lastStatement instanceof BreakPatcher;
  }

  /**
   * Gets the token representing the `then` between condition and consequent.
   *
   * @private
   */
  getThenToken(): SourceToken | null {
    const thenTokenIndex = this.indexOfSourceTokenBetweenSourceIndicesMatching(
      this.conditions[0].outerEnd,
      this.consequent !== null ? this.consequent.outerStart : this.contentEnd,
      (token) => token.type === SourceType.THEN
    );
    if (thenTokenIndex) {
      return this.sourceTokenAtIndex(thenTokenIndex);
    }
    // In some cases, the node bounds are wrong and the `then` is after our
    // current node, so just use that.
    const nextToken = this.nextSemanticToken();
    if (nextToken && nextToken.type === SourceType.THEN) {
      return nextToken;
    }
    return null;
  }
}


text:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Serialization.Formatters;
using System.Threading;

namespace GitMind.Utils.Ipc
{
	internal class IpcRemotingService : IDisposable
	{
		private string uniqueId;
		private Mutex channelMutex;
		private IpcServerChannel ipcServerChannel;
		private IpcClientChannel ipcClientChannel;

		public bool TryCreateServer(string serverId)
		{
			uniqueId = serverId;
			string mutexName = GetId(serverId);
			string channelName = GetChannelName(serverId);

			channelMutex = new Mutex(true, mutexName, out bool isMutexCreated);
			if (isMutexCreated)
			{
				CreateIpcServer(channelName);
			}

			return isMutexCreated;
		}

		public void PublishService(IpcService ipcService)
		{
			Asserter.Requires(ipcServerChannel != null);

			// Publish the ipc service receiving the data
			string ipcServiceName = uniqueId + ipcService.GetType().FullName;
			RemotingServices.Marshal(ipcService, ipcServiceName);
		}

		public void CallService<TRemoteService>(
			string serverId, Action<TRemoteService> serviceAction)
		{
			TRemoteService ipcProxy = CreateClientProxy<TRemoteService>(serverId);

			serviceAction(ipcProxy);
		}

		public TResult CallService<TRemoteService, TResult>(
			string serverId, Func<TRemoteService, TResult> serviceFunction)
		{
			TRemoteService ipcProxy = CreateClientProxy<TRemoteService>(serverId);

			return serviceFunction(ipcProxy);
		}

		public void Dispose()
		{
			try
			{
				if (channelMutex != null)
				{
					channelMutex.Close();
					channelMutex = null;
				}

				if (ipcServerChannel != null)
				{
					ChannelServices.UnregisterChannel(ipcServerChannel);
					ipcServerChannel = null;
				}
			}
			catch (Exception e) when (e.IsNotFatal())
			{
				Log.Exception(e, "Failed to close RPC remoting service");
			}
		}

		private void CreateIpcServer(string channelName)
		{
			BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
			serverProvider.TypeFilterLevel = TypeFilterLevel.Full;

			IDictionary properties = new Dictionary<string, string>();
			properties["name"] = channelName;
			properties["portName"] = channelName;
			properties["exclusiveAddressUse"] = "false";

			ipcServerChannel = new IpcServerChannel(properties, serverProvider);
			ChannelServices.RegisterChannel(ipcServerChannel, true);
		}

		private T CreateClientProxy<T>(string id)
		{
			string channelName = GetChannelName(id);

			if (ipcClientChannel == null)
			{
				ipcClientChannel = new IpcClientChannel();

				ChannelServices.RegisterChannel(ipcClientChannel, true);
			}

			string ipcServiceName = id + typeof(T).FullName;
			string ipcUrl = $"ipc://{channelName}/{ipcServiceName}";

			// Get proxy instance of rpc service instance published by server in PublishService()
			T ipcProxy = (T)RemotingServices.Connect(typeof(T), ipcUrl);

			if (ipcProxy == null)
			{
				Log.Error($"Failed to makeIPC call {channelName}");
			}

			return ipcProxy;
		}

		private static string GetChannelName(string uniqueName) => $"{GetId(uniqueName)}:rpc";

		private static string GetId(string uniqueName) => uniqueName + Environment.UserName;
	}
}


text:
@interface sideModel : NSObject
@property (nonatomic,strong)NSString* site;
@property (nonatomic,strong)NSString* waiting;
@property (nonatomic,strong)NSString* group;
@property (nonatomic,strong)NSString* name;
@property (nonatomic,strong)NSString* size;
@property (nonatomic,strong)NSString* count;
@property (nonatomic,strong)NSString* source;
@property (nonatomic,strong)NSString* magnet;
@property (nonatomic,strong)NSString* mark;
@end


text:
title:  "Side Project: Desarrollo de aplicación web con React y Leaflet (IV). Datos de servicios sanitarios desde WFS"
excerpt_separator: "<!--more-->"
comments: true
related: true
header:
  teaser: "/images/blog/202004_react_leaflet_4/react.png"
categories:
  - 2020
tags:
  - react
  - leaflet
---

Vamos con el tercer *sprint* de este [**proyecto para crear una aplicación de mapas con la librería React**](http://www.sigdeletras.com/2020/side-project-desarrollo-de-aplicacion-web-con-react-y-leaflet-i/). Como voy comentando desde la primera entrada se definieron un conjunto de "tareas" cerradas que establecerían el alcance de la aplicación. En esta ocasión, le he dado un buen impulso al *backlog*.

![react.png](/images/blog/202004_react_leaflet_4/react.png)

Estas son las tareas realizadas en esta nueva versión:

- 11 Conexión a servicio WFS.
- 12 Consulta WFS por muncipio.
- 13 Datos WFS en Mapa.
- 15 Consulta datos en mapa (popup).
- 23 Añadir capas WMS y gestión con LayerControl.

Los temas aprendidos sobre React a partir del desarrollo de las tareas son los siguientes:

- La gestión de forma asíncrona de **peticiones/respuestas a servicios WFS** usando [fetch](https://developer.mozilla.org/es/docs/Web/API/Fetch_API/Utilizando_Fetch).
- El uso de **referencias y métodos de cliclo** de vida en React.
- Nuevos **componentes del mapa (LayerControl, WMS)** de la librería React-Leaflet.

## Petición de datos a un servicio WFS

El consumo de datos geográficos mediante [servicios OGC](https://es.wikipedia.org/wiki/Open_Geospatial_Consortium) se encuentra extendido en proyectos de estas características. Dentro de estos servicios estándar, el conocido como **Web Feature Service (WFS)** ofrece una interfaz de comunicación que permite consultar o descargar objetos geográficos. En la la entrada titulada ["Acceso a servicios OGC (WMS,WFS..) con Postman"](http://www.sigdeletras.com/2019/acceso-a-servicios-ogc-con-postman/) tengo desarrollado algunos de estos aspectos.

Hay una gran cantidad de datos que pueden consumirse no solo con un SIG de escritorio, sino también mediante una aplicación web. Sirva come ejemplo la [recopilación de servicios de descargas en la web de la IDE España](https://www.idee.es/es_ES/web/guest/directorio-de-servicios?p_p_id=DIRSRVIDEE_WAR_DIRSRVIDEEportlet_INSTANCE_KXnVu4qMJc1J&p_p_lifecycle=1&p_p_state=normal&p_p_mode=view&p_p_col_id=column-1&p_p_col_count=1&_DIRSRVIDEE_WAR_DIRSRVIDEEportlet_INSTANCE_KXnVu4qMJc1J_descSrv=DESCARGA). Al ser un recurso muy especializado técnicamente, pienso que se encuentra realmente poco explotado tanto por parte de los profesionales "geo" como desde del desarrollo web en general.

Para el proyecto voy a usar los datos de Servicios de Salud del [WFS de los Datos Espaciales de Rerencia de Andalucía (DERA)](http://www.juntadeandalucia.es/institutodeestadisticaycartografia/DERA/servicios.htm).  En esta capa se encuentran la *"distribución de los equipamientos sanitarios públicos y privados integrados en el Sistema Sanitario Público de Andalucía."*

![03_dera.png](/images/blog/202004_react_leaflet_4/03_dera.png)

## Petición de datos con API fetch

En primer lugar han sido añadidos dos nuevos valores en *state* para el componente *App*

```javascript
//App.js
...
export default class App extends React.Component {

  constructor() {
    super()
    this.state = {
      coordCenter: [37.885963680860755, -4.774589538574219],
      munipalityName: '',
      zoom: 9,
      geodata: '',
      code: ''
    }
    this.munipalityChange = this.munipalityChange.bind(this)
  }
...
```
- *geodata*: Será usado para guardar los datos que obtengamos tras realizar la petición al servicio WFS.
- *code*: En este calor se almacenará el código INE del municipio y que permitirá realizar la consulta filtrada el servicio WFS. El código INE ha sido añadido al json que almacena los datos que aparecen en el listado y también se ha actualizado la información almacena en el valor del elemento *select* dentro de *SelectList* para que puede ser usado.

![03_add_codeine.png](/images/blog/202004_react_leaflet_4/03_add_codeine.png)

Para la obtención de los datos desde el WFS de la Junta de Andalucía, creamos una función *getWFSData(code)*. En esta función se realizará la petición de datos a la URL del servicio usando [API fetch](https://developer.mozilla.org/es/docs/Web/API/Fetch_API) y pasando el código INE como filtro. La asincronía de la función será manejada con [*async*](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Sentencias/funcion_asincrona)

```javascript
//App.js
...
  async getWFSData(code) {
    const URL = `http://www.ideandalucia.es/dea100/wfs?service=WFS&version=1.1.0&request=GetFeature&typename=dea100:sv03_sas&MAXFEATURES=10&outputFormat=application/json&filter=<Filter><PropertyIsEqualTo><PropertyName>codmun</PropertyName><Literal>${code}</Literal></PropertyIsEqualTo></Filter>&SRSNAME=EPSG:4326`
    const res = await fetch(URL)
    const data = await res.json();
    this.setState({
      geodata: data
    })
  }

  munipalityChange = (data) => {
    let aData = data.split(',')
    this.setState({
      coordCenter: [aData[0], aData[1]],
      munipalityName: aData[2],
      zoom: 14,
      code: aData[3]
    });
    this.getWFSData(aData[3])
  }

  render() {
...
```
Tengo que comentar que ya que estoy trabajando con el servidor de desarrollo que me crea la extensión [create-react-app](https://github.com/facebook/create-react-app) he tenido que solucionar el tema de CORS usando la extensión [Alow CORS](https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=es) de Chrome.

## Nuevo componente *MapLayer* para gestionar los datos geográficos (geojson)

La funcionalidad está desarrollada dentro de un nuevo componente llamado *Maplayer*. Con la librería React-Leaflet tenemos accesible el [componente GeoJSON](https://react-leaflet.js.org/docs/en/components#geojson) que implementa el [código de la API de Leaflet](https://leafletjs.com/reference-1.6.0.html#geojson) para añadir capas de datos vectoriales en este formato.

Para poder usar el icono que viene por defecto en Leaflet se ha tenido que incorporar el siguiente código.

![03_icon_lealfet.png](/images/blog/202004_react_leaflet_4/03_icon_lealfet.png)

Este componente será añadido en *MapView* y consumirá los datos que le pasamos en sus propiedades

### Ref y ciclos de vida

Despúes de alguna que otra búsqueda [aquí](https://github.com/LiveBy/react-leaflet-choropleth/issues/3) y [aquí](https://github.com/open-austin/austingreenmap/blob/9b0d9ad5ddc245c07c63ab7d2997e74328d73259/client/js/components/ParksMap.jsx), logré conseguir que se "pintaran" los datos al cambiar del municipio.

Según la documentación de la librería, alguno de los componentes no se actualizan cuando cambian después de que el componente es montado. Este el el caso del componente GeoJSON. Para que esta opción funciones debemos acceder directamente al elemento Leaflet usado *this.leafletElement* y usando las [referencias de React](https://es.reactjs.org/docs/refs-and-the-dom.html) y desde ahí manejar el DOM de Leaflet.

Hecha la referencia, ahora debemos usar las funciones de la librería de mapa en los **métodos del ciclo de vida del componente React**:
- *componentWillReceiveProps()*. Este método no se ejecutará una vez se monte el componente, si no que se esperará a recibir nuevas props de un componente padre para ejecutarse. Lo usaremos para limpiar las capas con *clearLayers()* si los datos recibidos son distintos.
- *componentDidUpdate()*. Es invocado inmediatamente después de que el componente se haya actualizado. Dentro se añadirán los datos para el GeoJSON que obtenemos al realizar la consulta a la API.

```javascript
//MapLayer.js
...
export default class MapLayer extends Component {

    leafletRef = React.createRef();

    componentWillReceiveProps(prevProps) {
        if (prevProps.data !== this.props.data) {
            this.leafletRef.current.leafletElement.clearLayers();
        }
    }

    componentDidUpdate(prevProps) {
        if (prevProps.data !== this.props.data) {
            this.leafletRef.current.leafletElement.addData(this.props.data);
        }
    }
...
```
Para poder usar las referencias tenemos que pasarsela como propiedad al compontente.

```javascript
//MapLayer.js
...
render() {
        return <GeoJSON
        data = { this.props.data }
        ref = { this.leafletRef }
        onEachFeature = { this.onEachFeature }
        />
    }
..
```

### Popups

Terminamos el componente incorporando la función *onEachFeature()* que permite ofrecer información de los servicios saniarios en un *popup*.

![03_popup.png](/images/blog/202004_react_leaflet_4/03_popup.png)

## LayerControl

Vamos a darle más **funcionalidades geo** a nuestra aplicación de mapas. Para poder ver los datos sobre distintos mapas base, he incorporado el compomente de control de capas *LayersControl* en *MapView*. Dentro del mismo seguimos manteniendo la base de OpenStreetMap y añadimos la **ortofotografía del PNOA** como capa WMS.

```javascript
//MapView.js
...
    return (
      <div>
        <Map
          style={styleMap}
          center={this.props.coordCenter}
          zoom={this.props.zoom}>

          <LayersControl position="topright">

            <BaseLayer checked name="OpenStreetMap">
              <TileLayer
                attribution='&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
              />
            </BaseLayer>

            <BaseLayer name="PNOA">
              <WMSTileLayer
                layers={'OI.OrthoimageCoverage'}
                attribution='© <a href="https://pnoa.ign.es/">IGN</a>'
                url="http://www.ign.es/wms-inspire/pnoa-ma?"
              />
            </BaseLayer>

            <Overlay checked name="Servicios Sanitarios (DERA)">
              <MapLayer data={this.props.geodata} />
            </Overlay>

          </LayersControl>

        </Map>
      </div>
    )

  }
```

Tras el desarrollo de las nuevas tareas esta es nuetra aplición web hasta el momento.

![03_sprint3.gif](/images/blog/202004_react_leaflet_4/03_sprint3.gif)

## Resumen de  tareas realizadas en el Sprint #3

![03_trello.png](/images/blog/202004_react_leaflet_4/03_trello.png)

## Hilo de entradas

- [Side Project: Desarrollo de aplicación web con React y Leaflet (I)](http://www.sigdeletras.com/2020/side-project-desarrollo-de-aplicacion-web-con-react-y-leaflet-i/)
- [Side Project: Desarrollo de aplicación web con React y Leaflet (II). Creando componentes](http://www.sigdeletras.com/2020/side-project-desarrollo-de-aplicacion-web-con-react-y-leaflet-ii-components/)
- [Side Project: Desarrollo de aplicación web con React y Leaflet (III). Funciones, estado y props](http://www.sigdeletras.com/2020/side-project-iii/)

## Enlaces

- Repositorio GitHub [React & Maps](https://github.com/sigdeletras/react_maps) (rama *master*)


text:
package org.gearvrf;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.util.TypedValue;

import org.gearvrf.asynchronous.CompressedTexture;
import org.gearvrf.asynchronous.GVRCompressedTextureLoader;
import org.gearvrf.utility.Log;
import org.gearvrf.utility.MarkingFileInputStream;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * A class to minimize overload fan-out.
 *
 * APIs that load resources can take a {@link GVRAndroidResource} instead of
 * having overloads for {@code assets} files, {@code res/drawable} and
 * {@code res/raw} files, and plain old files.
 *
 * See the discussion of asset-relative filenames vs. {@code R.raw}
 * resource ids in the package
 * description.
 *
 * @since 1.6.1
 */
public class GVRAndroidResource {
    private static final String TAG = Log.tag(GVRAndroidResource.class);

    private enum StreamStates {
        NEW, OPEN, CLOSED
    }

    /**
     * Designates the type of volume this resource comes from.
     */
    public enum ResourceType {
        ANDROID_ASSETS, ANDROID_RESOURCE, LINUX_FILESYSTEM, NETWORK, INPUT_STREAM
    }

    /*
     * Instance members
     */

    private InputStream stream;
    private StreamStates streamState;

    // Save parameters, for hashCode() and equals()
    private final String filePath;
    private final int resourceId;
    private final String assetPath;
    // For hint to Assimp
    private String resourceFilePath;
    private final URL url;
    private boolean enableUrlLocalCache = false;

    private Context context;
    private ResourceType resourceType;
    private String inputStreamName;

    /**
     * Open any file you have permission to read.
     *
     * @param path
     *            A Linux file path
     *
     * @throws FileNotFoundException
     *             File doesn't exist, or can't be read.
     */
    public GVRAndroidResource(String path) throws FileNotFoundException {
        streamState = StreamStates.NEW;

        filePath = path;
        resourceId = 0; // No R.whatever field will ever be 0
        assetPath = null;
        resourceFilePath = null;
        url = null;
        resourceType = ResourceType.LINUX_FILESYSTEM;
    }

    /**
     * Open any file you have permission to read.
     *
     * @param file
     *            A Java {@link File} object
     *
     * @throws FileNotFoundException
     *             File doesn't exist, or can't be read.
     */
    public GVRAndroidResource(File file) throws FileNotFoundException {
        this(file.getAbsolutePath());
    }

    /**
     * Open a {@code res/raw} or {@code res/drawable} bitmap file.
     *
     * @param gvrContext
     *            The GVR Context
     * @param resourceId
     *            A {@code R.raw} or {@code R.drawable} id
     */
    public GVRAndroidResource(GVRContext gvrContext, int resourceId) {
        this(gvrContext.getContext(), resourceId);
    }

    /**
     * Open a {@code res/raw} or {@code res/drawable} bitmap file.
     *
     * @param context
     *            An Android Context
     * @param resourceId
     *            A {@code R.raw} or {@code R.drawable} id
     */
    public GVRAndroidResource(Context context, int resourceId) {
        this.context = context.getApplicationContext();
        Resources resources = context.getResources();
        streamState = StreamStates.NEW;

        filePath = null;
        this.resourceId = resourceId;
        assetPath = null;
        url = null;
        TypedValue value = new TypedValue();
        resources.getValue(resourceId, value, true);
        resourceFilePath = value.string.toString();
        resourceType = ResourceType.ANDROID_RESOURCE;
    }

    /**
     * Open an {@code assets} file
     *
     * @param gvrContext
     *            The GVR Context
     * @param assetRelativeFilename
     *            A filename, relative to the {@code assets} directory. The file
     *            can be in a sub-directory of the {@code assets} directory:
     *            {@code "foo/bar.png"} will open the file
     *            {@code assets/foo/bar.png}
     */
    public GVRAndroidResource(GVRContext gvrContext,
            String assetRelativeFilename)  throws IOException  {
        this(gvrContext.getContext(), assetRelativeFilename);
    }

    /**
     * Open an {@code assets} file
     *
     * @param context
     *            An Android Context
     * @param assetRelativeFilename
     *            A filename, relative to the {@code assets} directory. The file
     *            can be in a sub-directory of the {@code assets} directory:
     *            {@code "foo/bar.png"} will open the file
     *            {@code assets/foo/bar.png}
     */
    public GVRAndroidResource(Context context, String assetRelativeFilename) {
        this.context = context.getApplicationContext();
        streamState = StreamStates.NEW;

        filePath = null;
        resourceId = 0; // No R.whatever field will ever be 0
        assetPath = assetRelativeFilename;
        resourceFilePath = null;
        url = null;
        resourceType = ResourceType.ANDROID_ASSETS;
    }

    /**
     * Open resource from a URL.
     *
     * @param url
     *            A Java {@link URL} object
     */
    public GVRAndroidResource(GVRContext context, URL url) {
        this(context, url, false);
    }

    /**
     * Create a resource from an {@link InputStream}.
     *
     * Note that this constructor is package private and is only used by the {@link ZipLoader}
     * (for now).
     *
     * @param name        a String for uniquely identifying this resource
     * @param inputStream an already open {@link InputStream} for this resource
     */
    public GVRAndroidResource(String name, InputStream inputStream) {
        inputStreamName = name;
        stream = inputStream;
        streamState = StreamStates.NEW;

        filePath = null;
        resourceId = 0; // No R.whatever field will ever be 0
        assetPath = null;
        resourceFilePath = null;
        url = null;
        resourceType = ResourceType.INPUT_STREAM;
    }

    /**
     * Gets the type of volume this resource resides on.
     *

     *
ANDROID_ASSETS  resource is a file in the "assets" directory of the application.

     *
ANDROID_RESOURCE  resource is referenced by resource ID.

     *
LINUX_FILESYSTEM  resource is on the SD card of the device.

     *
NETWORK  resource is a URL on the network.

     *
INPUT_STREAM  resource is from an input stream.

     *

     * @return GVRAndroidResource.ResourceType giving type of resource
     */
    ResourceType getResourceType()
    {
        return resourceType;
    }

    /*
     * A {@link URLBufferedInputStream} that supports {@link
     * InputStream#mark(int)} and {@link InputStream#reset()}
     */
    static class URLBufferedInputStream extends InputStream {
        private URL url;
        private BufferedInputStream in;

        public URLBufferedInputStream(URL url) throws IOException {
            this.url = url;
            in = new BufferedInputStream(url.openStream());
        }

        @Override
        public boolean markSupported() {
            return true;
        }

        @Override
        public void reset() throws IOException {
            // Since the bufferInputStream resets the offset within the internal
            // buffer while may not resets the url's stream correctly
            // it could easily causes OOM error when decoding it after some
            // initial read and reset.
            // Here we tackle it by opening a new connection to the url and
            // restart from beginning
            in = new BufferedInputStream(url.openStream());
        }

        @Override
        public int read() throws IOException {
            return in.read();
        }

        @Override
        public int read(byte[] buffer, int byteOffset, int byteCount)
                throws IOException {
            return in.read(buffer, byteOffset, byteCount);
        }
    }

    /**
     * Download resource from a URL and open it as a regular file.
     *
     * @param context
     *            An Android Context
     * @param url
     *            A Java {@link URL} object
     */
    public GVRAndroidResource(GVRContext context, URL url,
            boolean enableUrlLocalCache) {
        this.enableUrlLocalCache = enableUrlLocalCache;

        streamState = StreamStates.NEW;
        filePath = null;
        resourceId = 0;
        assetPath = null;
        resourceFilePath = null;
        this.url = url;
        resourceType = ResourceType.NETWORK;
        this.context = context.getContext().getApplicationContext();
    }

    /**
     * Get the open stream.
     *
     * Changes the debug state (visible via {@link #toString()}) to
     * {@linkplain GVRAndroidResource.StreamStates#OPEN OPEN}.
     *
     * @return An open {@link InputStream}.
     * @throws IOException
     */
    public synchronized final InputStream getStream() throws IOException{
        if (streamState != StreamStates.OPEN) {
            openStream();
        }

        return stream;
    }

    /**
     * Sets the stream for a resource.
     * This function allows you to provide a stream that is already open to
     * an existing resource. It will throw an exception if that resource
     * already has an open stream.
     * @param s InputStream currently open stream to use for I/O.
     */
    protected synchronized void setStream(InputStream s)
    {
        if (stream != null)
        {
            throw new UnsupportedOperationException("Cannot set the stream of an open resource");
        }
        stream = s;
        streamState = StreamStates.OPEN;
    }

    /*
     * TODO Should we somehow expose the CLOSED state? Return null or throw an
     * exception from getStream()? Or is it enough for the calling code to fail,
     * reading a closed stream?
     */

    /**
     * Close the open stream.
     *
     * Close the stream if it was opened before
     *
     */
    public synchronized final void closeStream() {
        try {
            if ((stream != null) && (streamState == StreamStates.OPEN)) {
                stream.close();
                stream = null;
            }
            streamState = StreamStates.CLOSED;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * Open the input stream for resource decoding
     *
     *
     */
    public synchronized void openStream() throws IOException {
        switch (resourceType) {
        case ANDROID_ASSETS:
            stream = context.getResources().getAssets().open(assetPath);
            streamState = StreamStates.OPEN;
            break;

        case ANDROID_RESOURCE:
            stream = context.getResources().openRawResource(resourceId);
            streamState = StreamStates.OPEN;
            break;

        case LINUX_FILESYSTEM:
            stream = new MarkingFileInputStream(filePath);
            streamState = StreamStates.OPEN;
            break;

        case NETWORK:
            if (!enableUrlLocalCache) {
                Log.d(TAG,
                        "Do not allow local caching, use streaming to get the resource");
                stream = new URLBufferedInputStream(url);
                streamState = StreamStates.OPEN;
            } else {
                Log.d(TAG,
                        "Allow local caching, download the resource to local cache");
                File file = GVRAssetLoader.downloadFile(context,
                        url.toString());
                stream = new MarkingFileInputStream(file);
                streamState = StreamStates.OPEN;
            }
            break;

        case INPUT_STREAM:
            //input stream is already open
            streamState = StreamStates.OPEN;
            break;
        default:
            stream = null;
        }
    }

    /**
     * Save the stream position, for later use with {@link #reset()}.
     *
     * All {@link GVRAndroidResource} streams support
     * {@link InputStream#mark(int) mark()} and {@link InputStream#reset()
     * reset().} Calling {@link #mark()} right after construction will allow you
     * to read the header then {@linkplain #reset() rewind the stream} if you
     * can't handle the file format.
     * @throws IOException
     *
     * @since 1.6.7
     */
    private void mark() throws IOException {
        if (streamState == StreamStates.OPEN) {
            if (stream.markSupported()) {
                stream.mark(Integer.MAX_VALUE);
            } else {
                // In case a inputStream (e.g., fileInputStream) doesn't support
                // mark, throw a exception
                throw new IOException("Input stream doesn't support mark");
            }
        }
    }

    /**
     * Restore the stream position, to the point set by a previous
     * {@link #mark() mark().}
     *
     * Please note that calling {@link #reset()} generally 'consumes' the
     * {@link #mark()} - do not call
     *
     *

     * mark();
     * reset();
     * reset();
     *

     * @throws IOException
     *
     * @since 1.6.7
     */
    private void reset() throws IOException {
        if (streamState == StreamStates.OPEN) {
            if (stream.markSupported()) {
                stream.reset();
            } else {
                // In case a inputStream (e.g., fileInputStream) doesn't support
                // mark, throw a exception
                throw new IOException("Input stream doesn't support mark");
            }
        }
    }

    /**
     * Returns the filename of the resource with extension.
     *
     * @return Filename of the GVRAndroidResource. May return null if the
     *         resource is not associated with any file
     */
    public String getResourceFilename() {
        switch (resourceType) {
        case ANDROID_ASSETS:
            return assetPath
                    .substring(assetPath.lastIndexOf(File.separator) + 1);

        case ANDROID_RESOURCE:
            return resourceFilePath.substring(
                    resourceFilePath.lastIndexOf(File.separator) + 1);

        case LINUX_FILESYSTEM:
            return filePath.substring(filePath.lastIndexOf(File.separator) + 1);

        case NETWORK:
            return url.getPath().substring(url.getPath().lastIndexOf("/") + 1);

        case INPUT_STREAM:
            return inputStreamName;

        default:
            return null;
        }
    }

    /*
     * Auto-generated hashCode() and equals(), for container support &c.
     *
     * These check only the private 'parameter capture' fields - not the
     * InputStream.
     */

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((assetPath == null) ? 0 : assetPath.hashCode());
        result = prime * result
                + ((filePath == null) ? 0 : filePath.hashCode());
        result = prime * result
                + ((url == null) ? 0 : url.hashCode());
        result = prime * result
                + ((inputStreamName == null) ? 0 : inputStreamName.hashCode());
        result = prime * result + resourceId;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }

        GVRAndroidResource other = (GVRAndroidResource) obj;
        switch (resourceType) {
        case ANDROID_ASSETS:
            return assetPath.equals(other.assetPath);

        case ANDROID_RESOURCE:
            return resourceId == other.resourceId;

        case LINUX_FILESYSTEM:
            return filePath.equals(other.filePath);

        case NETWORK:
            return url.equals(other.url);

        case INPUT_STREAM:
            return inputStreamName.equals(other.inputStreamName);

        default:
            return false;
        }
    }

    /*
     * toString(), for debugging.
     */

    /**
     * For debugging: shows which file the instance describes, and shows the
     * OPEN / READING / CLOSED state of the input stream.
     */
    @Override
    public String toString() {
        return String.format("%s { %s %x %s }",
                             streamState, getResourceFilename(), resourceId, inputStreamName);
    }

    /*
     * Generic callback interfaces, for asynchronous APIs that take a {@link
     * GVRAndroidResource} parameter
     */

    /**
     * Callback interface for asynchronous resource loading.
     *
     * None of the asynchronous resource [textures, and meshes] loading methods
     * that take a {@link GVRAndroidResource} parameter return a value. You must
     * supply a copy of this interface to get results.
     *
     *

     * While you will often create a callback for each load request, the APIs do
     * each include the {@link GVRAndroidResource} that you are loading. This
     * lets you use the same callback implementation with multiple resources.
     */
    public interface Callback<T extends GVRHybridObject> {
        /**
         * Resource load succeeded.
         *
         * @param resource
         *            A new GVRF resource
         * @param androidResource
         *            The description of the resource that was loaded
         *            successfully
         */
        void loaded(T resource, GVRAndroidResource androidResource);

        /**
         * Resource load failed.
         *
         * @param t
         *            Error information
         * @param androidResource
         *            The description of the resource that could not be loaded
         */
        void failed(Throwable t, GVRAndroidResource androidResource);
    }

    /**
     * Callback interface for cancelable resource loading.
     *
     * Loading uncompressed textures (Android {@linkplain Bitmap bitmaps}) can
     * take hundreds of milliseconds and megabytes of memory; loading even
     * moderately complex meshes can be even slower. GVRF uses a throttling
     * system to manage system load, and an priority system to give you some
     * control over the throttling. This means that slow resource loads can take
     * enough time that you don't actually need the resource by the time the
     * system gets to it. The {@link #stillWanted(GVRAndroidResource)} method
     * lets you cancel unneeded loads.
     */
    public interface CancelableCallback<T extends GVRHybridObject> extends
            Callback<T> {
        /**
         * Do you still want this resource?
         *
         * If the throttler has a thread available, your request will be run
         * right away; this method will not be called. If not, it is enqueued;
         * this method will be called (at least once) before starting to load
         * the resource. If you no longer need it, returning {@code false} can
         * save non-trivial amounts of time and memory.
         *
         * @param androidResource
         *            The description of the resource that is about to be loaded
         *
         * @return {@code true} to continue loading; {@code false} to abort.
         *         (Returning {@code false} will not call
         *         {@link #failed(Throwable, GVRAndroidResource) failed().})
         */
        boolean stillWanted(GVRAndroidResource androidResource);
    }

    /*
     * Specialized callback interfaces, to make use a bit smaller and clearer.
     */

    /**
     * Callback for asynchronous compressed-texture loads.
     *
     * Compressed textures load very quickly, so they're not subject to
     * throttling and don't support
     * {@link BitmapTextureCallback#stillWanted(GVRAndroidResource)}
     */
    public interface CompressedTextureCallback extends TextureCallback { }

    /** Callback for asynchronous bitmap-texture loads. */
    public interface BitmapTextureCallback extends TextureCallback { }

    /**
     * Callback for asynchronous texture loads.
     *
     * Both compressed and bitmapped textures, using the
     * {@link GVRContext#loadTexture(GVRAndroidResource.TextureCallback, GVRAndroidResource)}
     * APIs.
     *
     * @since 1.6.7
     */
    public interface TextureCallback extends CancelableCallback<GVRImage> {
    }

    /** Callback for asynchronous mesh loads */
    public interface MeshCallback extends CancelableCallback<GVRMesh> {
    }

    private GVRCompressedTextureLoader compressedLoader = null;
    private boolean isCompressedTextureSniffed = false;

    public synchronized GVRCompressedTextureLoader getCompressedLoader() {
        if (!isCompressedTextureSniffed) {
            try {
                Log.d(TAG, "Looking for compressed header");
                openStream();
                mark();
                try {
                    compressedLoader = CompressedTexture.sniff(getStream());
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    reset();
                    //don't close for this type
                    if (resourceType != ResourceType.INPUT_STREAM) {
                        closeStream();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                isCompressedTextureSniffed = true;
            }
        }

        return compressedLoader;
    }
}


text:
package org.jboss.resteasy.util;

import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;

import javax.ws.rs.core.Context;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

/**
 * Pick
 *
 * @author Bill Burke
 * @version $Revision: 1 $
 */
public class PickConstructor
{

   /**
    * Pick best constructor for a provider or resource class
    *

    * Picks constructor with most parameters.  Will ignore constructors that have parameters with no @Context annotation
    *
    * @param clazz
    * @return
    */
   public static Constructor pickSingletonConstructor(Class clazz)
   {
      Constructor<?>[] constructors = clazz.getConstructors();
      Constructor<?> constructor = null;
      // prefer a no-arg constructor
      int numParameters = 0;
      Constructor pick = null;
      boolean potentialConflict = false; // https://issues.jboss.org/browse/RESTEASY-645
      for (Constructor con : constructors)
      {
         if (Modifier.isPublic(con.getModifiers()) == false)
         {
            continue;
         }

         if (con.getParameterTypes().length >= numParameters)
         {
            if (con.getParameterTypes().length > numParameters) {
                potentialConflict = false;
            }
            boolean noContextAnnotation = false;
            if (con.getParameterAnnotations() != null)
            {
               for (Annotation[] ann : con.getParameterAnnotations())
               {
                  if (FindAnnotation.findAnnotation(ann, Context.class) == null)
                  {
                     noContextAnnotation = true;
                  }
               }
            }
            if (noContextAnnotation) continue;
            if (con.getParameterTypes().length == numParameters && numParameters != 0) {
                potentialConflict = true;
            }
            numParameters = con.getParameterTypes().length;
            pick = con;

         }
      }
      if (potentialConflict) {
         LogMessages.LOGGER.ambiguousConstructorsFound(clazz);
      }
      return pick;
   }

   /**
    * Pick best constructor for a provider or resource class
    *

    * Picks constructor with most parameters.  Will ignore constructors that have parameters with no @Context annotation
    *
    * @param clazz
    * @return
    */
   public static Constructor pickPerRequestConstructor(Class clazz)
   {
      Constructor<?>[] constructors = clazz.getConstructors();
      Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
      Constructor<?> constructor = null;
      // prefer a no-arg constructor
      int numParameters = 0;
      Constructor pick = null;
      boolean potentialConflict = false; // https://issues.jboss.org/browse/RESTEASY-645
      for (Constructor con : constructors)
      {
         if (Modifier.isPublic(con.getModifiers()) == false)
         {
            continue;
         }
         if (con.getParameterTypes().length >= numParameters)
         {
            if (con.getParameterTypes().length > numParameters) {
                potentialConflict = false;
            }

            boolean noContextAnnotation = false;
            if (con.getParameterAnnotations() != null)
            {
               for (Annotation[] ann : con.getParameterAnnotations())
               {
                  if (FindAnnotation.findJaxRSAnnotations(ann).length == 0)
                  {
                     noContextAnnotation = true;
                  }
               }
            }
            if (noContextAnnotation) continue;
            if (con.getParameterTypes().length == numParameters && numParameters != 0) {
                potentialConflict = true;
            }
            numParameters = con.getParameterTypes().length;
            pick = con;
         }
      }

      if (potentialConflict) {
         LogMessages.LOGGER.ambiguousConstructorsFound(clazz);
      }
      return pick;
   }
}


text:
from datetime import datetime
from dateutil.parser import parse as dateutil_parse
from flask import current_app as app
from flask_babel import to_utc
from functools import reduce
from urllib.parse import urljoin

import json
import logging
import urllib3
import six

logger = logging.getLogger(__name__)
http = urllib3.PoolManager()

class KQueenResponse:
    status = 200
    error = ''
    data = {}

    def __iter__(self):
        for item in self.data:
            yield item

    def __len__(self):
        return len(self.data)

    def __getitem__(self, x):
        return self.data[x]

    def get(self, item, default=None):
        if default:
            return self.data.get(item, default)
        else:
            return self.data.get(item)

class ParserMixin:
    DATETIME_FIELDS = ['created_at']

    def _parse_response_datetime(self, _dict):
        for key, value in _dict.items():
            if key in self.DATETIME_FIELDS and value:
                _dict[key] = dateutil_parse(value)
            elif isinstance(value, dict):
                self._parse_response_datetime(value)

    def _parse_request_payload_datetime(self, _dict):
        for key, value in _dict.items():
            if key in self.DATETIME_FIELDS:
                if isinstance(value, datetime):
                    _dict[key] = value.isoformat()
                elif isinstance(value, six.string_types):
                    fmt_dt = dateutil_parse(value)
                    dt = to_utc(fmt_dt)
                    _dict[key] = dt.isoformat()
            elif isinstance(value, dict):
                self._parse_request_payload_datetime(value)

    def _parse_response(self, response):
        if isinstance(response, list):
            for item in response:
                self._parse_response_datetime(item)
        elif isinstance(response, dict):
            self._parse_response_datetime(response)
        return response

    def _parse_request_payload(self, payload):
        if isinstance(payload, list):
            for item in payload:
                self._parse_request_payload_datetime(item)
        elif isinstance(payload, dict):
            self._parse_request_payload_datetime(payload)
        return payload

class BaseManager(ParserMixin):
    resource_url = ''

    def __init__(self, client):
        self.client = client

    def login(self):
        payload = json.dumps({
            'username': self.client.username,
            'password': self.client.password
        })

        r = self._request('', override_url=self.client.auth_url, method='POST', payload=payload, auth=False)
        token = r.data.get('access_token', None)
        error = None
        self.client.token = token
        if r.error:
            try:
                _msg = json.loads(r.error)
                msg = _msg['description']
            except Exception:
                msg = r.error
            error = {
                'status': r.status,
                'description': msg
            }
            logger.warning('KQueen Client:: Could not get access token: {}'.format(r.error))
        return token, error

    def _request(self, url_suffix, method='GET', payload=None, override_url=None, auth=True):
        headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }

        if auth:
            headers['Authorization'] = 'Bearer %s' % self.client.token

        _url = reduce(urljoin, [self.client.base_url, self.resource_url, url_suffix])
        url = _url[:-1] if _url.endswith('/') else _url
        if override_url:
            url = override_url

        body = None
        if method in ['POST', 'PATCH']:
            if isinstance(payload, dict):
                parsed_payload = self._parse_request_payload(payload)
                body = json.dumps(parsed_payload)
            else:
                body = payload

        response = KQueenResponse()

        try:
            raw = http.request(method, url, body=body, headers=headers)
        except Exception as e:
            response.error = repr(e)
            response.status = -1
            logger.error('KQueen Client:: {}'.format(repr(e)))
            return response

        response.status = raw.status

        if response.status > 200:
            response.error = raw.data.decode('utf-8')
            logger.error('KQueen Client:: {}'.format(raw.data.decode('utf-8')))
            return response

        try:
            data = json.loads(raw.data.decode('utf-8'))
            response.data = self._parse_response(data)
        except json.decoder.JSONDecodeError as e:
            response.error = 'JSONDecodeError: {}'.format(repr(e))
            logger.error('KQueen Client:: {}'.format(repr(e)))

        return response

    def request(self, *args, **kwargs):
        if not self.client.token:
            self.login()
        return self._request(*args, **kwargs)

    def list(self):
        return self.request('')

    def get(self, uuid):
        return self.request(uuid)

    def create(self, payload):
        return self.request('', method='POST', payload=payload)

    def delete(self, uuid):
        return self.request(uuid, method='DELETE')

    def update(self, uuid, payload):
        return self.request(uuid, method='PATCH', payload=payload)

class ClusterManager(BaseManager):
    resource_url = 'clusters/'

    def status(self, uuid):
        return self.request('%s/status' % uuid)

    def topology_data(self, uuid):
        return self.request('%s/topology-data' % uuid)

    def kubeconfig(self, uuid):
        return self.request('%s/kubeconfig' % uuid)

    def progress(self, uuid):
        return self.request('%s/progress' % uuid)

class ProvisionerManager(BaseManager):
    resource_url = 'provisioners/'

    def engines(self):
        return self.request('engines')

class OrganizationManager(BaseManager):
    resource_url = 'organizations/'

    def policy(self, uuid):
        return self.request('%s/policy' % uuid, method='GET')

class UserManager(BaseManager):
    resource_url = 'users/'

    def updatepw(self, uuid, payload):
        return self.request('%s/updatepw' % uuid, method='PATCH', payload=payload)

    def update(self, uuid, payload):
        organization = payload.get('organization', None)
        if organization and isinstance(organization, dict):
            payload['organization'] = 'Organization:{}'.format(payload['organization']['id'])
        return self.request(uuid, method='PATCH', payload=payload)

    def whoami(self):
        return self.request('whoami')

class KQueenAPIClient:

    def __init__(
        self,
        username=None,
        password=None,
        token=None,
        base_url='http://localhost:5000/api/v1/',
        auth_url='http://localhost:5000/api/v1/auth'
    ):
        # Save credentials
        self.username = username
        self.password = password
        self.token = token
        self.base_url = base_url
        self.auth_url = auth_url
        # Register managers
        self.base = BaseManager(self)
        self.cluster = ClusterManager(self)
        self.provisioner = ProvisionerManager(self)
        self.organization = OrganizationManager(self)
        self.user = UserManager(self)

def get_kqueen_client(username=None, password=None, token=None):
    base_url = app.config['KQUEEN_API_URL']
    auth_url = app.config['KQUEEN_AUTH_URL']
    return KQueenAPIClient(username, password, token, base_url, auth_url)

def get_service_client():
    username = app.config['KQUEEN_SERVICE_USER_USERNAME']
    password = app.config['KQUEEN_SERVICE_USER_PASSWORD']
    return get_kqueen_client(username=username, password=password)


text:
package javax.xml.bind;

/**
 * This exception indicates that an error has occurred while performing
 * a validate operation.
 *
 *

 * The <tt>ValidationEventHandler</tt> can cause this exception to be thrown
 * during the validate operations.  See
 * {@link ValidationEventHandler#handleEvent(ValidationEvent)
 * ValidationEventHandler.handleEvent(ValidationEvent)}.
 *
 * @author

Ryan Shoemaker, Sun Microsystems, Inc.

 * @see JAXBException
 * @see Validator
 * @since JAXB1.0
 */
public class ValidationException extends JAXBException {

    /**
     * Construct an ValidationException with the specified detail message.  The
     * errorCode and linkedException will default to null.
     *
     * @param message a description of the exception
     */
    public ValidationException(String message) {
        this( message, null, null );
    }

    /**
     * Construct an ValidationException with the specified detail message and vendor
     * specific errorCode.  The linkedException will default to null.
     *
     * @param message a description of the exception
     * @param errorCode a string specifying the vendor specific error code
     */
    public ValidationException(String message, String errorCode) {
        this( message, errorCode, null );
    }

    /**
     * Construct an ValidationException with a linkedException.  The detail message and
     * vendor specific errorCode will default to null.
     *
     * @param exception the linked exception
     */
    public ValidationException(Throwable exception) {
        this( null, null, exception );
    }

    /**
     * Construct an ValidationException with the specified detail message and
     * linkedException.  The errorCode will default to null.
     *
     * @param message a description of the exception
     * @param exception the linked exception
     */
    public ValidationException(String message, Throwable exception) {
        this( message, null, exception );
    }

    /**
     * Construct an ValidationException with the specified detail message, vendor
     * specific errorCode, and linkedException.
     *
     * @param message a description of the exception
     * @param errorCode a string specifying the vendor specific error code
     * @param exception the linked exception
     */
    public ValidationException(String message, String errorCode, Throwable exception) {
        super( message, errorCode, exception );
    }

}


text:
using System;
using log4net;
using SuperPutty.Data;
using System.Text.RegularExpressions;
using System.IO;

namespace SuperPutty.Utils
{

    /// <summary>
    /// Helper class for PS support
    /// </summary>
    public class PSStartInfo
    {
        private static readonly ILog Log = LogManager.GetLogger(typeof(PSStartInfo));

        private SessionData session;

        public PSStartInfo(SessionData session)
        {
            this.session = session;
            this.Args = "";

            this.StartingDir = "%userprofile%";
        }

        public string Args { get; set; }
        public string StartingDir { get; set; }

    }
}


text:
import argparse
import matplotlib.pyplot as plt

DEF_P = 0.7 # Default max contentration
DEF_X0 = 0.10 # Default initial condition
DEF_ST = 0.001 # Default Step size
K = 0.04

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("-P", "--concentration",
                        help="Max concentration")
    parser.add_argument("-x", "--init",
                        help="Initial concentration")
    parser.add_argument("-s", "--step", help="Step")

    args = parser.parse_args()

    P = float(args.concentration) if args.concentration is not None else DEF_P
    x0 = float(args.init) if args.init is not None else DEF_X0
    h = float(args.step) if args.step is not None else DEF_ST

    x_axis, y_axis = range(10000), [x0]
    for i in range(9999):
        x_prev = y_axis[-1]
        x = h * K * (P - x_prev) + x_prev
        y_axis.append(x)

    plt.plot(y_axis)
    plt.title('Graphic')
    plt.show()


text:
if (typeof process !== "undefined") {
    require("amd-loader");
    require("./test/mockdom");
}

define(function (require, exports, module) {
    "use strict";
    var EditSession = require("./edit_session").EditSession;
    var Editor = require("./editor").Editor;
    var MockRenderer = require("./test/mockrenderer").MockRenderer;
    var MultiSelect = require("./multi_select").MultiSelect;

    var snippetManager = require("./snippets").snippetManager;
    var assert = require("./test/assertions");

    module.exports = {
        setUp: function (next) {
            this.editor = new Editor(new MockRenderer());
            next();
        },

        "test: textmate style format strings": function () {
            var fmt = snippetManager.tmStrFormat;
            snippetManager.tmStrFormat("hello", {
                guard: "(..)(.)(.)",
                flag: "g",
                fmt: "a\\UO\\l$1\\E$2"
            }) == "aOHElo";
        },
        "test: parse snipmate file": function () {
            var expected = [{
                name: "a",
                guard: "(?:(=)|(:))?\\s*)",
                trigger: "\\(?f",
                endTrigger: "\\)",
                endGuard: "",
                content: "{$0}\n"
            }, {
                tabTrigger: "f",
                name: "f function",
                content: "function"
            }];

            var parsed = snippetManager.parseSnippetFile(
                "name a\nregex /(?:(=)|(:))?\\s*)/\\(?f/\\)/\n\t{$0}" +
                "\n\t\n\n#function\nsnippet f function\n\tfunction"
            );

            assert.equal(JSON.stringify(expected, null, 4), JSON.stringify(parsed, null, 4))
        },
        "test: parse snippet": function () {
            var content = "-\\$$2a${1:x${$2:y$3\\}\\n\\}$TM_SELECTION}";
            var tokens = snippetManager.tokenizeTmSnippet(content);
            assert.equal(tokens.length, 15);
            assert.equal(tokens[4], tokens[14]);
            assert.equal(tokens[2].tabstopId, 2);

            var content = "\\}${var/as\\/d/\\ul\\//g:s}"
            var tokens = snippetManager.tokenizeTmSnippet(content);
            assert.equal(tokens.length, 4);
            assert.equal(tokens[1], tokens[3]);
            assert.equal(tokens[2], "s");
            assert.equal(tokens[1].text, "var");
            assert.equal(tokens[1].fmt, "\\ul\\/");
            assert.equal(tokens[1].guard, "as\\/d");
            assert.equal(tokens[1].flag, "g");
        },
        "test: expand snippet with nested tabstops": function () {
            var content = "-${1}-${1:t\n1}--${2:2 ${3} 2}-${3:3 $1 3}-${4:4 $2 4}";
            this.editor.setValue("");
            snippetManager.insertSnippet(this.editor, content);
            assert.equal(this.editor.getValue(), [
                "-t",
                "1-t",
                "1--2 3 t",
                "1 3 2-3 t",
                "1 3-4 2 3 t",
                "1 3 2 4"
            ].join("\n"));

            assert.equal(this.editor.getSelectedText(), "t\n1\nt\n1\nt\n1\nt\n1\nt\n1");
            this.editor.tabstopManager.tabNext();
            assert.equal(this.editor.getSelectedText(), "2 3 t\n1 3 2\n2 3 t\n1 3 2");
            this.editor.tabstopManager.tabNext();
            assert.equal(this.editor.getSelectedText(), "3 t\n1 3\n3 t\n1 3\n3 t\n1 3");
            this.editor.tabstopManager.tabNext();
            assert.equal(this.editor.getSelectedText(), "4 2 3 t\n1 3 2 4");
            this.editor.tabstopManager.tabNext();
            assert.equal(this.editor.getSelectedText(), "");

            this.editor.setValue("");
            snippetManager.insertSnippet(this.editor, "-${1:a$2}-${2:b$1}");
            assert.equal(this.editor.getValue(), "-ab-ba");

            assert.equal(this.editor.getSelectedText(), "ab\na");
            this.editor.tabstopManager.tabNext();
            assert.equal(this.editor.getSelectedText(), "b\nba");
            this.editor.tabstopManager.tabNext();
            assert.equal(this.editor.getSelectedText(), "");
        }
    };

});

if (typeof module !== "undefined" && module === require.main) {
    require("asyncjs").test.testcase(module.exports).exec()
}


text:
<?php

declare(strict_types=1);

namespace LizardsAndPumpkins\DataPool\SearchEngine\SearchCriteria;

interface SearchCriteria extends \JsonSerializable
{
    /**
     * @return mixed[]
     */
    public function toArray() : array;
}


text:
objective-c-snippets
====================

Objective-C Snippets


text:
'use strict';

/* global Connector */

Connector.playerSelector = '#playerContents';

Connector.artistSelector = '#songartist';

Connector.trackSelector = '#songtitle';

Connector.isPlaying = function () {
	return $('#playerPauseButton').length;
};


text:
define(function(require, exports, module) {

	exports.run = function() {
		$('input:radio[name="enabled"]').click(function(){
			var value = $('input:radio[name="enabled"]:checked').val();
			if(value == 1) {
				$("#sensitiveWordRules").show();
			} else {
				$("#sensitiveWordRules").hide();
			}
		})
	}

});