text:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "CSE333.h"
#include "HashTable.h"
#include "HashTable_priv.h"

// A private utility function to grow the hashtable (increase
// the number of buckets) if its load factor has become too high.
static void ResizeHashtable(HashTable ht);

// a free function that does nothing
static void LLNullFree(LLPayload_t freeme) {
}
static void HTNullFree(HTValue_t freeme) {
}

HashTable AllocateHashTable(HWSize_t num_buckets) {
  HashTable ht;
  HWSize_t  i;

  // defensive programming
  if (num_buckets == 0) {
    return NULL;
  }

  // allocate the hash table record
  ht = (HashTable) malloc(sizeof(HashTableRecord));
  if (ht == NULL) {
    return NULL;
  }

  // initialize the record
  ht->num_buckets = num_buckets;
  ht->num_elements = 0;
  ht->buckets =
    (LinkedList *) malloc(num_buckets * sizeof(LinkedList));
  if (ht->buckets == NULL) {
    // make sure we don't leak!
    free(ht);
    return NULL;
  }
  for (i = 0; i < num_buckets; i++) {
    ht->buckets[i] = AllocateLinkedList();
    if (ht->buckets[i] == NULL) {
      // allocating one of our bucket chain lists failed,
      // so we need to free everything we allocated so far
      // before returning NULL to indicate failure.  Since
      // we know the chains are empty, we'll pass in a
      // free function pointer that does nothing; it should
      // never be called.
      HWSize_t j;
      for (j = 0; j < i; j++) {
        FreeLinkedList(ht->buckets[j], LLNullFree);
      }
      free(ht);
      return NULL;
    }
  }

  return (HashTable) ht;
}

void FreeHashTable(HashTable table,
                   ValueFreeFnPtr value_free_function) {
  HWSize_t i;

  Verify333(table != NULL);  // be defensive

  // loop through and free the chains on each bucket
  for (i = 0; i < table->num_buckets; i++) {
    LinkedList  bl = table->buckets[i];
    HTKeyValue *nextKV;

    // pop elements off the the chain list, then free the list
    while (NumElementsInLinkedList(bl) > 0) {
      Verify333(PopLinkedList(bl, (LLPayload_t*)&nextKV));
      value_free_function(nextKV->value);
      free(nextKV);
    }
    // the chain list is empty, so we can pass in the
    // null free function to FreeLinkedList.
    FreeLinkedList(bl, LLNullFree);
  }

  // free the bucket array within the table record,
  // then free the table record itself.
  free(table->buckets);
  free(table);
}

HWSize_t NumElementsInHashTable(HashTable table) {
  Verify333(table != NULL);
  return table->num_elements;
}

HTKey_t FNVHash64(unsigned char *buffer, HWSize_t len) {
  // This code is adapted from code by Landon Curt Noll
  // and Bonelli Nicola:
  //
  // http://code.google.com/p/nicola-bonelli-repo/
  static const uint64_t FNV1_64_INIT = 0xcbf29ce484222325ULL;
  static const uint64_t FNV_64_PRIME = 0x100000001b3ULL;
  unsigned char *bp = (unsigned char *) buffer;
  unsigned char *be = bp + len;
  uint64_t hval = FNV1_64_INIT;

  /*
   * FNV-1a hash each octet of the buffer
   */
  while (bp < be) {
    /* xor the bottom with the current octet */
    hval ^= (uint64_t) * bp++;
    /* multiply by the 64 bit FNV magic prime mod 2^64 */
    hval *= FNV_64_PRIME;
  }
  /* return our new hash value */
  return hval;
}

HTKey_t FNVHashInt64(HTValue_t hashval) {
  unsigned char buf[8];
  int i;
  uint64_t hashme = (uint64_t)hashval;

  for (i = 0; i < 8; i++) {
    buf[i] = (unsigned char) (hashme & 0x00000000000000FFULL);
    hashme >>= 8;
  }
  return FNVHash64(buf, 8);
}

HWSize_t HashKeyToBucketNum(HashTable ht, HTKey_t key) {
  return key % ht->num_buckets;
}

LLIter FindKVInHashTable(LinkedList list, HTKey_t key)
{
  if (list == NULL) return NULL;
  if (NumElementsInLinkedList(list) == 0U) return NULL;
  LLIter iter = LLMakeIterator(list, 0);
  LLPayload_t payload = NULL;
  do {
    LLIteratorGetPayload(iter, &payload);
    Verify333(payload != NULL);

    HTKey_t nkey = ((HTKeyValue*) payload)->key;
    if (nkey == key)
      return iter;
  } while (LLIteratorNext(iter));
  LLIteratorFree(iter);
  return NULL;
}

int InsertHashTable(HashTable table,
                    HTKeyValue newkeyvalue,
                    HTKeyValue *oldkeyvalue) {
  HWSize_t insertbucket;
  LinkedList insertchain;

  Verify333(table != NULL);
  ResizeHashtable(table);

  // calculate which bucket we're inserting into,
  // grab its linked list chain
  insertbucket = HashKeyToBucketNum(table, newkeyvalue.key);
  insertchain = table->buckets[insertbucket];

  // Step 1 -- finish the implementation of InsertHashTable.
  // This is a fairly complex task, so you might decide you want
  // to define/implement a helper function that helps you find
  // and optionally remove a key within a chain, rather than putting
  // all that logic inside here.  You might also find that your helper
  // can be reused in steps 2 and 3.

  Verify333(insertchain != NULL);
  LLIter location = FindKVInHashTable(insertchain, newkeyvalue.key);

  if (location == NULL) {
    HTKeyValue* payload = (HTKeyValue*) malloc(sizeof(HTKeyValue));
    Verify333(payload != NULL);
    payload->key = newkeyvalue.key;
    payload->value = newkeyvalue.value;
    AppendLinkedList(insertchain, payload);
    table->num_elements += 1;
    return 1;
  } else {
    LLPayload_t payload = NULL;
    LLIteratorGetPayload(location, &payload);
    *oldkeyvalue = *((HTKeyValue*) payload);
    ((HTKeyValue*) payload)->key = newkeyvalue.key;
    ((HTKeyValue*) payload)->value = newkeyvalue.value;
    LLIteratorFree(location);
    return 2;
  }
  return 0;  // You may need to change this return value.
}

int LookupHashTable(HashTable table,
                    HTKey_t key,
                    HTKeyValue *keyvalue) {
  Verify333(table != NULL);

  // Step 2 -- implement LookupHashTable.
  HWSize_t insertbucket;
  LinkedList insertchain;

  insertbucket = HashKeyToBucketNum(table, key);
  insertchain = table->buckets[insertbucket];
  LLIter location = FindKVInHashTable(insertchain, key);
  if (location == NULL) return 0;

  LLPayload_t payload = NULL;
  LLIteratorGetPayload(location, &payload);
  *keyvalue = *((HTKeyValue*) payload);
  LLIteratorFree(location);
  return 1;  // you may need to change this return value.
}

int RemoveFromHashTable(HashTable table,
                        HTKey_t key,
                        HTKeyValue *keyvalue) {
  Verify333(table != NULL);

  // Step 3 -- implement RemoveFromHashTable.
  HWSize_t insertbucket;
  LinkedList insertchain;

  insertbucket = HashKeyToBucketNum(table, key);
  insertchain = table->buckets[insertbucket];
  LLIter location = FindKVInHashTable(insertchain, key);
  if (location == NULL) return 0;
  else {
    LLPayload_t payload = NULL;
    LLIteratorGetPayload(location, &payload);
    *keyvalue = *((HTKeyValue*) payload);
    LLIteratorDelete(location, free);
    table->num_elements -= 1;
    LLIteratorFree(location);
    return 1;
  }
  LLIteratorFree(location);
  return -1;  // you may need to change this return value.
}

HTIter HashTableMakeIterator(HashTable table) {
  HTIterRecord *iter;
  HWSize_t      i;

  Verify333(table != NULL);  // be defensive

  // malloc the iterator
  iter = (HTIterRecord *) malloc(sizeof(HTIterRecord));
  if (iter == NULL) {
    return NULL;
  }

  // if the hash table is empty, the iterator is immediately invalid,
  // since it can't point to anything.
  if (table->num_elements == 0) {
    iter->is_valid = false;
    iter->ht = table;
    iter->bucket_it = NULL;
    return iter;
  }

  // initialize the iterator.  there is at least one element in the
  // table, so find the first element and point the iterator at it.
  iter->is_valid = true;
  iter->ht = table;
  for (i = 0; i < table->num_buckets; i++) {
    if (NumElementsInLinkedList(table->buckets[i]) > 0) {
      iter->bucket_num = i;
      break;
    }
  }
  Verify333(i < table->num_buckets);  // make sure we found it.
  iter->bucket_it = LLMakeIterator(table->buckets[iter->bucket_num], 0UL);
  if (iter->bucket_it == NULL) {
    // out of memory!
    free(iter);
    return NULL;
  }
  return iter;
}

void HTIteratorFree(HTIter iter) {
  Verify333(iter != NULL);
  if (iter->bucket_it != NULL) {
    LLIteratorFree(iter->bucket_it);
    iter->bucket_it = NULL;
  }
  iter->is_valid = false;
  free(iter);
}

int HTIteratorNext(HTIter iter) {
  Verify333(iter != NULL);

  // Step 4 -- implement HTIteratorNext.
  if (!iter->is_valid) return 0;
  if (LLIteratorHasNext(iter->bucket_it)) {
    LLIteratorNext(iter->bucket_it);
    return 1;
  } else {
    iter->bucket_num++;
    if (iter->bucket_num >= iter->ht->num_buckets) {
      iter->is_valid = false;
      return 0;
    } else {
      for (; iter->bucket_num < iter->ht->num_buckets; ++iter->bucket_num) {
        LinkedList chain = iter->ht->buckets[iter->bucket_num];
        if (NumElementsInLinkedList(chain) != 0U) {
          if (iter->bucket_it != NULL)
            LLIteratorFree(iter->bucket_it);
          iter->bucket_it = LLMakeIterator(chain, 0);
          return 1;
        }
      }
    }
  }

  iter->is_valid = false;
  return 0;  // you might need to change this return value.
}

int HTIteratorPastEnd(HTIter iter) {
  Verify333(iter != NULL);

  // Step 5 -- implement HTIteratorPastEnd.
  if (!iter->is_valid) return 1;
  if (iter->bucket_it != NULL) return 0;

  return 1;  // you might need to change this return value.
}

int HTIteratorGet(HTIter iter, HTKeyValue *keyvalue) {
  Verify333(iter != NULL);

  // Step 6 -- implement HTIteratorGet.
  if (!iter->is_valid) return 0;

  LLPayload_t payload = NULL;
  LLIteratorGetPayload(iter->bucket_it, &payload);
  *keyvalue = *((HTKeyValue*) payload);
  return 1;  // you might need to change this return value.
}

int HTIteratorDelete(HTIter iter, HTKeyValue *keyvalue) {
  HTKeyValue kv;
  int res, retval;

  Verify333(iter != NULL);

  // Try to get what the iterator is pointing to.
  res = HTIteratorGet(iter, &kv);
  if (res == 0)
    return 0;

  // Advance the iterator.
  res = HTIteratorNext(iter);
  if (res == 0) {
    retval = 2;
  } else {
    retval = 1;
  }
  res = RemoveFromHashTable(iter->ht, kv.key, keyvalue);
  Verify333(res == 1);
  Verify333(kv.key == keyvalue->key);
  Verify333(kv.value == keyvalue->value);

  return retval;
}

static void ResizeHashtable(HashTable ht) {
  // Resize if the load factor is > 3.
  if (ht->num_elements < 3 * ht->num_buckets)
    return;

  // This is the resize case.  Allocate a new hashtable,
  // iterate over the old hashtable, do the surgery on
  // the old hashtable record and free up the new hashtable
  // record.
  HashTable newht = AllocateHashTable(ht->num_buckets * 9);

  // Give up if out of memory.
  if (newht == NULL)
    return;

  // Loop through the old ht with an iterator,
  // inserting into the new HT.
  HTIter it = HashTableMakeIterator(ht);
  if (it == NULL) {
    // Give up if out of memory.
    FreeHashTable(newht, &HTNullFree);
    return;
  }

  while (!HTIteratorPastEnd(it)) {
    HTKeyValue item, dummy;

    Verify333(HTIteratorGet(it, &item) == 1);
    if (InsertHashTable(newht, item, &dummy) != 1) {
      // failure, free up everything, return.
      HTIteratorFree(it);
      FreeHashTable(newht, &HTNullFree);
      return;
    }
    HTIteratorNext(it);
  }

  // Worked!  Free the iterator.
  HTIteratorFree(it);

  // Sneaky: swap the structures, then free the new table,
  // and we're done.
  {
    HashTableRecord tmp;

    tmp = *ht;
    *ht = *newht;
    *newht = tmp;
    FreeHashTable(newht, &HTNullFree);
  }

  return;
}


text:
package org.unitsheet.utils;

import org.junit.Test;

import static org.unitsheet.utils.FilePaths.fileExtension;
import static org.junit.Assert.assertEquals;

public class FilePathsTest {

    @Test
    public void checkFileExtensionHappyPath() {
        assertEquals("txt", fileExtension("test.txt"));
    }

    @Test
    public void checkFileExtensionWithNothingAfterDotIsEmptyString() {
        assertEquals("", fileExtension("test."));
    }

    @Test
    public void checkFileExtensionsIsNullWhenFileExtensionAbsent() {
        assertEquals(null, fileExtension("test"));
    }

    @Test
    public void checkFileExtensionsIsNullWhenFilenameNull() {
        assertEquals(null, fileExtension(null));
    }

}

redpajama_set_name: RedPajamaGithub


text:
.class public Lcom/android/internal/logging/EventLogTags;
.super Ljava/lang/Object;
.source "EventLogTags.java"

# static fields
.field public static final SYSUI_ACTION:I = 0x80000

.field public static final SYSUI_COUNT:I = 0x80002

.field public static final SYSUI_HISTOGRAM:I = 0x80003

.field public static final SYSUI_MULTI_ACTION:I = 0x80004

.field public static final SYSUI_VIEW_VISIBILITY:I = 0x7ffff

# direct methods
.method private constructor <init>()V
    .locals 0

    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method

.method public static writeSysuiAction(ILjava/lang/String;)V
    .locals 3

    const/4 v0, 0x2

    new-array v0, v0, [Ljava/lang/Object;

    invoke-static {p0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

    move-result-object v1

    const/4 v2, 0x0

    aput-object v1, v0, v2

    const/4 v1, 0x1

    aput-object p1, v0, v1

    const/high16 v1, 0x80000

    invoke-static {v1, v0}, Landroid/util/EventLog;->writeEvent(I[Ljava/lang/Object;)I

    return-void
.end method

.method public static writeSysuiCount(Ljava/lang/String;I)V
    .locals 3

    const/4 v0, 0x2

    new-array v0, v0, [Ljava/lang/Object;

    const/4 v1, 0x0

    aput-object p0, v0, v1

    invoke-static {p1}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

    move-result-object v1

    const/4 v2, 0x1

    aput-object v1, v0, v2

    const v1, 0x80002

    invoke-static {v1, v0}, Landroid/util/EventLog;->writeEvent(I[Ljava/lang/Object;)I

    return-void
.end method

.method public static writeSysuiHistogram(Ljava/lang/String;I)V
    .locals 3

    const/4 v0, 0x2

    new-array v0, v0, [Ljava/lang/Object;

    const/4 v1, 0x0

    aput-object p0, v0, v1

    invoke-static {p1}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

    move-result-object v1

    const/4 v2, 0x1

    aput-object v1, v0, v2

    const v1, 0x80003

    invoke-static {v1, v0}, Landroid/util/EventLog;->writeEvent(I[Ljava/lang/Object;)I

    return-void
.end method

.method public static writeSysuiMultiAction([Ljava/lang/Object;)V
    .locals 1

    const v0, 0x80004

    invoke-static {v0, p0}, Landroid/util/EventLog;->writeEvent(I[Ljava/lang/Object;)I

    return-void
.end method

.method public static writeSysuiViewVisibility(II)V
    .locals 3

    const/4 v0, 0x2

    new-array v0, v0, [Ljava/lang/Object;

    invoke-static {p0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

    move-result-object v1

    const/4 v2, 0x0

    aput-object v1, v0, v2

    invoke-static {p1}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

    move-result-object v1

    const/4 v2, 0x1

    aput-object v1, v0, v2

    const v1, 0x7ffff

    invoke-static {v1, v0}, Landroid/util/EventLog;->writeEvent(I[Ljava/lang/Object;)I

    return-void
.end method


text:
/*
 * $Id: XMLNumber.cpp 568078 2007-08-21 11:43:25Z amassari $
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMLNumber.hpp>

//since we need to dynamically created each and every derivatives
//during deserialization by XSerializeEngine>>Derivative, we got
//to include all hpp
#include <xercesc/util/XMLDouble.hpp>
#include <xercesc/util/XMLFloat.hpp>
#include <xercesc/util/XMLDateTime.hpp>
#include <xercesc/util/XMLBigDecimal.hpp>

XERCES_CPP_NAMESPACE_BEGIN

XMLNumber::XMLNumber()
{}

XMLNumber::XMLNumber(const XMLNumber& toCopy)
: XSerializable(toCopy)
, XMemory(toCopy)
{}

XMLNumber::~XMLNumber()
{}

/***
 * Support for Serialization/De-serialization
 ***/

IMPL_XSERIALIZABLE_NOCREATE(XMLNumber)

void XMLNumber::serialize(XSerializeEngine&)
{
    // this class has no data to serialize/de-serilize
}

XMLNumber* XMLNumber::loadNumber(XMLNumber::NumberType  numType
                               , XSerializeEngine&      serEng)
{

    switch((XMLNumber::NumberType) numType)
    {
    case XMLNumber::Float:
        XMLFloat* floatNum;
        serEng>>floatNum;
        return floatNum;
        break;
    case XMLNumber::Double:
        XMLDouble* doubleNum;
        serEng>>doubleNum;
        return doubleNum;
        break;
    case XMLNumber::BigDecimal:
        XMLBigDecimal* bigdecimalNum;
        serEng>>bigdecimalNum;
        return bigdecimalNum;
        break;
    case XMLNumber::DateTime:
        XMLDateTime* datetimeNum;
        serEng>>datetimeNum;
        return datetimeNum;
        break;
    case XMLNumber::UnKnown:
        return 0;
        break;
    default: //we treat this same as UnKnown
        return 0;
        break;
    }

}

XERCES_CPP_NAMESPACE_END


text:
#include	<QCoreApplication>
#include	<QStringList>
#include	<QSettings>
#include	<QDir>
#include	<QDebug>
#include	<april/cmd/aprilmodule.h>

#define	NO_ARGUMENT		QString()

/* ------------------------------------------------------------------------- */
static void		update_settings_file	( void )
{

	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"a.new",
				QStringList()
				<< "<kind>",
				QStringList()
				<< "create new actor instance",
				QStringList()
				<< "kind",
				QList<QStringList>()
				<< (QStringList()
					<< "the kind of the actor to produce;"
					<< "to create a kind use dna.new"),
				QStringList()
				<< "This function creates a new actor in current world."
				<< "The kind must be one that has an associated DNA."
				<< "The energy for the actor is taken from the free"
				<< "energy of the world."
				);
	april::AprilModule::setUsage(
				"a.list",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "lists actors in current world",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "This function lists actors in current world"
				<< "and some of their basic properties"
				<< "(id, name of the id, date of birth and death,"
				<< "current age and ammount of energy inside)."
				);
	april::AprilModule::setUsage(
				"a.kill",
				QStringList()
				<< "<index>",
				QStringList()
				<< "kills an actor in current world",
				QStringList()
				<< "index",
				QList<QStringList>()
				<< (QStringList()
					<< "the index of the actor in the world"),
				QStringList()
				<< "This function terminates an actor in current world"
				<< "(the actor may not be removed immediatelly but"
				<< "will be dead)."
				<< "The energy of the actor and of alll of its components"
				<< "will be added to the free energy of the current world."
				);
	april::AprilModule::setUsage(
				"a.kinds",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "list kinds of actors",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "The list of registered types of actors."
				<< "This function lists all types but a.new"
				<< "is only capable of creating actors"
				<< "of kinds created with dna.new"
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"ak.new",
				QStringList()
				<< "<actor> <id>",
				QStringList()
				<< "create new actuator instance",
				QStringList()
				<< "actor"
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "destination actor where new actuator is created;"
					<< "this is the offset of the actor in the world list")
				<< (QStringList()
					<< "the ID of the new actuator to create;"
					<< "if the id is invalid or represents a different"
					<< "component the function fails."),
				QStringList()
				<< "This function creates a new actuator in an actor"
				<< "in current world."
				<< "The energy for the actuator is taken from the free"
				<< "energy of the world."
				);
	april::AprilModule::setUsage(
				"ak.list",
				QStringList()
				<< "<actor>",
				QStringList()
				<< "lists actors in current world",
				QStringList()
				<< "actor",
				QList<QStringList>()
				<< (QStringList()
					<< "the actor who'se actuators are listed;"
					<< "this is the offset of the actor in the world list"),
				QStringList()
				<< "This function lists actuators in an actor in current world"
				<< "and some of their basic properties"
				<< "(id, name of the id, running cost and packed energy)."
				);
	april::AprilModule::setUsage(
				"ak.kinds",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "list kinds of actors",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "The list of registered types of actuators in current world."
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"april.commands",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "lists the commands",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "The command lists ALL commands that are registered"
				<< "with the command system. If a command is accesible"
				<< "it is present in this list."
				);
	april::AprilModule::setUsage(
				"april.modules",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "lists the modules",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "The command lists ALL modules that are registered"
				<< "with the command system. This lists the long names"
				<< "that can't be used in a real command - these often use"
				<< "shorter forms for the commands."
				);
	april::AprilModule::setUsage(
				"april.version",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "display the version",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	april::AprilModule::setUsage(
				"april.copyright",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "display information about copyright",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "The command prints the content of the COPYING"
				<< "file if found, otherwise ives general directions."
				);
	april::AprilModule::setUsage(
				"april.prompt",
				QStringList()
				<< "<new prompt>",
				QStringList()
				<< "changes current prompt to new value",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "Any string provided as argument will be"
				<< "printed at the beginning of each command line."
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"b.new",
				QStringList()
				<< "<actor> <id>",
				QStringList()
				<< "create new brain instance",
				QStringList()
				<< "actor"
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "destination actor where new brain is created;"
					<< "this is the offset of the actor in the world list")
				<< (QStringList()
					<< "the ID of the new brain to create;"
					<< "if the id is invalid or represents a different"
					<< "component the function fails."),
				QStringList()
				<< "This function creates a new brain in an actor"
				<< "in current world."
				<< "The energy for the brain is taken from the free"
				<< "energy of the world."
				);
	april::AprilModule::setUsage(
				"b.list",
				QStringList()
				<< "<actor>",
				QStringList()
				<< "lists actors in current world",
				QStringList()
				<< "actor",
				QList<QStringList>()
				<< (QStringList()
					<< "the actor who'se brains are listed;"
					<< "this is the offset of the actor in the world list"),
				QStringList()
				<< "This function lists brains in an actor in current world"
				<< "and some of their basic properties"
				<< "(id, name of the id, running cost and packed energy)."
				);
	april::AprilModule::setUsage(
				"b.kinds",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "list kinds of actors",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "The list of registered types of brains in current world."
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"dna.new",
				QStringList()
				<< "[id] [cost] [age] [energy]",
				QStringList()
				<< "creates a new kind",
				QStringList()
				<< "id"
				<< "cost"
				<< "age"
				<< "energy",
				QList<QStringList>()
				<< (QStringList()
					<< "the name to assign to the new numeric ID that"
					<< "will be generated. If ommited, a new, unique"
					<< "name will be generated."
					<< "A form like this is recomended: Actor.Kind.<name>.")
				<< (QStringList()
					<< "the intrinsec energy cost for the agent per time"
					<< "unit; other components that are added will"
					<< "increase the total cost for running the agent.n"
					<< "This value must be an integer larger than 0."
					<< "By default the cost is set to 10.")
				<< (QStringList()
					<< "average age of death. This is an orientative"
					<< "value (suggestion). It must be larger than 0."
					<< "By default it is set to 100.")
				<< (QStringList()
					<< "energy required at birth. At least this ammount"
					<< "of energy units are assigned at birt to an agent"
					<< "of this kind. When the user creates the agent,"
					<< "the energy is substracted from the free energy"
					<< "of the world."
					<< "By default it is set to 10.")
				,
				QStringList()
				);
	april::AprilModule::setUsage(
				"dna.list",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "lists available kinds in this world",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "These are the IDs that are available for a.new command."
				);
	april::AprilModule::setUsage(
				"dna.info",
				QStringList()
				<< "<id>",
				QStringList()
				<< "detalied information about a kind",
				QStringList()
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "An id previously registered using dna.new"),
				QStringList()
				<< "The function provides a lot of details about"
				<< "the DNA for a certain kind. This includes:"
				<< "- id and name"
				<< "- running cost for the actor"
				<< "- ammount of energy at birth"
				<< "- list of brains, reflexes, sensors and actuators"
				<< "- the list of partitions and details about them"
				);
	april::AprilModule::setUsage(
				"dna.s",
				QStringList()
				<< "<kind> <id>",
				QStringList()
				<< "add a sensor to a DNA sequence",
				QStringList()
				<< "kind"
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "A kind previously registered using dna.new (id)")
				<< (QStringList()
					<< "The id of the sensor to add; this id must be"
					<< "valid (the function checks it before proceeding)"),
				QStringList()
				<< "The actors created based on this DNA will all attempt"
				<< "to create for themselves a sensor of this kind."
				);
	april::AprilModule::setUsage(
				"dna.ak",
				QStringList()
				<< "<kind> <id>",
				QStringList()
				<< "add a actuator to a DNA sequence",
				QStringList()
				<< "kind"
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "A kind previously registered using dna.new (id)")
				<< (QStringList()
					<< "The id of the actuator to add; this id must be"
					<< "valid (the function checks it before proceeding)"),
				QStringList()
				<< "The actors created based on this DNA will all attempt"
				<< "to create for themselves a actuator of this kind."
				);
	april::AprilModule::setUsage(
				"dna.b",
				QStringList()
				<< "<kind> <id>",
				QStringList()
				<< "add a brain to a DNA sequence",
				QStringList()
				<< "kind"
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "A kind previously registered using dna.new (id)")
				<< (QStringList()
					<< "The id of the brain to add; this id must be"
					<< "valid (the function checks it before proceeding)"),
				QStringList()
				<< "The actors created based on this DNA will all attempt"
				<< "to create for themselves a brain of this kind."
				<< "Note that there is nothing stpping an actor to have"
				<< "more than one brains."
				);
	april::AprilModule::setUsage(
				"dna.r",
				QStringList()
				<< "<kind> <id>",
				QStringList()
				<< "add a reflex to a DNA sequence",
				QStringList()
				<< "kind"
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "A kind previously registered using dna.new (id)")
				<< (QStringList()
					<< "The id of the reflex to add; this id must be"
					<< "valid (the function checks it before proceeding)"),
				QStringList()
				<< "The actors created based on this DNA will all attempt"
				<< "to create for themselves a reflex of this kind."
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"e.new",
				QStringList()
				<< "<id>",
				QStringList()
				<< "create new event source",
				QStringList()
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "a previously registered id for the event to create;"
					<< "the function checks this id for validity before proceding."),
				QStringList()
				<< "This function creates a new event source"
				<< "in current world."
				);
	april::AprilModule::setUsage(
				"e.list",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "lists event sources in current world",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "This function lists event sources in current world"
				<< "and some of their basic properties"
				<< "(id, name of the id)."
				);
	april::AprilModule::setUsage(
				"e.kinds",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "list registered kinds of events",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "The list of registered types of event sources"
				<< "in current world."
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"id.new",
				QStringList()
				<< "<name>",
				QStringList()
				<< "create new unique id in current world",
				QStringList()
				<< "name",
				QList<QStringList>()
				<< (QStringList()
					<< "the string to be associated with the new"
					<< "numeric id that will be created."),
				QStringList()
				<< "This function will check if that name"
				<< "is already associted with an id and will"
				<< "refuse to create the id if that is the case."
				);
	april::AprilModule::setUsage(
				"id.list",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "lists registered IDs in current world",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "Along with the numeric value the strings"
				<< "associated with them are also printed."
				);
	april::AprilModule::setUsage(
				"id.info",
				QStringList()
				<< "<id>",
				QStringList()
				<< "information about this id",
				QStringList()
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "An id previously registered with id.new"
					<< "or with other functions that register IDs"),
				QStringList()
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"p.load",
				QStringList()
				<< "<file-name>" ,
				QStringList()
				<< "loads specified plug-in file",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	april::AprilModule::setUsage(
				"p.unload",
				QStringList()
				<< "<index>"
				<< "<name>" ,
				QStringList()
				<< "unloads the plug-in at specified index"
				<< "unloads the plug-in having that name",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	april::AprilModule::setUsage(
				"p.list",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "lists the plug-ins and their paths",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"r.new",
				QStringList()
				<< "<actor> <id>",
				QStringList()
				<< "create new reflex instance",
				QStringList()
				<< "actor"
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "destination actor where new reflex is created;"
					<< "this is the offset of the actor in the world list")
				<< (QStringList()
					<< "the ID of the new reflex to create;"
					<< "if the id is invalid or represents a different"
					<< "component the function fails."),
				QStringList()
				<< "This function creates a new reflex in an actor"
				<< "in current world."
				<< "The energy for the reflex is taken from the free"
				<< "energy of the world."
				);
	april::AprilModule::setUsage(
				"r.list",
				QStringList()
				<< "<actor>",
				QStringList()
				<< "lists actors in current world",
				QStringList()
				<< "actor",
				QList<QStringList>()
				<< (QStringList()
					<< "the actor who'se reflexs are listed;"
					<< "this is the offset of the actor in the world list"),
				QStringList()
				<< "This function lists reflexs in an actor in current world"
				<< "and some of their basic properties"
				<< "(id, name of the id, running cost and packed energy)."
				);
	april::AprilModule::setUsage(
				"r.kinds",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "list kinds of actors",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "The list of registered types of reflexs in current world."
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"s.new",
				QStringList()
				<< "<actor> <id>",
				QStringList()
				<< "create new sensor instance",
				QStringList()
				<< "actor"
				<< "id",
				QList<QStringList>()
				<< (QStringList()
					<< "destination actor where new sensor is created;"
					<< "this is the offset of the actor in the world list")
				<< (QStringList()
					<< "the ID of the new sensor to create;"
					<< "if the id is invalid or represents a different"
					<< "component the function fails."),
				QStringList()
				<< "This function creates a new sensor in an actor"
				<< "in current world."
				<< "The energy for the sensor is taken from the free"
				<< "energy of the world."
				);
	april::AprilModule::setUsage(
				"s.list",
				QStringList()
				<< "<actor>",
				QStringList()
				<< "lists actors in current world",
				QStringList()
				<< "actor",
				QList<QStringList>()
				<< (QStringList()
					<< "the actor who'se sensors are listed;"
					<< "this is the offset of the actor in the world list"),
				QStringList()
				<< "This function lists sensors in an actor in current world"
				<< "and some of their basic properties"
				<< "(id, name of the id, running cost and packed energy)."
				);
	april::AprilModule::setUsage(
				"s.kinds",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "list kinds of actors",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				<< "The list of registered types of sensors in current world."
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */
	april::AprilModule::setUsage(
				"w.new",
				QStringList()
				<< NO_ARGUMENT
				<< "[name] [energy]" ,
				QStringList()
				<< "creates a new world with default values"
				<< "creates a world with given name and energy",
				QStringList()
				<< "name"
				<< "energy",
				QList<QStringList>()
				<< (QStringList()
					<< "the name of the world; this will identify the"
					<< "world in future dialogs; when no name is given"
					<< "an unique one is generated;")
				<< (QStringList()
					<< "the ammount of energy in the world; this must be"
					<< "a positive integer. In order to set the energy"
					<< "you MUST set a name. By default the energy is set"
					<< "to 100000 units."),
				QStringList()
				);
	april::AprilModule::setUsage(
				"w.open",
				QStringList()
				<< "<file-name>" ,
				QStringList()
				<< "opens specified file and loads the world inside",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	april::AprilModule::setUsage(
				"w.save",
				QStringList()
				<< "<name> [file]"
				<< "<index> [file]" ,
				QStringList()
				<< "saves specified world to a file"
				<< "saves specified world to a file",
				QStringList()
				<< "name"
				<< "energy",
				QList<QStringList>()
				<< (QStringList()
					<< "the name of the world.")
				<< (QStringList()
					<< "where to save; if not specified the"
					<< "file asociated with the world is used."),
				QStringList()
				<< "If the opperation is succefull the internal association"
				<< "is also updated."
				);
	april::AprilModule::setUsage(
				"w.close",
				QStringList()
				<< "<index>"
				<< "<name>" ,
				QStringList()
				<< "close the world at specified index"
				<< "close the world having that name",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	april::AprilModule::setUsage(
				"w.list",
				QStringList()
				<< NO_ARGUMENT,
				QStringList()
				<< "lists the worlds and basic properties",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	april::AprilModule::setUsage(
				"w.start",
				QStringList()
				<< "<index>"
				<< "<name>" ,
				QStringList()
				<< "starts the world at specified index"
				<< "starts the world having that name",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	april::AprilModule::setUsage(
				"w.stop",
				QStringList()
				<< "<index>"
				<< "<name>" ,
				QStringList()
				<< "stops the world at specified index"
				<< "stops the world having that name",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	april::AprilModule::setUsage(
				"w.adv",
				QStringList()
				<< "<index> [steps]"
				<< "<name> [steps]" ,
				QStringList()
				<< "advances the world at specified index 'steps' time units"
				<< "advances the world having that name 'steps' time units",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	april::AprilModule::setUsage(
				"w.crt",
				QStringList()
				<< NO_ARGUMENT
				<< "<index>"
				<< "<name>" ,
				QStringList()
				<< "prints the name of current world"
				<< "changes current world to the one indicated by index"
				<< "changes current world to the one indicated by name",
				QStringList(),
				QList<QStringList>(),
				QStringList()
				);
	/* 000000000000000000000000000000000000000000000000000000000000000000000 */

	qDebug() << "help.dat was updated\n";
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
static void				print_all_settings			( void )
{
	QSettings	stg( "help.dat", QSettings::IniFormat );
	QStringList sl = stg.childGroups();
	sl.sort();
	foreach( QString s, sl )
	{
		qDebug() << QString( 2, QChar( '\n' ) ).toLatin1().constBegin();
		qDebug() << QString( 80, QChar( '=' ) ).toLatin1().constBegin();
		qDebug() << QString( ">" + s + " help" ).toLatin1().constBegin();
		qDebug() << april::AprilModule::getCLUsage( s ).toLatin1().constBegin();
		qDebug() << QString( 80, QChar( '=' ) ).toLatin1().constBegin();
	}
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
static QString				properDoxString		( const QString & s_in )
{
	QString s_out = s_in;
	s_out.replace( "<", "\\<" );
	s_out.replace( ">", "\\> " );
	return s_out;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
static void				update_documentation		( void )
{
	static QString s_key_1 = "This is where automatic process places command documentation.";
	static QString s_key_2 = "@if hide_cmd_marker";
	static QString s_key_e = "@endif";

	/* start with current directory in build area */
	QDir	d("../../april/april/docs/commands");
	if ( d.exists() == false )
	{
		qDebug() << "Could not locate documentation directory\n"
				 << d.absolutePath()
				 << "Documentation not updated\n";
		return;
	}

	QSettings	stg( "help.dat", QSettings::IniFormat );
	QStringList sl_all = stg.childGroups();
	if ( sl_all.isEmpty() )
	{
		qDebug() << "Please generate documentation in help.dat file (u command).\n"
				 << "Documentation not updated\n";
		return;
	}

	/* get a list of modules */
	QString s_mod_in_cmd;
	QMap<QString,QStringList>	mod_map;
	foreach( QString s_cmd, sl_all )
	{
		int i_dot = s_cmd.indexOf( '.' );
		if ( i_dot > 0 )
		{
			s_mod_in_cmd = s_cmd.mid( 0, i_dot );
			if ( mod_map.contains( s_mod_in_cmd ) )
			{
				QStringList & cmd_l = mod_map[s_mod_in_cmd];
				cmd_l.append( s_cmd );
			}
			else
			{
				mod_map.insert( s_mod_in_cmd, QStringList( s_cmd ) );
			}
		}
	}

	/* for each module open its dox file */
	QMap<QString,QStringList>::ConstIterator itr = mod_map.constBegin();
	QMap<QString,QStringList>::ConstIterator itr_e = mod_map.constEnd();
	while ( itr != itr_e )
	{
		QString s_file = d.absoluteFilePath( itr.key() + ".dox" );
		const QStringList & sl_commands = itr.value();
		if ( d.exists( s_file ) == false )
		{
			QFile::copy(
						d.absoluteFilePath( "./module.dox.template" ),
						s_file );
		}

		QFile f( s_file );
		if ( f.open( QIODevice::ReadWrite ) == false )
		{
			qDebug() << "Failed to open dox file " << s_file << "\n"
					 << f.errorString()
					 << "Documentation not updated\n";
			return;
		}

		enum Stat {
			StsWaitSecStart,
			StsWaitEnd1,
			StsInsideArea,
			StsOutsideArea
		};

		QString s_usage;
		QString s_usage_descr;
		QString s_opt;
		QStringList s_opt_descr;
		QStringList s_obs;

		QString s_file_cont( f.readAll() );
		QStringList s_lines = s_file_cont.split( '\n' );
		QStringList s_lines_out;
		int i_max = s_lines.count();
		Stat sts = StsWaitSecStart;
		for ( int i = 0; i < i_max; i++ )
		{
			switch ( sts ) {
			case StsWaitSecStart:	{
				if ( s_lines.at( i ) == s_key_1 )
				{
					sts = StsWaitEnd1;
				}
				s_lines_out.append( s_lines.at( i ) );
				break; }
			case StsWaitEnd1:	{
				if ( s_lines.at( i ) == s_key_e )
				{
					sts = StsInsideArea;
				}
				s_lines_out.append( s_lines.at( i ) );
				break; }
			case StsInsideArea:	{
				if ( s_lines.at( i ) == s_key_2 )
				{
					sts = StsOutsideArea;

					foreach( QString s_iter_cmd, sl_commands ) {
						stg.beginGroup( s_iter_cmd );
						QString s_sec_name = s_iter_cmd;
						s_sec_name.replace( '.', '_' );

						s_lines_out.append( QString() );
						s_lines_out.append( "<br><br>" );
						s_lines_out.append( "\\section " + s_sec_name + " " + s_iter_cmd );
						s_lines_out.append( QString() );

						/* -------------------------- */
						s_obs = stg.value( "Observations" ).toStringList();
						if ( s_obs.count() > 0 )
						{
							//s_lines_out.append( "\\subsection " + s_sec_name + "_obs Observations" );
							s_lines_out.append( QString() );

							s_lines_out.append( properDoxString( s_obs.join( '\n' ) ) );
						}

						/* -------------------------- */
						s_lines_out.append( "\\subsection " + s_sec_name + "_usage Usage" );
						s_lines_out.append( QString() );
						s_lines_out.append( "<table width=\"70%\">" );
						int usg_max = stg.beginReadArray( "Usage" );
						for ( int j = 0; j < usg_max; j++ )
						{
							stg.setArrayIndex( j );
							s_usage = properDoxString( stg.value( "cmd" ).toString() );
							s_usage_descr = properDoxString( stg.value( "descr" ).toString() );
							s_lines_out.append(
										QString( "<tr><td width=\"30%\">%1</td><td>%2</td></tr>" )
										.arg( s_usage )
										.arg( s_usage_descr )
										);
						}
						stg.endArray(); // Usage
						s_lines_out.append( "</table>" );

						/* -------------------------- */
						int opt_max = stg.beginReadArray( "Options" );
						if ( opt_max > 0 )
						{
							s_lines_out.append( "\\subsection " + s_sec_name + "_opts Options" );
							s_lines_out.append( QString() );

							s_lines_out.append( "<table width=\"70%\">" );
							for ( int j = 0; j < opt_max; j++ )
							{
								stg.setArrayIndex( j );
								s_opt = properDoxString( stg.value( "opt" ).toString() );
								s_opt_descr = stg.value( "descr" ).toStringList();
								s_lines_out.append(
											QString( "<tr><td width=\"30%\">%1</td><td>%2</td></tr>" )
											.arg( s_opt )
											.arg( properDoxString( s_opt_descr.join( '\n' ) ) )
											);
							}
							s_lines_out.append( "</table>" );
						}
						stg.endArray(); // Options
						stg.endGroup();

					}

					s_lines_out.append( s_lines.at( i ) );
					break;
				}
				break; }
			case StsOutsideArea:	{
				s_lines_out.append( s_lines.at( i ) );
				break; }
			}
		}

		f.seek( 0 );
		f.write( s_lines_out.join( '\n' ).toLatin1() );
		f.close();

		itr++;
	}

	qDebug() << "documentation was updated\n";
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
//! application entry point
int			main			( int argc, char *argv[] )
{
	int i_ret = 0;

	/* prepare to start */
	QCoreApplication apl( argc, argv );
	Q_UNUSED( apl );

	for ( ;; )
	{
		if ( argc < 2 )
		{
			update_settings_file();
			print_all_settings();
			return 0;
		}
		else if ( argc > 3 )
		{
			qDebug() << "Invalid number of arguments!";
			break;
		}
		else
		{
			QString s_cmd( argv[1] );
			s_cmd = s_cmd.toLower();
			if ( ( s_cmd == "u" ) || ( s_cmd == "update" ) )
			{
				update_settings_file();
				return 0;
			}
			else if (
					 ( s_cmd == "?" ) ||
					 ( s_cmd == "/?" ) ||
					 ( s_cmd == "h" ) ||
					 ( s_cmd == "help" )  ||
					 ( s_cmd == "--help" ) )
			{
				break;
			}
			else if (
					 ( s_cmd == "p" ) ||
					 ( s_cmd == "print" ) )
			{
				print_all_settings();
				return 0;
			}
			else if (
					 ( s_cmd == "d" ) ||
					 ( s_cmd == "docs" ) )
			{
				update_documentation();
				return 0;
			}
			else
			{
				qDebug() << "Unknown command!";
				break;
			}
		}
		Q_ASSERT(false);
	}
	qDebug() << "Usage:\n"
			 << "april-cmd-help ?      prints this help message\n"
			 << "april-cmd-help u      update the commands in help.dat file\n"
			 << "april-cmd-help p      print commands from help.dat to console\n"
			 << "april-cmd-help d      update dox files from help.dat\n"
				;

	return i_ret;
}
/* ========================================================================= */


text:
package org.kohsuke.stapler.export;

import static org.junit.Assert.assertEquals;

import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.junit.Test;

public class ModelTest {
    private ExportConfig config = new ExportConfig()
            .withClassAttribute(ClassAttributeBehaviour.ALWAYS.simple());
    ModelBuilder builder = new ModelBuilder();

    @Test // JENKINS-26775
    public void sytheticMethodShouldNotBeExported() {
        Model<Impl> model = builder.get(Impl.class);
        assertEquals("Redundant properties discovered: " + model.getProperties(), 1, model.getProperties().size());
    }

    public static interface GenericInterface<T extends Number> {
        Collection<T> get();
    }

    @ExportedBean
    public static class Impl implements GenericInterface<Integer> {
        @Exported
        public List<Integer> get() {
            return Arrays.asList(42);
        }
    }

    //===========================================

    @Test
    public void merge() throws Exception {
        StringWriter sw = new StringWriter();
        builder.get(B.class).writeTo(b, Flavor.JSON.createDataWriter(b, sw, config));
        // B.x should maskc C.x, so x should be 40
        // but C.y should be printed as merged
        assertEquals("{'_class':'B','y':20,'z':30,'x':40}", sw.toString().replace('"','\''));
    }

    /**
     * y is a property from a merged object but that shouldn't be visible to {@link NamedPathPruner}.
     */
    @Test
    public void merge_pathPrune() throws Exception {
        StringWriter sw = new StringWriter();
        builder.get(B.class).writeTo(b, new NamedPathPruner("z,y"), Flavor.JSON.createDataWriter(b, sw, config));
        assertEquals("{'_class':'B','y':20,'z':30}", sw.toString().replace('"','\''));
    }

    B b = new B();
    public static class B extends A {
        @Exported
        public int x = 40;
    }

    @ExportedBean
    public static class A {
        @Exported(merge=true)
        public C c = new C();

        @Exported
        public int z = 30;
    }

    @ExportedBean
    public static class C {
        @Exported public int x = 10;
        @Exported public int y = 20;
    }

    //===========================================

    @Test
    public void skipNull() throws Exception {
        StringWriter sw = new StringWriter();
        SomeNullProperty o = new SomeNullProperty();
        builder.get(SomeNullProperty.class).writeTo(o, TreePruner.DEFAULT, Flavor.JSON.createDataWriter(o, sw, config));
        assertEquals("{'_class':'SomeNullProperty','bbb':'bbb','ccc':null,'ddd':'ddd'}", sw.toString().replace('"','\''));
    }

    @ExportedBean
    public static class SomeNullProperty {
        @Exported(skipNull=true)
        public String aaa = null;

        @Exported(skipNull=true)
        public String bbb = "bbb";

        @Exported(skipNull=false)
        public String ccc = null;

        @Exported(skipNull=false)
        public String ddd = "ddd";
    }
}


text:
//
//  PBVersionInfo.h
//  PebbleKit
//
//  Created by Marcel Jackwerth on 20/08/15.
//  Copyright (c) 2015 Pebble Technology. All rights reserved.
//

#import <PebbleKit/PBDefines.h>
#import <Foundation/Foundation.h>

#import <PebbleKit/PBFirmwareVersion.h>
#import <PebbleKit/PBFirmwareMetadata.h>
#import <PebbleKit/PBResourceMetadata.h>

typedef NS_OPTIONS(uint64_t, PBRemoteProtocolCapabilitiesFlags) {
  PBRemoteProtocolCapabilitiesFlagsAppRunState                 = 1 << 0,
  PBRemoteProtocolCapabilitiesFlagsInfiniteLogDumping          = 1 << 1, // unused
  PBRemoteProtocolCapabilitiesFlagsUpdateMusicProtocol         = 1 << 2, // unused
  PBRemoteProtocolCapabilitiesFlagsExtendedNotificationService = 1 << 3, // unused
  PBRemoteProtocolCapabilitiesFlagsLanguagePacksSupported      = 1 << 4, // unused
  PBRemoteProtocolCapabilitiesFlagsAppMessage8kSupported       = 1 << 5,
  PBRemoteProtocolCapabilitiesFlagsInsightsSupport             = 1 << 6,
  PBRemoteProtocolCapabilitiesFlagsThirdPartyVoiceSupported    = 1 << 7,
};

NS_ASSUME_NONNULL_BEGIN

/**
 *  An instance of PBVersionInfo describes all the different system software (Pebble OS)
 *  on a Pebble watch and other auxiliary information.
 *  @see PBWatch
 */
PB_EXTERN_CLASS @interface PBVersionInfo : NSObject

/**
 *  The metadata of the firmware that is running.
 */
@property (nonatomic, readonly, strong) PBFirmwareMetadata *runningFirmwareMetadata;

/**
 *  The metadata of the recovery firmware that is in storage.
 */
@property (nonatomic, readonly, strong) PBFirmwareMetadata *recoveryFirmwareMetadata;

/**
 *  The metadata of the system resources.
 */
@property (nonatomic, readonly, strong) PBResourceMetadata *systemResources;

/**
 *  The version of the bootloader.
 */
@property (nonatomic, readonly) UInt32 bootloaderVersion;

/**
 *  The version of the hardware.
 */
@property (nonatomic, readonly, strong) NSString *hardwareVersion;

/**
 *  The serial number.
 */
@property (nonatomic, readonly, strong) NSString *serialNumber;

/**
 *  The current Bluetooth device address.
 */
@property (nonatomic, readonly, strong) NSData *deviceAddress;

/**
 *  Flags for the supported protocol features of the watch.
 */
@property (nonatomic, readonly, assign) PBRemoteProtocolCapabilitiesFlags remoteProtocolCapabilitiesFlags;

/**
 *  Indicates if the previous connection for the watch was to this device.
 *
 *  If the watch has been connected to this device, but connects to other
 *  device before connecting again to this device, the value will be YES.
 */
@property (nonatomic, readonly, assign) BOOL hasBeenUnfaithful;

/**
 *  YES if valid recovery firmware is installed, NO if not.
 */
- (BOOL)hasRecoveryFirmware;

/**
 *  YES if valid system resources are installed, NO if not.
 */
- (BOOL)hasSystemResources;

/**
 *  YES if app messages are supported, NO if not.
 */
- (BOOL)appMessagesSupported;

@end

NS_ASSUME_NONNULL_END


text:
package com.google.cloud.language.v1;

import com.google.api.core.BetaApi;
import com.google.api.gax.core.BackgroundResource;
import com.google.api.gax.rpc.UnaryCallable;
import com.google.cloud.language.v1.AnnotateTextRequest.Features;
import com.google.cloud.language.v1.stub.LanguageServiceStub;
import com.google.cloud.language.v1.stub.LanguageServiceStubSettings;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Generated;

// AUTO-GENERATED DOCUMENTATION AND SERVICE
/**
 * Service Description: Provides text analysis operations such as sentiment analysis and entity
 * recognition.
 *
 *
This class provides the ability to make remote calls to the backing service through method
 * calls that map to API methods. Sample code to get started:
 *
 *

 *
 * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
 *   Document document = Document.newBuilder().build();
 *   AnalyzeSentimentResponse response = languageServiceClient.analyzeSentiment(document);
 * }
 *
 *

 *
 *
Note: close() needs to be called on the languageServiceClient object to clean up resources
 * such as threads. In the example above, try-with-resources is used, which automatically calls
 * close().
 *
 *
The surface of this class includes several types of Java methods for each of the API's
 * methods:
 *
 *

 *
 A "flattened" method. With this type of method, the fields of the request type have been
 *       converted into function parameters. It may be the case that not all fields are available as
 *       parameters, and not every API method will have a flattened method entry point.
 *
 A "request object" method. This type of method only takes one parameter, a request object,
 *       which must be constructed before the call. Not every API method will have a request object
 *       method.
 *
 A "callable" method. This type of method takes no parameters and returns an immutable API
 *       callable object, which can be used to initiate calls to the service.
 *

 *
 *
See the individual methods for example code.
 *
 *
Many parameters require resource names to be formatted in a particular way. To assist with
 * these names, this class includes a format method for each type of name, and additionally a parse
 * method to extract the individual identifiers contained within names that are returned.
 *
 *
This class can be customized by passing in a custom instance of LanguageServiceSettings to
 * create(). For example:
 *
 *
To customize credentials:
 *
 *

 *
 * LanguageServiceSettings languageServiceSettings =
 *     LanguageServiceSettings.newBuilder()
 *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
 *         .build();
 * LanguageServiceClient languageServiceClient =
 *     LanguageServiceClient.create(languageServiceSettings);
 *
 *

 *
 * To customize the endpoint:
 *
 *

 *
 * LanguageServiceSettings languageServiceSettings =
 *     LanguageServiceSettings.newBuilder().setEndpoint(myEndpoint).build();
 * LanguageServiceClient languageServiceClient =
 *     LanguageServiceClient.create(languageServiceSettings);
 *
 *

 */
@Generated("by gapic-generator")
public class LanguageServiceClient implements BackgroundResource {
  private final LanguageServiceSettings settings;
  private final LanguageServiceStub stub;

  /** Constructs an instance of LanguageServiceClient with default settings. */
  public static final LanguageServiceClient create() throws IOException {
    return create(LanguageServiceSettings.newBuilder().build());
  }

  /**
   * Constructs an instance of LanguageServiceClient, using the given settings. The channels are
   * created based on the settings passed in, or defaults for any settings that are not set.
   */
  public static final LanguageServiceClient create(LanguageServiceSettings settings)
      throws IOException {
    return new LanguageServiceClient(settings);
  }

  /**
   * Constructs an instance of LanguageServiceClient, using the given stub for making calls. This is
   * for advanced usage - prefer to use LanguageServiceSettings}.
   */
  @BetaApi("A restructuring of stub classes is planned, so this may break in the future")
  public static final LanguageServiceClient create(LanguageServiceStub stub) {
    return new LanguageServiceClient(stub);
  }

  /**
   * Constructs an instance of LanguageServiceClient, using the given settings. This is protected so
   * that it is easy to make a subclass, but otherwise, the static factory methods should be
   * preferred.
   */
  protected LanguageServiceClient(LanguageServiceSettings settings) throws IOException {
    this.settings = settings;
    this.stub = ((LanguageServiceStubSettings) settings.getStubSettings()).createStub();
  }

  @BetaApi("A restructuring of stub classes is planned, so this may break in the future")
  protected LanguageServiceClient(LanguageServiceStub stub) {
    this.settings = null;
    this.stub = stub;
  }

  public final LanguageServiceSettings getSettings() {
    return settings;
  }

  @BetaApi("A restructuring of stub classes is planned, so this may break in the future")
  public LanguageServiceStub getStub() {
    return stub;
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Analyzes the sentiment of the provided text.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnalyzeSentimentResponse response = languageServiceClient.analyzeSentiment(document);
   * }
   *

   *
   * @param document Input document.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final AnalyzeSentimentResponse analyzeSentiment(Document document) {

    AnalyzeSentimentRequest request =
        AnalyzeSentimentRequest.newBuilder().setDocument(document).build();
    return analyzeSentiment(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Analyzes the sentiment of the provided text.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnalyzeSentimentRequest request = AnalyzeSentimentRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   AnalyzeSentimentResponse response = languageServiceClient.analyzeSentiment(request);
   * }
   *

   *
   * @param request The request object containing all of the parameters for the API call.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  private final AnalyzeSentimentResponse analyzeSentiment(AnalyzeSentimentRequest request) {
    return analyzeSentimentCallable().call(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Analyzes the sentiment of the provided text.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnalyzeSentimentRequest request = AnalyzeSentimentRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   ApiFuture<AnalyzeSentimentResponse> future = languageServiceClient.analyzeSentimentCallable().futureCall(request);
   *   // Do something
   *   AnalyzeSentimentResponse response = future.get();
   * }
   *

   */
  public final UnaryCallable<AnalyzeSentimentRequest, AnalyzeSentimentResponse>
      analyzeSentimentCallable() {
    return stub.analyzeSentimentCallable();
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Finds named entities (currently proper names and common nouns) in the text along with entity
   * types, salience, mentions for each entity, and other properties.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   EncodingType encodingType = EncodingType.NONE;
   *   AnalyzeEntitiesResponse response = languageServiceClient.analyzeEntities(document, encodingType);
   * }
   *

   *
   * @param document Input document.
   * @param encodingType The encoding type used by the API to calculate offsets.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final AnalyzeEntitiesResponse analyzeEntities(
      Document document, EncodingType encodingType) {

    AnalyzeEntitiesRequest request =
        AnalyzeEntitiesRequest.newBuilder()
            .setDocument(document)
            .setEncodingType(encodingType)
            .build();
    return analyzeEntities(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Finds named entities (currently proper names and common nouns) in the text along with entity
   * types, salience, mentions for each entity, and other properties.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnalyzeEntitiesRequest request = AnalyzeEntitiesRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   AnalyzeEntitiesResponse response = languageServiceClient.analyzeEntities(request);
   * }
   *

   *
   * @param request The request object containing all of the parameters for the API call.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final AnalyzeEntitiesResponse analyzeEntities(AnalyzeEntitiesRequest request) {
    return analyzeEntitiesCallable().call(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Finds named entities (currently proper names and common nouns) in the text along with entity
   * types, salience, mentions for each entity, and other properties.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnalyzeEntitiesRequest request = AnalyzeEntitiesRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   ApiFuture<AnalyzeEntitiesResponse> future = languageServiceClient.analyzeEntitiesCallable().futureCall(request);
   *   // Do something
   *   AnalyzeEntitiesResponse response = future.get();
   * }
   *

   */
  public final UnaryCallable<AnalyzeEntitiesRequest, AnalyzeEntitiesResponse>
      analyzeEntitiesCallable() {
    return stub.analyzeEntitiesCallable();
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Finds entities, similar to
   * [AnalyzeEntities][google.cloud.language.v1.LanguageService.AnalyzeEntities] in the text and
   * analyzes sentiment associated with each entity and its mentions.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   EncodingType encodingType = EncodingType.NONE;
   *   AnalyzeEntitySentimentResponse response = languageServiceClient.analyzeEntitySentiment(document, encodingType);
   * }
   *

   *
   * @param document Input document.
   * @param encodingType The encoding type used by the API to calculate offsets.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final AnalyzeEntitySentimentResponse analyzeEntitySentiment(
      Document document, EncodingType encodingType) {

    AnalyzeEntitySentimentRequest request =
        AnalyzeEntitySentimentRequest.newBuilder()
            .setDocument(document)
            .setEncodingType(encodingType)
            .build();
    return analyzeEntitySentiment(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Finds entities, similar to
   * [AnalyzeEntities][google.cloud.language.v1.LanguageService.AnalyzeEntities] in the text and
   * analyzes sentiment associated with each entity and its mentions.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnalyzeEntitySentimentRequest request = AnalyzeEntitySentimentRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   AnalyzeEntitySentimentResponse response = languageServiceClient.analyzeEntitySentiment(request);
   * }
   *

   *
   * @param request The request object containing all of the parameters for the API call.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final AnalyzeEntitySentimentResponse analyzeEntitySentiment(
      AnalyzeEntitySentimentRequest request) {
    return analyzeEntitySentimentCallable().call(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Finds entities, similar to
   * [AnalyzeEntities][google.cloud.language.v1.LanguageService.AnalyzeEntities] in the text and
   * analyzes sentiment associated with each entity and its mentions.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnalyzeEntitySentimentRequest request = AnalyzeEntitySentimentRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   ApiFuture<AnalyzeEntitySentimentResponse> future = languageServiceClient.analyzeEntitySentimentCallable().futureCall(request);
   *   // Do something
   *   AnalyzeEntitySentimentResponse response = future.get();
   * }
   *

   */
  public final UnaryCallable<AnalyzeEntitySentimentRequest, AnalyzeEntitySentimentResponse>
      analyzeEntitySentimentCallable() {
    return stub.analyzeEntitySentimentCallable();
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Analyzes the syntax of the text and provides sentence boundaries and tokenization along with
   * part of speech tags, dependency trees, and other properties.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   EncodingType encodingType = EncodingType.NONE;
   *   AnalyzeSyntaxResponse response = languageServiceClient.analyzeSyntax(document, encodingType);
   * }
   *

   *
   * @param document Input document.
   * @param encodingType The encoding type used by the API to calculate offsets.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final AnalyzeSyntaxResponse analyzeSyntax(Document document, EncodingType encodingType) {

    AnalyzeSyntaxRequest request =
        AnalyzeSyntaxRequest.newBuilder()
            .setDocument(document)
            .setEncodingType(encodingType)
            .build();
    return analyzeSyntax(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Analyzes the syntax of the text and provides sentence boundaries and tokenization along with
   * part of speech tags, dependency trees, and other properties.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnalyzeSyntaxRequest request = AnalyzeSyntaxRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   AnalyzeSyntaxResponse response = languageServiceClient.analyzeSyntax(request);
   * }
   *

   *
   * @param request The request object containing all of the parameters for the API call.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final AnalyzeSyntaxResponse analyzeSyntax(AnalyzeSyntaxRequest request) {
    return analyzeSyntaxCallable().call(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Analyzes the syntax of the text and provides sentence boundaries and tokenization along with
   * part of speech tags, dependency trees, and other properties.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnalyzeSyntaxRequest request = AnalyzeSyntaxRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   ApiFuture<AnalyzeSyntaxResponse> future = languageServiceClient.analyzeSyntaxCallable().futureCall(request);
   *   // Do something
   *   AnalyzeSyntaxResponse response = future.get();
   * }
   *

   */
  public final UnaryCallable<AnalyzeSyntaxRequest, AnalyzeSyntaxResponse> analyzeSyntaxCallable() {
    return stub.analyzeSyntaxCallable();
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Classifies a document into categories.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   ClassifyTextResponse response = languageServiceClient.classifyText(document);
   * }
   *

   *
   * @param document Input document.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final ClassifyTextResponse classifyText(Document document) {

    ClassifyTextRequest request = ClassifyTextRequest.newBuilder().setDocument(document).build();
    return classifyText(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Classifies a document into categories.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   ClassifyTextRequest request = ClassifyTextRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   ClassifyTextResponse response = languageServiceClient.classifyText(request);
   * }
   *

   *
   * @param request The request object containing all of the parameters for the API call.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final ClassifyTextResponse classifyText(ClassifyTextRequest request) {
    return classifyTextCallable().call(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * Classifies a document into categories.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   ClassifyTextRequest request = ClassifyTextRequest.newBuilder()
   *     .setDocument(document)
   *     .build();
   *   ApiFuture<ClassifyTextResponse> future = languageServiceClient.classifyTextCallable().futureCall(request);
   *   // Do something
   *   ClassifyTextResponse response = future.get();
   * }
   *

   */
  public final UnaryCallable<ClassifyTextRequest, ClassifyTextResponse> classifyTextCallable() {
    return stub.classifyTextCallable();
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * A convenience method that provides all the features that analyzeSentiment, analyzeEntities, and
   * analyzeSyntax provide in one call.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnnotateTextRequest.Features features = AnnotateTextRequest.Features.newBuilder().build();
   *   EncodingType encodingType = EncodingType.NONE;
   *   AnnotateTextResponse response = languageServiceClient.annotateText(document, features, encodingType);
   * }
   *

   *
   * @param document Input document.
   * @param features The enabled features.
   * @param encodingType The encoding type used by the API to calculate offsets.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final AnnotateTextResponse annotateText(
      Document document, AnnotateTextRequest.Features features, EncodingType encodingType) {

    AnnotateTextRequest request =
        AnnotateTextRequest.newBuilder()
            .setDocument(document)
            .setFeatures(features)
            .setEncodingType(encodingType)
            .build();
    return annotateText(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * A convenience method that provides all the features that analyzeSentiment, analyzeEntities, and
   * analyzeSyntax provide in one call.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnnotateTextRequest.Features features = AnnotateTextRequest.Features.newBuilder().build();
   *   AnnotateTextRequest request = AnnotateTextRequest.newBuilder()
   *     .setDocument(document)
   *     .setFeatures(features)
   *     .build();
   *   AnnotateTextResponse response = languageServiceClient.annotateText(request);
   * }
   *

   *
   * @param request The request object containing all of the parameters for the API call.
   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
   */
  public final AnnotateTextResponse annotateText(AnnotateTextRequest request) {
    return annotateTextCallable().call(request);
  }

  // AUTO-GENERATED DOCUMENTATION AND METHOD
  /**
   * A convenience method that provides all the features that analyzeSentiment, analyzeEntities, and
   * analyzeSyntax provide in one call.
   *
   *
Sample code:
   *
   *

   * try (LanguageServiceClient languageServiceClient = LanguageServiceClient.create()) {
   *   Document document = Document.newBuilder().build();
   *   AnnotateTextRequest.Features features = AnnotateTextRequest.Features.newBuilder().build();
   *   AnnotateTextRequest request = AnnotateTextRequest.newBuilder()
   *     .setDocument(document)
   *     .setFeatures(features)
   *     .build();
   *   ApiFuture<AnnotateTextResponse> future = languageServiceClient.annotateTextCallable().futureCall(request);
   *   // Do something
   *   AnnotateTextResponse response = future.get();
   * }
   *

   */
  public final UnaryCallable<AnnotateTextRequest, AnnotateTextResponse> annotateTextCallable() {
    return stub.annotateTextCallable();
  }

  @Override
  public final void close() {
    stub.close();
  }

  @Override
  public void shutdown() {
    stub.shutdown();
  }

  @Override
  public boolean isShutdown() {
    return stub.isShutdown();
  }

  @Override
  public boolean isTerminated() {
    return stub.isTerminated();
  }

  @Override
  public void shutdownNow() {
    stub.shutdownNow();
  }

  @Override
  public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException {
    return stub.awaitTermination(duration, unit);
  }
}


text:
package rres.knetminer.api.client;

import static uk.ac.ebi.utils.exceptions.ExceptionUtils.buildEx;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.machinezoo.noexception.Exceptions;

import rres.knetminer.api.ApiIT;
import rres.knetminer.datasource.api.config.DatasetInfo;
import rres.knetminer.datasource.api.config.ServerDatasetInfo;
import rres.knetminer.datasource.server.datasetinfo.DatasetInfoService;
import uk.ac.ebi.utils.exceptions.ExceptionUtils;
import uk.ac.ebi.utils.exceptions.UnexpectedEventException;

/**
 * A simple client for the KnetMiner APIs.
 *
 * TODO: move it to its own module.
 *
 * @author brandizi
 *

Date:

23 May 2022

 *
 */
public class KnetminerApiClient
{
	private String baseUrl;

	private Logger log = LogManager.getLogger ( this.getClass () );

	/**
	 * Options for API invocations, which affects several aspects of how the HTTP request is made
	 * and how the results are processed.
	 */
	public static class RequestOptions
	{
		private boolean failOnError = true;
		private boolean useJsonParams = true;

		public RequestOptions () {
			super ();
		}

		public static RequestOptions of () {
			return new RequestOptions ();
		}

		/**
		 * If true, an HTTP returning other than 20x will throw an exception, else the status code will be
		 * ignored. This is useful for tests and when you want to check the error details.
		 *
		 * @see ApiIT#testBadCallError() and similar methods about failure cases.
		 */
		public RequestOptions setFailOnError ( boolean failOnError )
		{
			this.failOnError = failOnError;
			return this;
		}

		/**
		 * Many of the Knetminer API calls accepts parameters in the form of JSON objects put in the
		 * request body. This is how the parameters are passed to the server if this flag is true (which
		 * is the default). When it is false, then parameters are sent in the
		 * {@link ContentType#APPLICATION_FORM_URLENCODED application/x-www-form-urlencoded} form.
		 */
		public RequestOptions setUseJsonParams ( boolean useJsonParams )
		{
			this.useJsonParams = useJsonParams;
			return this;
		}

		public boolean isFailOnError ()
		{
			return failOnError;
		}

		public boolean isUseJsonParams ()
		{
			return useJsonParams;
		}
	}

	public KnetminerApiClient ( String baseUrl )
	{
		super ();
		if ( !baseUrl.endsWith ( "/" ) ) baseUrl += "/";
		this.baseUrl = baseUrl;
	}

	/**
	 * The /countHits API
	 * @param keyword
	 * @param taxId
	 * @return
	 */
	public CountHitsApiResult countHits ( String keyword, String taxId )
	{
		return new CountHitsApiResult ( invokeApiJs ( "countHits", params ( "keyword", keyword, "taxId", taxId ) ));
	}

	/**
	 * The /genome API call.
	 *
	 * All params can be null, as long as at least one isn't
	 *
	 * @param keyword the keywords string to search
	 * @param geneList the param 'list'
	 * @param genomeRegions the param 'qtl'. Each element of this should be in the format: "1A:0:390000000:myLabel",
	 *   the method then turns it into something like "&qtl2=5A:0:590000000:", which is required by the API.
	 *   If you explicitly set the "&qtl", this is then retained.
	 * @param taxId the NCBI specie ID, must be one served by the KnetMiner instance.
	 *
	 */
	public GenomeApiResult genome ( String keyword, List<String> geneList, List<String> genomeRegions, String taxId )
	{
		// TODO: I removed the need for this from the server, but needs testing

//		if ( genomeRegions != null )
//		{
//			for ( int i = 0; i < genomeRegions.size (); i++ )
//			{
//				var reg = genomeRegions.get ( i );
//				if ( reg.startsWith ( "&" ) ) continue;
//				genomeRegions.set ( i, "&qtl=" + i + reg );
//			}
//		}

		return new GenomeApiResult ( invokeApiJs (
			"genome",
			params ( "keyword", keyword, "list", geneList, "qtl", genomeRegions, "taxId", taxId ) )
		);
	}

	/**
	 * Invokes the /countLoci API, which is used to count the no. of genes falling within a region.
	 */
	public int countLoci ( String chromosome, int start, int end, String taxId )
	{
		String lociStr = chromosome + '-' + start + '-' + end;
		JSONObject jsResult = invokeApiJs ( "countLoci", params ( "keyword", lociStr, "taxId", taxId ) );
		return jsResult.getInt ( "geneCount" );
	}

	/**
	 * Counterpart of {@link DatasetInfoService#datasetInfo() /dataset-info}.
	 */
	public DatasetInfo datasetInfo ()
	{
		// Yes, it's the server class used to serve the client output. It's because
		// ServerDatasetInfo contains the fields in DatasetInfo plus more fields that
		// are used on the server only. asDatasetInfo() yields a view on what's
		// needed here.
		return invokeApiJsMap ( "dataset-info", ServerDatasetInfo.class, null )
			.asDatasetInfo ();
	}

	/**
	 * Counterpart of {@link DatasetInfoService#datasetInfo() /dataset-info/chromosome-ids}.
	 */
	public List<String> chromosomeIds ( String taxId )
	{
		String[] taxIds = invokeApiJsMap (
			"dataset-info/chromosome-ids",
			String[].class,
			RequestOptions.of ().setUseJsonParams ( false ),
			params ( "taxId", taxId )
		);

		return Arrays.asList ( taxIds );
	}

	/**
	 * Counterpart of {@link DatasetInfoService#basemapXml()}.
	 */
	public String basemapXml ( String taxId )
	{
		return invokeApiStr (
			"dataset-info/basemap.xml", RequestOptions.of ().setUseJsonParams ( false ), params ( "taxId", taxId )
		);
	}

	/**
	 * Counterpart of {@link DatasetInfoService#sampleQueryXml()}.
	 */
	public String sampleQueryXml ()
	{
		return invokeApiStr ( "dataset-info/sample-query.xml", null );
	}

	/**
	 * Counterpart of {@link DatasetInfoService#releaseNotesHtml()}.
	 */
	public String releaseNotesHtml ()
	{
		return invokeApiStr ( "dataset-info/release-notes.html", null );
	}

	/**
	 * Counterpart of {@link DatasetInfoService#backgroundImage()}.
	 */
	public byte[] backgroundImage ()
	{
		return invokeApi (
			"dataset-info/background-image",
			Exceptions.sneak ().<InputStream, byte[]> function ( IOUtils::toByteArray ),
			RequestOptions.of ().setUseJsonParams ( false ),
			null
		);
	}

	/**
	 * Default options
	 */
	public <T> T invokeApiJsMap ( String urlOrCallName, Class<? extends T> resultClass, Map<String, Object> params  )
	{
		return invokeApiJsMap ( urlOrCallName, resultClass, RequestOptions.of (), params );
	}

	/**
	 * Assumes the request returns a JSON string and maps it to a {@code T} object, using {@link ObjectMapper} but this one uses {@link ObjectMapper}
	 *
	 */
	public <T> T invokeApiJsMap ( String urlOrCallName, Class<? extends T> resultClass, RequestOptions reqOpts, Map<String, Object> params  )
	{
		var jsmap = new ObjectMapper ();
		Function<InputStream, T> jsMapFunc = Exceptions.sneak ().function ( in -> jsmap.readValue ( in, resultClass ) );
		return invokeApi  ( urlOrCallName, jsMapFunc, reqOpts, params );
	}

	/**
	 * Default options.
	 */
	public JSONObject invokeApiJs ( String urlOrCallName, Map<String, Object> params )
	{
		return invokeApiJs ( urlOrCallName, RequestOptions.of (), params );
	}

	/**
	 * Invokes a KnetMiner API that is expected to return a JSON object as root in its result.
	 *
	 * @see #invokeApiJs(String, Function, RequestOptions, Map)
   *
	 */
	public JSONObject invokeApiJs ( String urlOrCallName, RequestOptions reqOpts, Map<String, Object> params )
	{
		return invokeApiJs ( urlOrCallName, JSONObject::new, reqOpts, params );
	}

	/**
	 * Default options.
	 */
	public JSONArray invokeApiJsArray ( String urlOrCallName, Map<String, Object> params )
	{
		return invokeApiJsArray ( urlOrCallName, RequestOptions.of (), params );
	}

	/**
	 * Invokes a KnetMiner API that is expected to return a JSON array as root in its result.
	 *
	 * @see #invokeApiJs(String, Function, RequestOptions, Map)
   *
	 */
	public JSONArray invokeApiJsArray ( String urlOrCallName, RequestOptions reqOpts, Map<String, Object> params )
	{
		return invokeApiJs ( urlOrCallName, JSONArray::new, reqOpts, params );
	}

	/**
	 * Base method for other invokeApiJsXXX methods.
	 *
	 * Calls {@link #invokeApiStr(String, RequestOptions, Map)} assuming that the request at issue returns JSON output (object
	 * or array) and uses {@code jsonSupplier} to convert it into a {@link JSONObject} or {@link JSONArray}.
	 *
	 */
	private <J> J invokeApiJs ( String urlOrCallName, Function<String, J> jsonSupplier, RequestOptions reqOpts, Map<String, Object> params )
	{
		/* DEBUG
		var s = invokeApiStr ( urlOrCallName, reqOpts, params );
		log.info ( "RETURNED JSON:\n{}", s );
		*/

		return jsonSupplier.apply (
			invokeApiStr ( urlOrCallName, reqOpts, params )
		);
	}

	/**
	 * Default options.
	 */
	public String invokeApiStr ( String urlOrCallName, Map<String, Object> params )
	{
		return invokeApiStr ( urlOrCallName, RequestOptions.of (), params );
	}

	/**
	 * A wrapper of {@link #invokeApi(String, Function, RequestOptions, Map)} and collects all its output into
	 * a string.
	 */
	public String invokeApiStr ( String urlOrCallName, RequestOptions reqOpts, Map<String, Object> params )
	{
		String outStr = invokeApi (
			urlOrCallName,
			Exceptions.sneak ().function ( in -> IOUtils.toString ( in, "UTF-8" ) ), reqOpts, params
		);
		if ( log.isDebugEnabled () ) log.debug ( "Result from <{}>:\n{}", urlOrCallName, outStr );
		return outStr;
	}

	/**
	 * Low-level invocation of a KnetMiner API.
	 *
	 * @param urlOrCallName the call name or a straight URL (if it's not a URL, it automatically prefixes {@link #getBaseUrl()}).
	 * @param reqOpts the request options.
	 * @param params the request parameters.
	 * @param outConverter a converter that turns the {@link InputStream} coming from the request output into an instance of T.
	 * @return the API output, in the form of an object of type T
	 */
	private <T> T invokeApi (
		String urlOrCallName, Function<InputStream, T> outConverter, RequestOptions reqOpts, Map<String, Object> params
	)
	{
		var nrmUrlOrCallName = urlOrCallName.toLowerCase ();
		String url = nrmUrlOrCallName.startsWith ( "http://" ) || nrmUrlOrCallName.startsWith ( "https://" )
			? urlOrCallName
			: getApiUrl ( urlOrCallName );

		try
		{
			HttpPost post = new HttpPost ( url );

			if ( params == null ) params = new HashMap<> ();

			HttpEntity payload = null;

			if ( reqOpts.isUseJsonParams () )
			{
				var js = new JSONObject ( params );
				// This ContentType is UTF-8
				payload = new StringEntity ( js.toString (), ContentType.APPLICATION_JSON );
			}
			else
			{
				// Else, let's use x-www-form-urlencoded
				//
				List<NameValuePair> nvps = params.entrySet ()
				.stream ()
				.filter ( e -> e.getValue () != null )
				.map ( e -> new BasicNameValuePair ( e.getKey (), e.getValue ().toString () ) )
				.collect ( Collectors.toUnmodifiableList () );

				payload = new UrlEncodedFormEntity ( nvps, StandardCharsets.UTF_8 );
			}

			post.setEntity ( payload );

			HttpClient client = HttpClientBuilder.create ().build ();

			HttpResponse response = client.execute ( post );
			int httpCode = response.getStatusLine ().getStatusCode ();
			if ( httpCode != 200 )
			{
				// TODO: yield an exception that carries the exception response
				if ( reqOpts.isFailOnError () ) ExceptionUtils.throwEx (
					HttpException.class, "Http response code %s is not 200", Integer.valueOf ( httpCode )
				);
				log.warn ( "Return code for {} is {}", url, httpCode );
			}

			InputStream in = response.getEntity ().getContent ();
			return outConverter.apply ( in );
		}
		catch ( IOException | HttpException ex )
		{
			throw buildEx (
				UnexpectedEventException.class,
				"Error while invoking <%s>: %s",
				url,
				ex.getMessage ()
			);
		}
	}

	/**
	 * Prepares API params starting from an array that alternate key/value pairs in its values.
	 */
	public static Map<String, Object> params ( Object ...paramPairs )
	{
		Map<String, Object> result = new HashMap<> ();
		for ( int i = 0; i < paramPairs.length; i++ )
		{
			String key = (String) paramPairs [ i ];
			Object value = paramPairs [ ++ i ];
			if ( value == null ) continue;
			result.put ( key, value );
		}

		return result;
	}

	/**
	 * Includes the data source name, eg, "http://localhost:8080/ws/aratiny/"
	 */
	public String getBaseUrl ()
	{
		return baseUrl;
	}

	/**
	 * Builds the URL of a KnetMiner API invocation, composing path with
	 * {@link #getBaseUrl()}.
	 *
	 * If path is null, returns the base URL.
	 */
	public String getApiUrl ( String path )
	{
		return getBaseUrl () + Optional.ofNullable ( path ).orElse ( "" );
	}

}


text:
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
   <title>Larbin : Parcourir le web, telle est ma passion...</title>

Larbin

Web crawler généraliste

Présentation

Larbin est un web crawler (synonyme de (web) robot, spider, scooter,
aspirateur...). Il est dimensionné pour ramener une grande quantité de
pages web pour remplir la base de données d'un moteur de recherche. A
condition d'avoir un réseau suffisament rapide, Larbin est censé être
capable de ramener plus de 100 millions de pages sur un PC classique.

Larbin est juste un crawler. Il ne contient aucun outil pour
indexer vos données.

Larbin a été initialement développé pour le projet XYLEME de
l'équipe VERSO de l'INRIA. Son but était de récupérer toutes les pages
xml présentes sur le web pour approvisionner la base de données d'un
moteur de recherche tourné vers le xml. Du fait de cette conception,
Larbin est très généraliste.

Comment utiliser Larbin

Comment éduquer votre Larbin

Disponiblité (Télécharger)

Larbin est à la disposition de tout le monde. Il est sous license
GPL. Les critiques (constructives) sont les bienvenues !

Malgré tout, un tel programme n'est pas fait pour être utilisé par
n'importe qui et n'importe comment : Larbin n'est pas orienté vers le
grand public (wget ou ht://dig sont sans doute plus appropriés dans
beaucoup de cas).

Quoi qu'il en soit, je ne suis aucunement responsable des dommages
causés par l'utilisation de Larbin.

État actuel

Le programme actuel est capable de récupérer 5.000.000 de
pages par jour sur un PC standard (la vitesse dépend en fait
principalement de votre réseau).

Larbin fonctionne sous Linux et utilise les librairies standards,
plus la librairie adns (elle est
incluse dans le logiciel). Le programme est très faiblement
multithreadé et privilégie l'utilisation de fonctions non bloquantes
(select et adns) pour des raisons d'efficacité.

L'intérêt de Larbin par rapport à wget ou ht://dig est qu'il est
beaucoup plus rapide (car il peut gérer plusieurs centaines de
connexions en parallèle) et qu'il est très généraliste (en particulier
très spécialisable).

A faire

De nombreuses fonctionnalités peuvent être ajoutées. N'hésitez pas à
me contacter (sebastien@ailleret.com)
si vous avez besoin d'une nouvelle fonction. Voici quelques
améliorations en vue :

Faire tourner le programme en parallèle de façon coopérative sur
plusieurs ordinateurs à la fois.

Assurer la compatibilité avec Solaris.

Voici quelques idées de choses faisables avec Larbin :

Crawler pour un moteur de recherche classique

Crawler pour un moteur de recherche spécialisé. ex :
recherche des pages xml, d'images, de mp3...

Statistiques sur le web (sur serveurs web ou contenu des pages)

sebastien@ailleret.com

 home page


text:
package com.github.jankroken.commandline.happy;

import com.github.jankroken.commandline.CommandLineParser;
import com.github.jankroken.commandline.OptionStyle;
import org.junit.Test;

import java.util.List;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.hasItems;

public class BasicParserTest {

    @Test
    public void testSimpleConfiguration() throws Exception {
        String[] args = new String[]{"-f", "hello.txt", "-v"};
        SimpleConfiguration config = CommandLineParser.parse(SimpleConfiguration.class, args, OptionStyle.SIMPLE);
        assertThat(config.getFilename(), is("hello.txt"));
        assertThat(config.getVerbose(), is(true));
    }

    @Test
    public void testMultipleArgsConfiguration() throws Exception {
        String[] args = new String[]{"-files", "hello.txt", "world.txt", "bye.txt", "-logfile", "hello.log"};
        MultipleArgsConfiguration config = CommandLineParser.parse(MultipleArgsConfiguration.class, args, OptionStyle.SIMPLE);
        assertThat(config.getFiles(), hasItems("hello.txt", "world.txt", "bye.txt"));
        assertThat(config.getLogfile(), is("hello.log"));
    }

    @Test
    public void testDelimiterConfiguration() throws Exception {
        String[] args = new String[]{"-exec", "ls", "-l", "*.txt", ";", "-logfile", "hello.log"};
        DelimiterConfiguration config = CommandLineParser.parse(DelimiterConfiguration.class, args, OptionStyle.SIMPLE);
        assertThat(config.getCommand(), hasItems("ls", "-l", "*.txt"));
        assertThat(config.getLogfile(), is("hello.log"));
    }

    @Test
    public void testMultipleConfiguration() throws Exception {
        String[] args = new String[]{"-verbose", "-file", "hello.txt", "-file", "world.txt"};
        MultipleConfiguration config = CommandLineParser.parse(MultipleConfiguration.class, args, OptionStyle.SIMPLE);
        assertThat(config.getFiles(), hasItems("hello.txt", "world.txt"));
        assertThat(config.getVerbose(), is(true));
    }

    @Test
    public void testSubConfiguration() throws Exception {
        String[] args = new String[]{"-verbose", "-album", "-name", "Caustic Grip", "-artist", "Front Line Assembly", "-year", "1990", "-available", "-logfile", "hello.log"};
        SimpleSuperConfiguration config = CommandLineParser.parse(SimpleSuperConfiguration.class, args, OptionStyle.SIMPLE);
        AlbumConfiguration album = config.getAlbum();
        assertThat(config.getLogfile(), is("hello.log"));
        assertThat(config.getVerbose(), is(true));
        assertThat(album.getName(), is("Caustic Grip"));
        assertThat(album.getArtist(), is("Front Line Assembly"));
        assertThat(album.getYear(), is("1990"));
        assertThat(album.isAvailable(), is(true));
    }

    @Test
    public void testMultipleSubConfiguration() throws Exception {
        String[] args = new String[]{"-verbose",
                "-album", "-name", "Caustic Grip", "-artist", "Front Line Assembly", "-year", "1990", "-available",
                "-album", "-name", "Scintilla", "-artist", "Stendeck", "-year", "2011", "-available",
                "-logfile", "hello.log"};
        MultipleSubconfigsConfiguration config = CommandLineParser.parse(MultipleSubconfigsConfiguration.class, args, OptionStyle.SIMPLE);
        boolean verbose = config.getVerbose();
        List<AlbumConfiguration> albums = config.getAlbums();
        assertThat(albums.size(), is(2));
        AlbumConfiguration causticGrip = albums.get(0);
        AlbumConfiguration scintilla = albums.get(1);
        assertThat(causticGrip.getName(), is("Caustic Grip"));
        assertThat(causticGrip.getArtist(), is("Front Line Assembly"));
        assertThat(causticGrip.getYear(), is("1990"));
        assertThat(causticGrip.isAvailable(), is(true));
        assertThat(scintilla.getName(), is("Scintilla"));
        assertThat(scintilla.getArtist(), is("Stendeck"));
        assertThat(scintilla.getYear(), is("2011"));
        assertThat(scintilla.isAvailable(), is(true));

        assertThat(config.getLogfile(), is("hello.log"));
        assertThat(verbose, is(true));
    }

    @Test
    public void testLooseArguments() throws Exception {
        String[] args = new String[]{"-verbose", "zombies", "ate", "my", "-logfile", "hello.log", "raptors"};
        LooseArgsConfiguration config = CommandLineParser.parse(LooseArgsConfiguration.class, args, OptionStyle.SIMPLE);
        assertThat(config.getVerbose(), is(true));
        assertThat(config.getLogfile(), is("hello.log"));
        assertThat(config.getArgs(), hasItems("zombies", "ate", "my", "raptors"));
    }

    @Test
    public void testArgumentEscape() throws Exception {
        String[] args = new String[]{"-verbose", "-logfile", "hello.log", "--", "-zombies", "-ate", "-my", "--", "-raptors"};
        LooseArgsConfiguration config = CommandLineParser.parse(LooseArgsConfiguration.class, args, OptionStyle.SIMPLE);
        assertThat(config.getVerbose(), is(true));
        assertThat(config.getLogfile(), is("hello.log"));
        assertThat(config.getArgs(), hasItems("-zombies", "-ate", "-my", "--", "-raptors"));
    }

}


text:
import { Pipe, PipeTransform } from '@angular/core';

import { ItemListing } from './../models/item-listing.model';

@Pipe({
    name: 'priceGreaterThen'
})
export class PriceGreaterThenPipe implements PipeTransform {

    transform(array: ItemListing[], priceGreaterThen: Number): ItemListing[] {
        if (!priceGreaterThen) {
            return array;
        }

        return array.filter(x => x.price >= priceGreaterThen);
    }
}